Mercurial > projects > ldc
diff gen/toir.cpp @ 797:340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Fixed function literals in static initializers.
Changed alignment of delegates from 2*PTRSIZE to just PTRSIZE.
Changed errors to go to stderr instead of stdout.
Fairly major rewriting of struct/union/class handling, STILL A BIT BUGGY !!!
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sat, 29 Nov 2008 21:25:43 +0100 |
parents | 4adf0f742896 |
children | 28ce72c60a21 |
line wrap: on
line diff
--- a/gen/toir.cpp Sat Nov 29 12:28:10 2008 +0100 +++ b/gen/toir.cpp Sat Nov 29 21:25:43 2008 +0100 @@ -135,20 +135,27 @@ } else { Logger::println("a normal variable"); + // take care of forward references of global variables if (vd->isDataseg() || (vd->storage_class & STCextern)) { vd->toObjFile(0); // TODO: multiobj } - if (!vd->ir.isSet() || !vd->ir.getIrValue()) { + + LLValue* val; + + if (!vd->ir.isSet() || !(val = vd->ir.getIrValue())) { error("variable %s not resolved", vd->toChars()); if (Logger::enabled()) Logger::cout() << "unresolved variable had type: " << *DtoType(vd->type) << '\n'; fatal(); } + if (vd->isDataseg() || (vd->storage_class & STCextern)) { DtoConstInitGlobal(vd); + val = DtoBitCast(val, DtoType(type->pointerTo())); } - return new DVarValue(type, vd, vd->ir.getIrValue()); + + return new DVarValue(type, vd, val); } } else if (FuncDeclaration* fdecl = var->isFuncDeclaration()) @@ -369,7 +376,7 @@ llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; if (Logger::enabled()) Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n'; - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".stringliteral",gIR->module); + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".str",gIR->module); llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); LLConstant* idxs[2] = { zero, zero }; @@ -443,7 +450,7 @@ } llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".stringliteral",gIR->module); + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".str",gIR->module); llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); LLConstant* idxs[2] = { zero, zero }; @@ -1008,19 +1015,21 @@ assert(fdecl->vtblIndex > 0); assert(e1type->ty == Tclass); - LLValue* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); - LLValue* vtblidx = llvm::ConstantInt::get(LLType::Int32Ty, (size_t)fdecl->vtblIndex, false); + LLValue* zero = DtoConstUint(0); + size_t vtblidx = fdecl->vtblIndex; if (Logger::enabled()) Logger::cout() << "vthis: " << *vthis << '\n'; - funcval = DtoGEP(vthis, zero, zero); + funcval = vthis; + if (!fdecl->isMember2()->isInterfaceDeclaration()) + funcval = DtoGEP(funcval, zero, zero); funcval = DtoLoad(funcval); - funcval = DtoGEP(funcval, zero, vtblidx, toChars()); + Logger::println("vtblidx = %lu", vtblidx); + funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars()); funcval = DtoLoad(funcval); - #if OPAQUE_VTBLS + funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type))); if (Logger::enabled()) Logger::cout() << "funcval casted: " << *funcval << '\n'; - #endif } // static call else { @@ -2143,6 +2152,22 @@ ////////////////////////////////////////////////////////////////////////////////////////// +LLConstant* FuncExp::toConstElem(IRState* p) +{ + Logger::print("FuncExp::toConstElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + + assert(fd); + assert(fd->tok == TOKfunction); + + DtoForceDefineDsymbol(fd); + assert(fd->ir.irFunc->func); + + return fd->ir.irFunc->func; +} + +////////////////////////////////////////////////////////////////////////////////////////// + DValue* ArrayLiteralExp::toElem(IRState* p) { Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); @@ -2252,91 +2277,147 @@ ////////////////////////////////////////////////////////////////////////////////////////// +void addZeros(std::vector<llvm::Value*>& inits, unsigned pos, unsigned offset); + DValue* StructLiteralExp::toElem(IRState* p) { Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - const LLType* llt = DtoType(type); - - LLValue* mem = 0; - - LLValue* sptr = DtoAlloca(llt,"tmpstructliteral"); - - // default init the struct to take care of padding - // and unspecified members - TypeStruct* ts = (TypeStruct*)type->toBasetype(); - assert(ts->sym); - DtoForceConstInitDsymbol(ts->sym); - assert(ts->sym->ir.irStruct->init); - DtoAggrCopy(sptr, ts->sym->ir.irStruct->init); - - // num elements in literal - unsigned n = elements->dim; - - // unions might have different types for each literal - if (sd->ir.irStruct->hasUnions) { - // build the type of the literal - std::vector<const LLType*> tys; - for (unsigned i=0; i<n; ++i) { - Expression* vx = (Expression*)elements->data[i]; - if (!vx) continue; - tys.push_back(DtoType(vx->type)); + // get arrays + size_t n = elements->dim; + Expression** exprs = (Expression**)elements->data; + + assert(sd->fields.dim == n); + VarDeclaration** vars = (VarDeclaration**)sd->fields.data; + + // vector of values to build aggregate from + std::vector<llvm::Value*> values; + + // trackers + size_t lastoffset = 0; + size_t lastsize = 0; + + // for through each field and build up the struct, padding with zeros + for (size_t i=0; i<n; i++) + { + Expression* e = exprs[i]; + VarDeclaration* var = vars[i]; + + // field is skipped + if (!e) + continue; + + // add any 0 padding needed before this field + if (var->offset > lastoffset + lastsize) + { + addZeros(values, lastoffset + lastsize, var->offset); } - const LLStructType* t = LLStructType::get(tys, sd->ir.irStruct->packed); - if (t != llt) { - if (getABITypeSize(t) != getABITypeSize(llt)) { - if (Logger::enabled()) - Logger::cout() << "got size " << getABITypeSize(t) << ", expected " << getABITypeSize(llt) << '\n'; - assert(0 && "type size mismatch"); - } - sptr = DtoBitCast(sptr, getPtrToType(t)); - if (Logger::enabled()) - Logger::cout() << "sptr type is now: " << *t << '\n'; - } + + // add the expression value + DValue* v = e->toElem(p); + values.push_back(v->getRVal()); + + // update offsets + lastoffset = var->offset; + lastsize = var->type->size(); + } + + // add any 0 padding needed at the end of the literal + const LLType* structtype = DtoType(sd->type); + size_t structsize = getABITypeSize(structtype); + + if (structsize > lastoffset+lastsize) + { + addZeros(values, lastoffset + lastsize, structsize); } - // build - unsigned j = 0; - for (unsigned i=0; i<n; ++i) + // get the struct type from the values + n = values.size(); + std::vector<const LLType*> types(n, NULL); + + for (size_t i=0; i<n; i++) { - Expression* vx = (Expression*)elements->data[i]; - if (!vx) continue; - - if (Logger::enabled()) - Logger::cout() << "getting index " << j << " of " << *sptr << '\n'; - LLValue* arrptr = DtoGEPi(sptr,0,j); - DValue* darrptr = new DVarValue(vx->type, arrptr); - - DValue* ve = vx->toElem(p); - DtoAssign(loc, darrptr, ve); - - j++; + types[i] = values[i]->getType(); } - return new DImValue(type, sptr); + const LLStructType* sty = LLStructType::get(types, sd->ir.irStruct->packed); + + // allocate storage for the struct literal on the stack + LLValue* mem = DtoAlloca(sty, "tmpstructliteral"); + + // put all the values into the storage + for (size_t i=0; i<n; i++) + { + LLValue* ptr = DtoGEPi(mem, 0, i); + DtoStore(values[i], ptr); + } + + // cast the alloca pointer to the "formal" struct type + mem = DtoBitCast(mem, getPtrToType(structtype)); + + // return as a var + return new DVarValue(type, mem); } ////////////////////////////////////////////////////////////////////////////////////////// +void addZeros(std::vector<llvm::Constant*>& inits, unsigned pos, unsigned offset); + LLConstant* StructLiteralExp::toConstElem(IRState* p) { Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - unsigned n = elements->dim; - std::vector<LLConstant*> vals(n, NULL); - - for (unsigned i=0; i<n; ++i) + // get arrays + size_t n = elements->dim; + Expression** exprs = (Expression**)elements->data; + + assert(sd->fields.dim == n); + VarDeclaration** vars = (VarDeclaration**)sd->fields.data; + + // vector of values to build aggregate from + std::vector<llvm::Constant*> values; + + // trackers + size_t lastoffset = 0; + size_t lastsize = 0; + + // for through each field and build up the struct, padding with zeros + for (size_t i=0; i<n; i++) { - Expression* vx = (Expression*)elements->data[i]; - vals[i] = vx->toConstElem(p); + Expression* e = exprs[i]; + VarDeclaration* var = vars[i]; + + // field is skipped + if (!e) + continue; + + // add any 0 padding needed before this field + if (var->offset > lastoffset + lastsize) + { + addZeros(values, lastoffset + lastsize, var->offset); + } + + // add the expression value + values.push_back(e->toConstElem(p)); + + // update offsets + lastoffset = var->offset; + lastsize = var->type->size(); } - assert(type->toBasetype()->ty == Tstruct); - const LLType* t = DtoType(type); - const LLStructType* st = isaStruct(t); - return llvm::ConstantStruct::get(st,vals); + // add any 0 padding needed at the end of the literal + const LLType* structtype = DtoType(sd->type); + size_t structsize = getABITypeSize(structtype); + + if (structsize > lastoffset+lastsize) + { + addZeros(values, lastoffset + lastsize, structsize); + } + + // return constant struct + return LLConstantStruct::get(values, sd->ir.irStruct->packed); } //////////////////////////////////////////////////////////////////////////////////////////