Mercurial > projects > ldc
diff gen/toobj.cpp @ 100:5071469303d4 trunk
[svn r104] TONS OF FIXES.
Split up declaration, constant initializer gen and definition for globals, structs, classes and functions.
Improved ClassInfo support (not complete), not in vtable yet.
Fixed a bunch of forward reference problems.
Much more. Major commit! :)
author | lindquist |
---|---|
date | Fri, 16 Nov 2007 08:21:47 +0100 |
parents | 6789050b5ad1 |
children | 027b8d8b71ec |
line wrap: on
line diff
--- a/gen/toobj.cpp Thu Nov 15 00:24:44 2007 +0100 +++ b/gen/toobj.cpp Fri Nov 16 08:21:47 2007 +0100 @@ -36,6 +36,8 @@ #include "gen/tollvm.h" #include "gen/arrays.h" #include "gen/structs.h" +#include "gen/classes.h" +#include "gen/functions.h" #include "gen/todebug.h" #include "gen/runtime.h" @@ -90,12 +92,14 @@ dsym->toObjFile(); } - // check if there are queued function definitions, if so process their bodies now - if (!ir.funcQueue.empty()) { - size_t n = ir.funcQueue.size(); - for (size_t i=0; i<n; ++i) { - ir.funcQueue[i]->toObjFile(); - } + // process deferred const initializers + for (size_t i=0; i<ir.constInitQueue.size(); ++i) { + DtoConstInitDsymbol(ir.constInitQueue[i]); + } + + // process deferred definitions + for (size_t i=0; i<ir.defineQueue.size(); ++i) { + DtoDefineDsymbol(ir.defineQueue[i]); } // generate ModuleInfo @@ -322,183 +326,7 @@ void StructDeclaration::toObjFile() { - TypeStruct* ts = (TypeStruct*)DtoDType(type); - if (llvmType != 0) - return; - - static int sdi = 0; - Logger::print("StructDeclaration::toObjFile(%d): %s\n", sdi++, toChars()); - LOG_SCOPE; - - gIR->structs.push_back(IRStruct(ts)); - - for (int k=0; k < members->dim; k++) { - Dsymbol* dsym = (Dsymbol*)(members->data[k]); - dsym->toObjFile(); - } - - Logger::println("doing struct fields"); - - const llvm::StructType* structtype = 0; - std::vector<llvm::Constant*> fieldinits; - - if (gIR->topstruct().offsets.empty()) - { - std::vector<const llvm::Type*> fieldtypes; - Logger::println("has no fields"); - fieldtypes.push_back(llvm::Type::Int8Ty); - fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); - structtype = llvm::StructType::get(fieldtypes); - } - else - { - Logger::println("has fields"); - std::vector<const llvm::Type*> fieldtypes; - unsigned prevsize = (unsigned)-1; - unsigned lastoffset = (unsigned)-1; - const llvm::Type* fieldtype = NULL; - llvm::Constant* fieldinit = NULL; - size_t fieldpad = 0; - int idx = 0; - for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) { - // first iteration - if (lastoffset == (unsigned)-1) { - lastoffset = i->first; - assert(lastoffset == 0); - fieldtype = DtoType(i->second.var->type); - fieldinit = i->second.init; - prevsize = gTargetData->getTypeSize(fieldtype); - i->second.var->llvmFieldIndex = idx; - } - // colliding offset? - else if (lastoffset == i->first) { - const llvm::Type* t = DtoType(i->second.var->type); - size_t s = gTargetData->getTypeSize(t); - if (s > prevsize) { - fieldpad += s - prevsize; - prevsize = s; - } - llvmHasUnions = true; - i->second.var->llvmFieldIndex = idx; - } - // intersecting offset? - else if (i->first < (lastoffset + prevsize)) { - const llvm::Type* t = DtoType(i->second.var->type); - size_t s = gTargetData->getTypeSize(t); - assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size - llvmHasUnions = true; - i->second.var->llvmFieldIndex = idx; - i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s; - } - // fresh offset - else { - // commit the field - fieldtypes.push_back(fieldtype); - fieldinits.push_back(fieldinit); - if (fieldpad) { - // match up with below - std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); - llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals); - fieldtypes.push_back(c->getType()); - fieldinits.push_back(c); - idx++; - } - - idx++; - - // start new - lastoffset = i->first; - fieldtype = DtoType(i->second.var->type); - fieldinit = i->second.init; - prevsize = gTargetData->getTypeSize(fieldtype); - i->second.var->llvmFieldIndex = idx; - fieldpad = 0; - } - } - fieldtypes.push_back(fieldtype); - fieldinits.push_back(fieldinit); - if (fieldpad) { - // match up with above - std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); - llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals); - fieldtypes.push_back(c->getType()); - fieldinits.push_back(c); - } - - Logger::println("creating struct type"); - structtype = llvm::StructType::get(fieldtypes); - } - - // refine abstract types for stuff like: struct S{S* next;} - if (gIR->topstruct().recty != 0) - { - llvm::PATypeHolder& pa = gIR->topstruct().recty; - llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype); - structtype = isaStruct(pa.get()); - } - - ts->llvmType = structtype; - llvmType = structtype; - - if (parent->isModule()) { - gIR->module->addTypeName(mangle(),ts->llvmType); - } - - llvmUnion = new DUnion; // uses gIR->topstruct() - - // generate static data - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; - llvm::Constant* _init = 0; - - // always generate the constant initalizer - if (!zeroInit) { - Logger::println("Not zero initialized"); - //assert(tk == gIR->gIR->topstruct()().size()); - #ifndef LLVMD_NO_LOGGER - Logger::cout() << "struct type: " << *structtype << '\n'; - for (size_t k=0; k<fieldinits.size(); ++k) { - Logger::cout() << "Type:" << '\n'; - Logger::cout() << *fieldinits[k]->getType() << '\n'; - Logger::cout() << "Value:" << '\n'; - Logger::cout() << *fieldinits[k] << '\n'; - } - Logger::cout() << "Initializer printed" << '\n'; - #endif - llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits); - } - else { - Logger::println("Zero initialized"); - llvmInitZ = llvm::ConstantAggregateZero::get(structtype); - } - - // only provide the constant initializer for the defining module - if (getModule() == gIR->dmodule) - { - _init = llvmInitZ; - } - - std::string initname("_D"); - initname.append(mangle()); - initname.append("6__initZ"); - llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module); - ts->llvmInit = initvar; - - // generate member function definitions - gIR->topstruct().queueFuncs = false; - IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs; - size_t n = mfs.size(); - for (size_t i=0; i<n; ++i) { - //mfs[i]->toObjFile(); - gIR->funcQueue.push_back(mfs[i]); - } - - llvmDModule = gIR->dmodule; - - gIR->structs.pop_back(); - - // generate typeinfo - if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo) - type->getTypeInfo(NULL); + DtoDeclareStruct(this); } /* ================================================================== */ @@ -534,186 +362,9 @@ /* ================================================================== */ -static void LLVM_AddBaseClassData(BaseClasses* bcs) -{ - // add base class data members first - for (int j=0; j<bcs->dim; j++) - { - BaseClass* bc = (BaseClass*)(bcs->data[j]); - assert(bc); - Logger::println("Adding base class members of %s", bc->base->toChars()); - LOG_SCOPE; - - LLVM_AddBaseClassData(&bc->base->baseclasses); - for (int k=0; k < bc->base->members->dim; k++) { - Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); - if (dsym->isVarDeclaration()) - { - dsym->toObjFile(); - } - } - } -} - void ClassDeclaration::toObjFile() { - TypeClass* ts = (TypeClass*)DtoDType(type); - if (ts->llvmType != 0 || llvmInProgress) - return; - - llvmInProgress = true; - - static int fdi = 0; - Logger::print("ClassDeclaration::toObjFile(%d): %s\n", fdi++, toChars()); - LOG_SCOPE; - - gIR->structs.push_back(IRStruct(ts)); - gIR->classes.push_back(this); - - // add vtable - llvm::PATypeHolder pa = llvm::OpaqueType::get(); - const llvm::Type* vtabty = llvm::PointerType::get(pa); - - std::vector<const llvm::Type*> fieldtypes; - fieldtypes.push_back(vtabty); - - std::vector<llvm::Constant*> fieldinits; - fieldinits.push_back(0); - - // base classes first - LLVM_AddBaseClassData(&baseclasses); - - // then add own members - for (int k=0; k < members->dim; k++) { - Dsymbol* dsym = (Dsymbol*)(members->data[k]); - dsym->toObjFile(); - } - - // fill out fieldtypes/inits - for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) { - fieldtypes.push_back(DtoType(i->second.var->type)); - fieldinits.push_back(i->second.init); - } - - const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); - // refine abstract types for stuff like: class C {C next;} - if (gIR->topstruct().recty != 0) - { - llvm::PATypeHolder& pa = gIR->topstruct().recty; - llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype); - structtype = isaStruct(pa.get()); - } - - ts->llvmType = structtype; - llvmType = structtype; - - bool needs_definition = false; - if (parent->isModule()) { - gIR->module->addTypeName(mangle(),ts->llvmType); - needs_definition = (getModule() == gIR->dmodule); - } - else { - assert(0 && "class parent is not a module"); - } - - // generate vtable - llvm::GlobalVariable* svtblVar = 0; - std::vector<llvm::Constant*> sinits; - std::vector<const llvm::Type*> sinits_ty; - sinits.reserve(vtbl.dim); - sinits_ty.reserve(vtbl.dim); - - for (int k=0; k < vtbl.dim; k++) - { - Dsymbol* dsym = (Dsymbol*)vtbl.data[k]; - assert(dsym); - //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; - - if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { - fd->toObjFile(); - assert(fd->llvmValue); - llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); - sinits.push_back(c); - sinits_ty.push_back(c->getType()); - } - else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { - const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty); - llvm::Constant* c = llvm::Constant::getNullValue(cty); - sinits.push_back(c); - sinits_ty.push_back(cty); - } - else - assert(0); - } - - const llvm::StructType* svtbl_ty = 0; - if (!sinits.empty()) - { - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; - - std::string varname("_D"); - varname.append(mangle()); - varname.append("6__vtblZ"); - - std::string styname(mangle()); - styname.append("__vtblTy"); - - svtbl_ty = llvm::StructType::get(sinits_ty); - gIR->module->addTypeName(styname, svtbl_ty); - svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); - - llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits)); - if (needs_definition) - svtblVar->setInitializer(llvmConstVtbl); - llvmVtbl = svtblVar; - } - - //////////////////////////////////////////////////////////////////////////////// - - // refine for final vtable type - llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty); - svtbl_ty = isaStruct(pa.get()); - structtype = isaStruct(gIR->topstruct().recty.get()); - ts->llvmType = structtype; - llvmType = structtype; - - // generate initializer - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; - llvm::Constant* _init = 0; - - // first field is always the vtable - assert(svtblVar != 0); - fieldinits[0] = svtblVar; - - llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits); - 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, NULL, initname, gIR->module); - ts->llvmInit = initvar; - - if (needs_definition) { - initvar->setInitializer(_init); - // generate member functions - gIR->topstruct().queueFuncs = false; - IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs; - size_t n = mfs.size(); - for (size_t i=0; i<n; ++i) { - //mfs[i]->toObjFile(); - gIR->funcQueue.push_back(mfs[i]); - } - } - - gIR->classes.pop_back(); - gIR->structs.pop_back(); - - llvmInProgress = false; - - // if (ClassDeclaration::classinfo != this) - // DtoClassInfo(this); + DtoDeclareClass(this); } /****************************************** @@ -732,7 +383,6 @@ { Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - llvm::Module* M = gIR->module; if (aliassym) { @@ -747,81 +397,40 @@ if (llvmTouched) return; else llvmTouched = true; - bool _isconst = false; - if (isConst() && (init && !init->isExpInitializer())) - _isconst = true; + llvmIRGlobal = new IRGlobal(this); + + Logger::println("parent: %s (%s)", parent->toChars(), parent->kind()); + + bool _isconst = isConst(); + if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer()) + _isconst = false; llvm::GlobalValue::LinkageTypes _linkage; bool istempl = false; + bool static_local = false; if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) { _linkage = llvm::GlobalValue::WeakLinkage; istempl = true; } - else if (parent && parent->isFuncDeclaration()) + else if (parent && parent->isFuncDeclaration()) { _linkage = llvm::GlobalValue::InternalLinkage; + static_local = true; + } else _linkage = DtoLinkage(protection, storage_class); - Type* t = DtoDType(type); - - const llvm::Type* _type = DtoType(t); - assert(_type); - - llvm::Constant* _init = 0; - bool _signed = !type->isunsigned(); + const llvm::Type* _type = llvmIRGlobal->type.get(); Logger::println("Creating global variable"); std::string _name(mangle()); - bool emitRTstaticInit = false; - - if (!(storage_class & STCextern) && (getModule() == gIR->dmodule || istempl)) - { - if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer()) { - _init = DtoConstInitializer(t, NULL); - emitRTstaticInit = true; - } - else { - _init = DtoConstInitializer(t, init); - } - - //Logger::cout() << "initializer: " << *_init << '\n'; - if (_type != _init->getType()) { - Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n"; - // zero initalizer - if (_init->isNullValue()) - _init = llvm::Constant::getNullValue(_type); - // pointer to global constant (struct.init) - else if (llvm::isa<llvm::GlobalVariable>(_init)) - { - assert(_init->getType()->getContainedType(0) == _type); - llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init); - assert(t->ty == Tstruct); - TypeStruct* ts = (TypeStruct*)t; - assert(ts->sym->llvmInitZ); - _init = ts->sym->llvmInitZ; - } - // array single value init - else if (isaArray(_type)) - { - _init = DtoConstStaticArray(_type, _init); - } - else { - Logger::cout() << "Unexpected initializer type: " << *_type << '\n'; - //assert(0); - } - } - } - - if (_init && _init->getType() != _type) - _type = _init->getType(); - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,_init,_name,M); + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,NULL,_name,gIR->module); llvmValue = gvar; - if (emitRTstaticInit) - DtoLazyStaticInit(istempl, gvar, init, t); - - llvmDModule = gIR->dmodule; + if (static_local) + DtoConstInitGlobal(this); + else + gIR->constInitQueue.push_back(this); //if (storage_class & STCprivate) // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility); @@ -832,47 +441,10 @@ { Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset); - Type* t = DtoDType(type); - const llvm::Type* _type = DtoType(t); - - llvm::Constant*_init = DtoConstInitializer(t, init); - assert(_init); - Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n'; - if (_type != _init->getType()) - { - if (t->ty == Tsarray) - { - const llvm::ArrayType* arrty = isaArray(_type); - uint64_t n = arrty->getNumElements(); - std::vector<llvm::Constant*> vals(n,_init); - _init = llvm::ConstantArray::get(arrty, vals); - } - else if (t->ty == Tarray) - { - assert(isaStruct(_type)); - _init = llvm::ConstantAggregateZero::get(_type); - } - else if (t->ty == Tstruct) - { - const llvm::StructType* structty = isaStruct(_type); - TypeStruct* ts = (TypeStruct*)t; - assert(ts); - assert(ts->sym); - assert(ts->sym->llvmInitZ); - _init = ts->sym->llvmInitZ; - } - else if (t->ty == Tclass) - { - _init = llvm::Constant::getNullValue(_type); - } - else { - Logger::println("failed for type %s", type->toChars()); - assert(0); - } - } + const llvm::Type* _type = DtoType(type); // add the field in the IRStruct - gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init))); + gIR->topstruct()->offsets.insert(std::make_pair(offset, IRStruct::Offset(this, _type))); } Logger::println("VarDeclaration::toObjFile is done"); @@ -901,254 +473,5 @@ void FuncDeclaration::toObjFile() { - if (llvmDModule) { - assert(llvmValue != 0); - return; - } - - if (llvmRunTimeHack) { - Logger::println("runtime hack func chars: %s", toChars()); - if (!llvmValue) - llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, toChars()); - return; - } - - if (isUnitTestDeclaration()) { - Logger::attention("ignoring unittest declaration: %s", toChars()); - return; - } - - Type* t = DtoDType(type); - TypeFunction* f = (TypeFunction*)t; - - bool declareOnly = false; - if (parent) - { - if (TemplateInstance* tinst = parent->isTemplateInstance()) { - TemplateDeclaration* tempdecl = tinst->tempdecl; - if (tempdecl->llvmInternal == LLVMva_start) - { - Logger::println("magic va_start found"); - llvmInternal = LLVMva_start; - declareOnly = true; - } - else if (tempdecl->llvmInternal == LLVMva_arg) - { - Logger::println("magic va_arg found"); - llvmInternal = LLVMva_arg; - return; - } - } - } - - llvm::Function* func = DtoDeclareFunction(this); - - if (declareOnly) - return; - - if (!gIR->structs.empty() && gIR->topstruct().queueFuncs) { - if (!llvmQueued) { - Logger::println("queueing %s", toChars()); - gIR->topstruct().funcs.push_back(this); - llvmQueued = true; - } - return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete - } - - // debug info - if (global.params.symdebug) { - Module* mo = getModule(); - if (!mo->llvmCompileUnit) { - mo->llvmCompileUnit = DtoDwarfCompileUnit(mo,false); - } - llvmDwarfSubProgram = DtoDwarfSubProgram(this, mo->llvmCompileUnit); - } - - assert(f->llvmType); - const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0)); - - // template instances should have weak linkage - if (parent && DtoIsTemplateInstance(parent)) { - func->setLinkage(llvm::GlobalValue::WeakLinkage); - } - - // only members of the current module maybe be defined - if (getModule() == gIR->dmodule || DtoIsTemplateInstance(parent)) - { - llvmDModule = gIR->dmodule; - - // handle static constructor / destructor - if (isStaticCtorDeclaration() || isStaticDtorDeclaration()) { - const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1); - //Logger::cout() << "static ctor type: " << *sctor_type << '\n'; - - llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(llvmValue); - //Logger::cout() << "static ctor func: " << *sctor_func << '\n'; - - llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1); - - //Logger::cout() << "static ctor init: " << *sctor_init << '\n'; - - // output the llvm.global_ctors array - const char* varname = isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array"; - llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module); - } - - // function definition - if (fbody != 0) - { - gIR->functions.push_back(IRFunction(this)); - gIR->func().func = func; - - // first make absolutely sure the type is up to date - f->llvmType = llvmValue->getType()->getContainedType(0); - - //Logger::cout() << "func type: " << *f->llvmType << '\n'; - - // this handling - if (f->llvmUsesThis) { - Logger::println("uses this"); - if (f->llvmRetInPtr) - llvmThisVar = ++func->arg_begin(); - else - llvmThisVar = func->arg_begin(); - assert(llvmThisVar != 0); - } - - if (isMain()) - gIR->emitMain = true; - - llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func); - llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func); - - //assert(gIR->scopes.empty()); - gIR->scopes.push_back(IRScope(beginbb, endbb)); - - // create alloca point - f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); - gIR->func().allocapoint = f->llvmAllocaPoint; - - // give arguments storage - size_t n = Argument::dim(f->parameters); - for (int i=0; i < n; ++i) { - Argument* arg = Argument::getNth(f->parameters, i); - if (arg && arg->vardecl) { - VarDeclaration* vd = arg->vardecl; - if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)) - continue; - llvm::Value* a = vd->llvmValue; - assert(a); - std::string s(a->getName()); - Logger::println("giving argument '%s' storage", s.c_str()); - s.append("_storage"); - llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint); - gIR->ir->CreateStore(a,v); - vd->llvmValue = v; - } - else { - Logger::attention("some unknown argument: %s", arg ? arg->toChars() : 0); - } - } - - // debug info - if (global.params.symdebug) DtoDwarfFuncStart(this); - - llvm::Value* parentNested = NULL; - if (FuncDeclaration* fd = toParent()->isFuncDeclaration()) { - parentNested = fd->llvmNested; - } - - // construct nested variables struct - if (!llvmNestedVars.empty() || parentNested) { - std::vector<const llvm::Type*> nestTypes; - int j = 0; - if (parentNested) { - nestTypes.push_back(parentNested->getType()); - j++; - } - for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) { - VarDeclaration* vd = *i; - vd->llvmNestedIndex = j++; - if (vd->isParameter()) { - assert(vd->llvmValue); - nestTypes.push_back(vd->llvmValue->getType()); - } - else { - nestTypes.push_back(DtoType(vd->type)); - } - } - const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); - Logger::cout() << "nested var struct has type:" << '\n' << *nestSType; - llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint); - if (parentNested) { - assert(llvmThisVar); - llvm::Value* ptr = gIR->ir->CreateBitCast(llvmThisVar, parentNested->getType(), "tmp"); - gIR->ir->CreateStore(ptr, DtoGEPi(llvmNested, 0,0, "tmp")); - } - for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) { - VarDeclaration* vd = *i; - if (vd->isParameter()) { - gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(llvmNested, 0, vd->llvmNestedIndex, "tmp")); - vd->llvmValue = llvmNested; - } - } - } - - // copy _argptr to a memory location - if (f->linkage == LINKd && f->varargs == 1) - { - llvm::Value* argptrmem = new llvm::AllocaInst(llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint()); - new llvm::StoreInst(llvmArgPtr, argptrmem, gIR->scopebb()); - llvmArgPtr = argptrmem; - } - - // output function body - fbody->toIR(gIR); - - // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement - // in automatically, so we do it here. - if (!isMain()) { - if (!gIR->scopereturned()) { - // pass the previous block into this block - if (global.params.symdebug) DtoDwarfFuncEnd(this); - if (func->getReturnType() == llvm::Type::VoidTy) { - new llvm::ReturnInst(gIR->scopebb()); - } - else { - new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb()); - } - } - } - - // erase alloca point - f->llvmAllocaPoint->eraseFromParent(); - f->llvmAllocaPoint = 0; - gIR->func().allocapoint = 0; - - gIR->scopes.pop_back(); - - // get rid of the endentry block, it's never used - assert(!func->getBasicBlockList().empty()); - func->getBasicBlockList().pop_back(); - - // if the last block is empty now, it must be unreachable or it's a bug somewhere else - // would be nice to figure out how to assert that this is correct - llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); - if (lastbb->empty()) { - if (lastbb->getNumUses() == 0) - lastbb->eraseFromParent(); - else { - new llvm::UnreachableInst(lastbb); - /*if (func->getReturnType() == llvm::Type::VoidTy) { - new llvm::ReturnInst(lastbb); - } - else { - new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb); - }*/ - } - } - - gIR->functions.pop_back(); - } - } + DtoDeclareFunction(this); }