[svn r58] Fixed cond expression resulting in a non-basic type.

Fixed identity expression for dynamic arrays.
Revamped the system to keep track of lvalues and rvalues and their relations.
Typedef declaration now generate the custom typeinfo.
Other bugfixes.
This commit is contained in:
Tomas Lindquist Olsen
2007-10-24 01:37:34 +02:00
parent b72a4fa645
commit 039bc0880d
17 changed files with 370 additions and 97 deletions

View File

@@ -40,6 +40,7 @@ namespace llvm
class Type;
class Value;
class Constant;
class ConstantStruct;
}
struct AggregateDeclaration : ScopeDsymbol
@@ -98,6 +99,7 @@ struct AggregateDeclaration : ScopeDsymbol
bool llvmInProgress;
llvm::Type* llvmType;
llvm::Value* llvmVtbl;
llvm::ConstantStruct* llvmConstVtbl;
llvm::Constant* llvmInitZ;
virtual void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector

View File

@@ -47,6 +47,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
llvmType = NULL;
llvmVtbl = NULL;
llvmConstVtbl = NULL;
llvmInitZ = NULL;
llvmInProgress = false;
}

View File

@@ -100,6 +100,7 @@ void LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
}
else
{
Logger::cout() << "array assignment type dont match: " << *dst->getType() << '\n' << *src->getType() << '\n';
if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0)))
{
Logger::cout() << "invalid: " << *src << '\n';
@@ -109,7 +110,7 @@ void LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
llvm::Value* dstlen = LLVM_DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
llvm::Value* srclen = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false);
llvm::Value* srclen = LLVM_DtoConstSize_t(arrty->getNumElements());
new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
llvm::Value* dstptr = LLVM_DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
@@ -551,3 +552,25 @@ llvm::Value* LLVM_DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty,
args.push_back(llvm::ConstantInt::get(LLVM_DtoSize_t(), gTargetData->getTypeSize(newelemty), false));
return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r)
{
assert(l->getType() == r->getType());
llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
llvm::Value* ll = gIR->ir->CreateLoad(LLVM_DtoGEPi(l, 0,0, "tmp"),"tmp");
llvm::Value* rl = gIR->ir->CreateLoad(LLVM_DtoGEPi(r, 0,0, "tmp"),"tmp");
llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
llvm::Value* lp = gIR->ir->CreateLoad(LLVM_DtoGEPi(l, 0,1, "tmp"),"tmp");
llvm::Value* rp = gIR->ir->CreateLoad(LLVM_DtoGEPi(r, 0,1, "tmp"),"tmp");
llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
if (op == TOKnotidentity)
return gIR->ir->CreateNot(b,"tmp");
else
return b;
}

View File

@@ -22,7 +22,9 @@ void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp);
void LLVM_DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src);
llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
llvm::Value* LLVM_DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
llvm::Value* LLVM_DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r);
llvm::Value* LLVM_DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty);

View File

@@ -35,7 +35,6 @@ IRState::IRState()
{
dmodule = 0;
module = 0;
inLvalue = false;
emitMain = false;
mainFunc = 0;
ir.state = this;
@@ -71,10 +70,9 @@ IRStruct& IRState::topstruct()
return structs.back();
}
llvm::Value* IRState::toplval()
IRExp* IRState::topexp()
{
assert(!lvals.empty() && "Lval vector is empty!");
return lvals.back();
return exps.empty() ? NULL : &exps.back();
}
IRScope& IRState::scope()
@@ -153,3 +151,18 @@ IRFunction::IRFunction(FuncDeclaration* fd)
func = NULL;
allocapoint = NULL;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRExp::IRExp()
{
e1 = e2 = NULL;
v = NULL;
}
IRExp::IRExp(Expression* l, Expression* r, llvm::Value* val)
{
e1 = l;
e2 = r;
v = val;
}

View File

@@ -88,6 +88,15 @@ struct IRBuilderHelper
LLVMBuilder* operator->();
};
struct IRExp
{
Expression* e1;
Expression* e2;
llvm::Value* v;
IRExp();
IRExp(Expression* l, Expression* r, llvm::Value* val);
};
// represents the module
struct IRState
{
@@ -119,11 +128,10 @@ struct IRState
bool emitMain;
llvm::Function* mainFunc;
// L-values
bool inLvalue;
typedef std::vector<llvm::Value*> LvalVec;
LvalVec lvals;
llvm::Value* toplval();
// expression l/r value handling
typedef std::vector<IRExp> ExpVec;
ExpVec exps;
IRExp* topexp();
// basic block scopes
std::vector<IRScope> scopes;
@@ -141,7 +149,7 @@ struct IRState
// might be a better way but it works. problem is I only get a
// VarDeclaration for __dollar, but I can't see how to get the
// array pointer from this :(
LvalVec arrays;
std::vector<llvm::Value*> arrays;
// builder helper
IRBuilderHelper ir;

View File

@@ -51,10 +51,10 @@ void ReturnStatement::toIR(IRState* p)
Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars());
LOG_SCOPE;
IRFunction::FinallyVec& fin = p->func().finallys;
if (exp)
{
Logger::println("return type is: %s", exp->type->toChars());
Type* exptype = LLVM_DtoDType(exp->type);
TY expty = exptype->ty;
if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
@@ -63,28 +63,36 @@ void ReturnStatement::toIR(IRState* p)
TypeFunction* f = p->topfunctype();
assert(f->llvmRetInPtr && f->llvmRetArg);
p->lvals.push_back(f->llvmRetArg);
p->exps.push_back(IRExp(NULL,exp,f->llvmRetArg));
elem* e = exp->toElem(p);
p->lvals.pop_back();
p->exps.pop_back();
if (expty == Tstruct) {
if (!e->inplace) {
assert(e->mem);
LLVM_DtoStructCopy(f->llvmRetArg,e->mem);
}
if (!e->inplace)
LLVM_DtoStructCopy(f->llvmRetArg,e->getValue());
}
else if (expty == Tdelegate) {
LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem);
if (!e->inplace)
LLVM_DtoDelegateCopy(f->llvmRetArg,e->getValue());
}
else if (expty == Tarray) {
if (e->type == elem::SLICE) {
assert(e->mem);
LLVM_DtoSetArray(f->llvmRetArg,e->arg,e->mem);
}
// else the return value is a variable and should already have been assigned by now
else if (!e->inplace) {
if (e->type == elem::NUL) {
LLVM_DtoNullArray(f->llvmRetArg);
}
else {
LLVM_DtoArrayAssign(f->llvmRetArg, e->getValue());
}
}
}
else
assert(0);
IRFunction::FinallyVec& fin = p->func().finallys;
if (fin.empty())
new llvm::ReturnInst(p->scopebb());
else {
@@ -98,6 +106,8 @@ void ReturnStatement::toIR(IRState* p)
llvm::Value* v = e->getValue();
delete e;
Logger::cout() << "return value is '" <<*v << "'\n";
IRFunction::FinallyVec& fin = p->func().finallys;
if (fin.empty()) {
new llvm::ReturnInst(v, p->scopebb());
}
@@ -113,6 +123,7 @@ void ReturnStatement::toIR(IRState* p)
else
{
if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
IRFunction::FinallyVec& fin = p->func().finallys;
if (fin.empty()) {
new llvm::ReturnInst(p->scopebb());
}

View File

@@ -377,19 +377,16 @@ elem* StringExp::toElem(IRState* p)
if (dtype->ty == Tarray) {
llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false);
if (p->lvals.empty() || !p->toplval()) {
if (!p->topexp() || p->topexp()->e2 != this) {
llvm::Value* tmpmem = new llvm::AllocaInst(LLVM_DtoType(dtype),"tmp",p->topallocapoint());
LLVM_DtoSetArray(tmpmem, clen, arrptr);
e->mem = tmpmem;
}
else if (llvm::Value* arr = p->toplval()) {
if (llvm::isa<llvm::GlobalVariable>(arr)) {
e->val = LLVM_DtoConstantSlice(clen, arrptr);
}
else {
LLVM_DtoSetArray(arr, clen, arrptr);
e->inplace = true;
}
else if (p->topexp()->e2 == this) {
llvm::Value* arr = p->topexp()->v;
assert(arr);
LLVM_DtoSetArray(arr, clen, arrptr);
e->inplace = true;
}
else
assert(0);
@@ -453,14 +450,13 @@ elem* AssignExp::toElem(IRState* p)
Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type->toChars());
LOG_SCOPE;
assert(e1 && e2);
p->inLvalue = true;
elem* l = e1->toElem(p);
p->inLvalue = false;
p->exps.push_back(IRExp(e1,e2,NULL));
p->lvals.push_back(l->mem);
elem* r = e2->toElem(p);
p->lvals.pop_back();
elem* l = e1->toElem(p);
p->topexp()->v = l->mem;
elem* r = e2->toElem(p);
p->exps.pop_back();
if (l->type == elem::ARRAYLEN)
{
@@ -1066,11 +1062,14 @@ elem* CallExp::toElem(IRState* p)
Logger::println("hidden struct return");
IRExp* topexp = p->topexp();
// hidden struct return arguments
if (retinptr) {
if (!p->lvals.empty() && p->toplval()) {
assert(llvm::isa<llvm::StructType>(p->toplval()->getType()->getContainedType(0)));
llargs[j] = p->toplval();
if (topexp && topexp->e2 == this) {
assert(topexp->v);
assert(llvm::isa<llvm::StructType>(topexp->v->getType()->getContainedType(0)));
llargs[j] = topexp->v;
if (LLVM_DtoIsPassedByRef(tf->next)) {
e->inplace = true;
}
@@ -1534,17 +1533,19 @@ elem* StructLiteralExp::toElem(IRState* p)
llvm::Value* sptr = 0;
// if there is no lval, this is probably a temporary struct literal. correct?
if (p->lvals.empty() || !p->toplval())
if (!p->topexp() || p->topexp()->e2 != this)
{
sptr = new llvm::AllocaInst(LLVM_DtoType(type),"tmpstructliteral",p->topallocapoint());
e->mem = sptr;
e->type = elem::VAR;
}
// already has memory
else
else if (p->topexp()->e2 == this)
{
sptr = p->toplval();
sptr = p->topexp()->v;
}
else
assert(0);
assert(sptr);
@@ -1558,9 +1559,9 @@ elem* StructLiteralExp::toElem(IRState* p)
Expression* vx = (Expression*)elements->data[i];
if (vx != 0) {
p->lvals.push_back(arrptr);
p->exps.push_back(IRExp(NULL,vx,arrptr));
elem* ve = vx->toElem(p);
p->lvals.pop_back();
p->exps.pop_back();
if (!ve->inplace) {
llvm::Value* val = ve->getValue();
@@ -2042,7 +2043,8 @@ elem* NewExp::toElem(IRState* p)
if (arguments->dim == 1) {
elem* sz = ((Expression*)arguments->data[0])->toElem(p);
llvm::Value* dimval = sz->getValue();
LLVM_DtoNewDynArray(p->toplval(), dimval, ntype->next);
assert(p->topexp() && p->topexp()->e2 == this && p->topexp()->v);
LLVM_DtoNewDynArray(p->topexp()->v, dimval, ntype->next);
delete sz;
}
else {
@@ -2161,7 +2163,7 @@ elem* ArrayLengthExp::toElem(IRState* p)
elem* e = new elem;
elem* u = e1->toElem(p);
if (p->inLvalue)
if (p->topexp() && p->topexp()->e1 == this)
{
e->mem = u->mem;
e->type = elem::ARRAYLEN;
@@ -2372,26 +2374,27 @@ elem* DelegateExp::toElem(IRState* p)
elem* e = new elem;
elem* u = e1->toElem(p);
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
const llvm::Type* int8ptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
llvm::Value* lval = p->toplval();
assert(p->topexp() && p->topexp()->e2 == this && p->topexp()->v);
llvm::Value* lval = p->topexp()->v;
llvm::Value* context = LLVM_DtoGEP(lval,zero,zero,"tmp",p->scopebb());
llvm::Value* castcontext = new llvm::BitCastInst(u->getValue(),int8ptrty,"tmp",p->scopebb());
new llvm::StoreInst(castcontext, context, p->scopebb());
llvm::Value* fptr = LLVM_DtoGEP(lval,zero,one,"tmp",p->scopebb());
assert(func->llvmValue);
llvm::Value* castfptr = new llvm::BitCastInst(func->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb());
new llvm::StoreInst(castfptr, fptr, p->scopebb());
e->inplace = true;
delete u;
return e;
}
@@ -2415,8 +2418,16 @@ elem* IdentityExp::toElem(IRState* p)
else
r = v->getValue();
llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
Type* t1 = LLVM_DtoDType(e1->type);
if (t1->ty == Tarray) {
assert(l->getType() == r->getType());
e->val = LLVM_DtoDynArrayIs(op,l,r);
}
else {
llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
}
e->type = elem::VAL;
delete u;
@@ -2445,7 +2456,8 @@ elem* CondExp::toElem(IRState* p)
Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
const llvm::Type* resty = LLVM_DtoType(type);
Type* dtype = LLVM_DtoDType(type);
const llvm::Type* resty = LLVM_DtoType(dtype);
// allocate a temporary for the final result. failed to come up with a better way :/
llvm::BasicBlock* entryblock = &p->topfunc()->front();
@@ -2463,21 +2475,21 @@ elem* CondExp::toElem(IRState* p)
p->scope() = IRScope(condtrue, condfalse);
elem* u = e1->toElem(p);
new llvm::StoreInst(u->getValue(),resval,p->scopebb());
LLVM_DtoAssign(dtype, resval, u->getValue());
new llvm::BranchInst(condend,p->scopebb());
delete u;
p->scope() = IRScope(condfalse, condend);
elem* v = e2->toElem(p);
new llvm::StoreInst(v->getValue(),resval,p->scopebb());
LLVM_DtoAssign(dtype, resval, v->getValue());
new llvm::BranchInst(condend,p->scopebb());
delete v;
p->scope() = IRScope(condend, oldend);
elem* e = new elem;
e->val = new llvm::LoadInst(resval,"tmp",p->scopebb());
e->type = elem::VAL;
e->mem = resval;
e->type = elem::VAR;
return e;
}
@@ -2589,12 +2601,13 @@ elem* ArrayLiteralExp::toElem(IRState* p)
Logger::cout() << "array literal has llvm type: " << *t << '\n';
llvm::Value* mem = 0;
if (p->lvals.empty() || !p->toplval()) {
if (!p->topexp() || p->topexp()->e2 != this) {
assert(LLVM_DtoDType(type)->ty == Tsarray);
mem = new llvm::AllocaInst(t,"tmparrayliteral",p->topallocapoint());
}
else {
mem = p->toplval();
else if (p->topexp()->e2 == this) {
mem = p->topexp()->v;
assert(mem);
if (!llvm::isa<llvm::PointerType>(mem->getType()) ||
!llvm::isa<llvm::ArrayType>(mem->getType()->getContainedType(0)))
{
@@ -2602,6 +2615,8 @@ elem* ArrayLiteralExp::toElem(IRState* p)
fatal();
}
}
else
assert(0);
for (unsigned i=0; i<elements->dim; ++i)
{
@@ -2657,14 +2672,17 @@ elem* FuncExp::toElem(IRState* p)
fd->toObjFile();
llvm::Value* lval = NULL;
if (p->lvals.empty() || p->toplval() == NULL) {
if (!p->topexp() || p->topexp()->e2 != this) {
const llvm::Type* dgty = LLVM_DtoType(type);
Logger::cout() << "delegate without explicit storage:" << '\n' << *dgty << '\n';
lval = new llvm::AllocaInst(dgty,"dgstorage",p->topallocapoint());
}
else {
lval = p->toplval();
else if (p->topexp()->e2 == this) {
lval = p->topexp()->v;
assert(lval);
}
else
assert(0);
elem* e = new elem;

View File

@@ -1100,14 +1100,14 @@ llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expr
{
llvm::Value* retval = 0;
bool haslvals = !gIR->lvals.empty();
bool haslvals = !gIR->exps.empty();
if (haslvals)
gIR->lvals.push_back(NULL);
gIR->exps.push_back(IRExp(NULL,NULL,NULL));
elem* arg = argexp->toElem(gIR);
if (haslvals)
gIR->lvals.pop_back();
gIR->exps.pop_back();
if (arg->inplace) {
assert(arg->mem != 0);
@@ -1254,3 +1254,29 @@ void LLVM_DtoAssign(Type* t, llvm::Value* lhs, llvm::Value* rhs)
gIR->ir->CreateStore(rhs, lhs);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::ConstantInt* LLVM_DtoConstSize_t(size_t i)
{
return llvm::ConstantInt::get(LLVM_DtoSize_t(), i, false);
}
llvm::ConstantInt* LLVM_DtoConstUint(unsigned i)
{
return llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Constant* LLVM_DtoConstString(const char* str)
{
std::string s(str);
llvm::Constant* init = llvm::ConstantArray::get(s, true);
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module);
llvm::Constant* idxs[2] = { LLVM_DtoConstUint(0), LLVM_DtoConstUint(0) };
return LLVM_DtoConstantSlice(
LLVM_DtoConstSize_t(s.length()),
llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2)
);
}

View File

@@ -59,4 +59,8 @@ llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd);
void LLVM_DtoAssign(Type* lhsType, llvm::Value* lhs, llvm::Value* rhs);
llvm::ConstantInt* LLVM_DtoConstSize_t(size_t);
llvm::ConstantInt* LLVM_DtoConstUint(unsigned i);
llvm::Constant* LLVM_DtoConstString(const char*);
#include "enums.h"

View File

@@ -363,10 +363,10 @@ void ClassDeclaration::toObjFile()
ts->llvmType = structtype;
llvmType = structtype;
bool define_vtable = false;
bool needs_definition = false;
if (parent->isModule()) {
gIR->module->addTypeName(mangle(),ts->llvmType);
define_vtable = (getModule() == gIR->dmodule);
needs_definition = (getModule() == gIR->dmodule);
}
else {
assert(0 && "class parent is not a module");
@@ -418,9 +418,9 @@ void ClassDeclaration::toObjFile()
gIR->module->addTypeName(styname, svtbl_ty);
svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
if (define_vtable) {
svtblVar->setInitializer(llvm::ConstantStruct::get(svtbl_ty, sinits));
}
llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
if (needs_definition)
svtblVar->setInitializer(llvmConstVtbl);
llvmVtbl = svtblVar;
}
@@ -441,25 +441,25 @@ void ClassDeclaration::toObjFile()
assert(svtblVar != 0);
gIR->topstruct().inits[0] = svtblVar;
_init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
llvmInitZ = _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
assert(_init);
std::string initname("_D");
initname.append(mangle());
initname.append("6__initZ");
//Logger::cout() << *_init << '\n';
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module);
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, NULL, initname, gIR->module);
ts->llvmInit = initvar;
if (define_vtable) {
initvar->setInitializer(_init);
}
// generate member function definitions
gIR->topstruct().queueFuncs = false;
IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
size_t n = mfs.size();
for (size_t i=0; i<n; ++i) {
mfs[i]->toObjFile();
if (needs_definition) {
initvar->setInitializer(_init);
// generate member functions
gIR->topstruct().queueFuncs = false;
IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
size_t n = mfs.size();
for (size_t i=0; i<n; ++i) {
mfs[i]->toObjFile();
}
}
gIR->classes.pop_back();
@@ -525,9 +525,7 @@ void VarDeclaration::toObjFile()
// if extern don't emit initializer
if (!(storage_class & STCextern))
{
gIR->lvals.push_back(gvar);
_init = LLVM_DtoConstInitializer(t, init);
gIR->lvals.pop_back();
//Logger::cout() << "initializer: " << *_init << '\n';
if (_type != _init->getType()) {
@@ -628,7 +626,8 @@ void TypedefDeclaration::toObjFile()
LOG_SCOPE;
// generate typeinfo
type->getTypeInfo(NULL);
if (!type->builtinTypeInfo())
type->getTypeInfo(NULL);
}
/* ================================================================== */

View File

@@ -30,6 +30,8 @@
#include "gen/irstate.h"
#include "gen/logger.h"
#include "gen/runtime.h"
#include "gen/tollvm.h"
#include "gen/arrays.h"
/*******************************************
* Get a canonicalized form of the TypeInfo for use with the internal
@@ -242,10 +244,20 @@ void TypeInfoDeclaration::toObjFile()
if (llvmTouched) return;
else llvmTouched = true;
Logger::println("Getting typeinfo var: %s", mangle());
llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
assert(llvmValue);
Logger::cout() << "Got:" << '\n' << *llvmValue << '\n';
Logger::println("typeinfo mangle: %s", mangle());
if (tinfo->builtinTypeInfo()) {
// this is a declaration of a builtin __initZ var
llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
assert(llvmValue);
Logger::cout() << "Got typeinfo var:" << '\n' << *llvmValue << '\n';
}
else {
toDt(NULL);
// this is a specialized typeinfo
//std::vector<const llvm::Type*> stypes;
//stypes.push_back(
}
}
/* ========================================================================= */
@@ -257,7 +269,89 @@ void TypeInfoDeclaration::toDt(dt_t **pdt)
void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
{
assert(0 && "TypeInfoTypedefDeclaration");
Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars());
LOG_SCOPE;
ClassDeclaration* base = Type::typeinfotypedef;
base->toObjFile();
llvm::Constant* initZ = base->llvmInitZ;
assert(initZ);
const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
std::vector<llvm::Constant*> sinits;
sinits.push_back(initZ->getOperand(0));
assert(tinfo->ty == Ttypedef);
TypeTypedef *tc = (TypeTypedef *)tinfo;
TypedefDeclaration *sd = tc->sym;
// TypeInfo base
//const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
//sinits.push_back(llvm::ConstantPointerNull::get(basept));
Logger::println("generating base typeinfo");
//sd->basetype = sd->basetype->merge();
sd->basetype->getTypeInfo(NULL); // generate vtinfo
assert(sd->basetype->vtinfo);
if (!sd->basetype->vtinfo->llvmValue)
sd->basetype->vtinfo->toObjFile();
assert(llvm::isa<llvm::Constant>(sd->basetype->vtinfo->llvmValue));
llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->basetype->vtinfo->llvmValue);
castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
sinits.push_back(castbase);
// char[] name
char *name = sd->toPrettyChars();
sinits.push_back(LLVM_DtoConstString(name));
assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
// void[] init
//const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
//sinits.push_back(LLVM_DtoConstantSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
sinits.push_back(initZ->getOperand(3));
// create the symbol
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
llvmValue = gvar;
/*
dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef
dtdword(pdt, 0); // monitor
assert(tinfo->ty == Ttypedef);
TypeTypedef *tc = (TypeTypedef *)tinfo;
TypedefDeclaration *sd = tc->sym;
//printf("basetype = %s\n", sd->basetype->toChars());
// Put out:
// TypeInfo base;
// char[] name;
// void[] m_init;
sd->basetype = sd->basetype->merge();
sd->basetype->getTypeInfo(NULL); // generate vtinfo
assert(sd->basetype->vtinfo);
dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for basetype
char *name = sd->toPrettyChars();
size_t namelen = strlen(name);
dtdword(pdt, namelen);
dtabytes(pdt, TYnptr, 0, namelen + 1, name);
// void[] init;
if (tinfo->isZeroInit() || !sd->init)
{ // 0 initializer, or the same as the base type
dtdword(pdt, 0); // init.length
dtdword(pdt, 0); // init.ptr
}
else
{
dtdword(pdt, sd->type->size()); // init.length
dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr
*/
}
void TypeInfoEnumDeclaration::toDt(dt_t **pdt)

View File

@@ -433,8 +433,6 @@ class TypeInfo
OffsetTypeInfo[] offTi() { return null; }
}
/+
class TypeInfo_Typedef : TypeInfo
{
char[] toString() { return name; }
@@ -455,7 +453,7 @@ class TypeInfo_Typedef : TypeInfo
size_t tsize() { return base.tsize(); }
void swap(void *p1, void *p2) { return base.swap(p1, p2); }
TypeInfo next() { return base.next(); }
TypeInfo next() { return base; }
uint flags() { return base.flags(); }
void[] init() { return m_init.length ? m_init : base.init(); }
@@ -468,6 +466,8 @@ class TypeInfo_Enum : TypeInfo_Typedef
{
}
/+
class TypeInfo_Pointer : TypeInfo
{
char[] toString() { return m_next.toString() ~ "*"; }

14
test/bug32.d Normal file
View File

@@ -0,0 +1,14 @@
module bug32;
struct S
{
char[] getName() { return name; }
char[] name;
}
void main()
{
S s = S("Kyle");
char[] name = s.name;
printf("%.*s\n", name.length, name.ptr);
}

33
test/bug33.d Normal file
View File

@@ -0,0 +1,33 @@
module bug33;
extern(C) int memcmp(void*,void*,size_t);
private int string_cmp(char[] s1, char[] s2)
{
auto len = s1.length;
if (s2.length < len)
len = s2.length;
int result = memcmp(s1.ptr, s2.ptr, len);
if (result == 0)
result = cast(int)(cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length);
return result;
}
struct S
{
char[] toString()
{
return "S";
}
}
int func()
{
S a,b;
return string_cmp(a.toString(),b.toString());
}
void main()
{
assert(func() == 0);
}

12
test/condexp1.d Normal file
View File

@@ -0,0 +1,12 @@
module condexp1;
void main()
{
char[] a = "hello";
char[] b = "world";
int i = 42;
{
char[] c = i > 50 ? b : a;
assert(c is a);
}
}

13
test/typeinfo3.d Normal file
View File

@@ -0,0 +1,13 @@
module typeinfo3;
typedef int int_t;
void main()
{
int_t i;
auto ti = typeid(typeof(i));
printf("%s\n",ti.toString.ptr);
assert(ti.toString() == "typeinfo3.int_t");
assert(ti.next !is null);
assert(ti.next.toString() == "int");
}