[svn r155] Fixed a bunch of linkage problems (especially with templates)

This commit is contained in:
Tomas Lindquist Olsen
2008-03-24 19:43:02 +01:00
parent 402ce90e19
commit ecd91a48f2
9 changed files with 170 additions and 60 deletions

View File

@@ -350,7 +350,7 @@ void DtoDeclareClass(ClassDeclaration* cd)
needs_definition = true;
}
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd);
// interfaces have no static initializer
// same goes for abstract classes
@@ -1201,7 +1201,7 @@ void DtoDeclareClassInfo(ClassDeclaration* cd)
const llvm::Type* st = cinfo->type->llvmType->get();
cd->irStruct->classInfo = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module);
cd->irStruct->classInfo = new llvm::GlobalVariable(st, true, DtoLinkage(cd), NULL, gname, gIR->module);
}
static llvm::Constant* build_offti_entry(VarDeclaration* vd)
@@ -1275,7 +1275,8 @@ static llvm::Constant* build_offti_array(ClassDeclaration* cd, llvm::Constant* i
std::string name(cd->type->vtinfo->toChars());
name.append("__OffsetTypeInfos");
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,llvm::GlobalValue::InternalLinkage,arrInit,name,gIR->module);
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,DtoInternalLinkage(cd),arrInit,name,gIR->module);
ptr = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(sTy));
}
else {
@@ -1307,7 +1308,7 @@ static llvm::Constant* build_class_dtor(ClassDeclaration* cd)
gname.append(cd->mangle());
gname.append("12__destructorMFZv");
llvm::Function* func = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, gname, gIR->module);
llvm::Function* func = new llvm::Function(fnTy, DtoInternalLinkage(cd), gname, gIR->module);
llvm::Value* thisptr = func->arg_begin();
thisptr->setName("this");

View File

@@ -353,7 +353,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
const llvm::FunctionType* functype = DtoFunctionType(fdecl);
llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name);
if (!func)
func = new llvm::Function(functype, DtoLinkage(fdecl->protection, fdecl->storage_class), mangled_name, gIR->module);
func = new llvm::Function(functype, DtoLinkage(fdecl), mangled_name, gIR->module);
else
assert(func->getFunctionType() == functype);
@@ -363,21 +363,8 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
// calling convention
if (!vafunc && fdecl->llvmInternal != LLVMintrinsic)
func->setCallingConv(DtoCallingConv(f->linkage));
// template instances should have weak linkage
if (!vafunc && fdecl->llvmInternal != LLVMintrinsic && fdecl->parent && DtoIsTemplateInstance(fdecl->parent))
func->setLinkage(llvm::GlobalValue::WeakLinkage);
// extern(C) functions are always external
if (f->linkage == LINKc)
func->setLinkage(llvm::GlobalValue::ExternalLinkage);
// intrinsics are always external C
if (fdecl->llvmInternal == LLVMintrinsic)
{
func->setLinkage(llvm::GlobalValue::ExternalLinkage);
else // fall back to C, it should be the right thing to do
func->setCallingConv(llvm::CallingConv::C);
}
fdecl->irFunc->func = func;
assert(llvm::isa<llvm::FunctionType>(f->llvmType->get()));

View File

@@ -332,7 +332,7 @@ void DtoDeclareStruct(StructDeclaration* sd)
initname.append(sd->mangle());
initname.append("6__initZ");
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(sd);
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
sd->irStruct->init = initvar;

View File

@@ -344,36 +344,71 @@ llvm::Value* DtoCompareDelegate(TOK op, llvm::Value* lhs, llvm::Value* rhs)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::GlobalValue::LinkageTypes DtoLinkage(PROT prot, uint stc)
llvm::GlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
{
// turns out we can't really make anything internal with the way D works :(
// the things we can need much more info than this can extract.
// TODO : remove this useless function
switch(prot)
// global variable
if (VarDeclaration* vd = sym->isVarDeclaration())
{
case PROTprivate:
//if (stc & STCextern)
return llvm::GlobalValue::ExternalLinkage;
//else
// return llvm::GlobalValue::InternalLinkage;
case PROTpublic:
case PROTpackage:
case PROTprotected:
case PROTexport:
return llvm::GlobalValue::ExternalLinkage;
case PROTundefined:
case PROTnone:
assert(0 && "Unsupported linkage type");
// template
if (DtoIsTemplateInstance(sym))
return llvm::GlobalValue::WeakLinkage;
// local static
else if (sym->parent && sym->parent->isFuncDeclaration())
return llvm::GlobalValue::InternalLinkage;
}
// function
else if (FuncDeclaration* fdecl = sym->isFuncDeclaration())
{
assert(fdecl->type->ty == Tfunction);
TypeFunction* ft = (TypeFunction*)fdecl->type;
// intrinsics are always external
if (fdecl->llvmInternal == LLVMintrinsic)
return llvm::GlobalValue::ExternalLinkage;
// template instances should have weak linkage
else if (DtoIsTemplateInstance(fdecl))
return llvm::GlobalValue::WeakLinkage;
// extern(C) functions are always external
else if (ft->linkage == LINKc)
return llvm::GlobalValue::ExternalLinkage;
}
// class
else if (ClassDeclaration* cd = sym->isClassDeclaration())
{
// template
if (DtoIsTemplateInstance(cd))
return llvm::GlobalValue::WeakLinkage;
}
else
{
assert(0 && "not global/function");
}
// default to external linkage
return llvm::GlobalValue::ExternalLinkage;
// llvm linkage types
/* ExternalLinkage = 0, LinkOnceLinkage, WeakLinkage, AppendingLinkage,
InternalLinkage, DLLImportLinkage, DLLExportLinkage, ExternalWeakLinkage,
GhostLinkage */
}
llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
{
if (DtoIsTemplateInstance(sym))
return llvm::GlobalValue::WeakLinkage;
else
return llvm::GlobalValue::InternalLinkage;
}
llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym)
{
if (DtoIsTemplateInstance(sym))
return llvm::GlobalValue::WeakLinkage;
else
return llvm::GlobalValue::ExternalLinkage;
}
//////////////////////////////////////////////////////////////////////////////////////////
unsigned DtoCallingConv(LINK l)

View File

@@ -21,8 +21,10 @@ llvm::Value* DtoNullDelegate(llvm::Value* v);
llvm::Value* DtoDelegateCopy(llvm::Value* dst, llvm::Value* src);
llvm::Value* DtoCompareDelegate(TOK op, llvm::Value* lhs, llvm::Value* rhs);
// return linkage types for general cases
llvm::GlobalValue::LinkageTypes DtoLinkage(PROT prot, uint stc);
// return linkage type for symbol using the current ir state for context
llvm::GlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym);
llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym);
llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym);
// convert DMD calling conv to LLVM
unsigned DtoCallingConv(LINK l);

View File

@@ -519,27 +519,21 @@ void VarDeclaration::toObjFile()
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;
// handle static local variables
bool static_local = false;
if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) {
_linkage = llvm::GlobalValue::WeakLinkage;
istempl = true;
}
else if (parent && parent->isFuncDeclaration()) {
_linkage = llvm::GlobalValue::InternalLinkage;
bool _isconst = isConst();
if (parent && parent->isFuncDeclaration())
{
static_local = true;
if (init && init->isExpInitializer()) {
_isconst = false;
}
}
else
_linkage = DtoLinkage(protection, storage_class);
const llvm::Type* _type = irGlobal->type.get();
Logger::println("Creating global variable");
const llvm::Type* _type = irGlobal->type.get();
llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(this);
std::string _name(mangle());
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,NULL,_name,gIR->module);

View File

@@ -572,6 +572,94 @@
<path>dmd25/utf.h</path>
<path>dmd25/version.c</path>
<path>dmd25/version.h</path>
<path>dmd26</path>
<path>dmd26/access.c</path>
<path>dmd26/aggregate.h</path>
<path>dmd26/array.c</path>
<path>dmd26/arraytypes.h</path>
<path>dmd26/attrib.c</path>
<path>dmd26/attrib.h</path>
<path>dmd26/cast.c</path>
<path>dmd26/class.c</path>
<path>dmd26/complex_t.h</path>
<path>dmd26/cond.c</path>
<path>dmd26/cond.h</path>
<path>dmd26/constfold.c</path>
<path>dmd26/dchar.c</path>
<path>dmd26/dchar.h</path>
<path>dmd26/declaration.c</path>
<path>dmd26/declaration.h</path>
<path>dmd26/delegatize.c</path>
<path>dmd26/doc.c</path>
<path>dmd26/doc.h</path>
<path>dmd26/dsymbol.c</path>
<path>dmd26/dsymbol.h</path>
<path>dmd26/dump.c</path>
<path>dmd26/entity.c</path>
<path>dmd26/enum.c</path>
<path>dmd26/enum.h</path>
<path>dmd26/expression.c</path>
<path>dmd26/expression.h</path>
<path>dmd26/func.c</path>
<path>dmd26/gnuc.c</path>
<path>dmd26/gnuc.h</path>
<path>dmd26/hdrgen.c</path>
<path>dmd26/hdrgen.h</path>
<path>dmd26/html.c</path>
<path>dmd26/html.h</path>
<path>dmd26/identifier.c</path>
<path>dmd26/identifier.h</path>
<path>dmd26/idgen.c</path>
<path>dmd26/impcnvgen.c</path>
<path>dmd26/import.c</path>
<path>dmd26/import.h</path>
<path>dmd26/inifile.c</path>
<path>dmd26/init.c</path>
<path>dmd26/init.h</path>
<path>dmd26/inline.c</path>
<path>dmd26/interpret.c</path>
<path>dmd26/lexer.c</path>
<path>dmd26/lexer.h</path>
<path>dmd26/link.c</path>
<path>dmd26/lstring.c</path>
<path>dmd26/lstring.h</path>
<path>dmd26/macro.c</path>
<path>dmd26/macro.h</path>
<path>dmd26/mangle.c</path>
<path>dmd26/mars.c</path>
<path>dmd26/mars.h</path>
<path>dmd26/mem.c</path>
<path>dmd26/mem.h</path>
<path>dmd26/module.c</path>
<path>dmd26/module.h</path>
<path>dmd26/mtype.c</path>
<path>dmd26/mtype.h</path>
<path>dmd26/opover.c</path>
<path>dmd26/optimize.c</path>
<path>dmd26/parse.c</path>
<path>dmd26/parse.h</path>
<path>dmd26/port.h</path>
<path>dmd26/root.c</path>
<path>dmd26/root.h</path>
<path>dmd26/scope.c</path>
<path>dmd26/scope.h</path>
<path>dmd26/statement.c</path>
<path>dmd26/statement.h</path>
<path>dmd26/staticassert.c</path>
<path>dmd26/staticassert.h</path>
<path>dmd26/stringtable.c</path>
<path>dmd26/stringtable.h</path>
<path>dmd26/struct.c</path>
<path>dmd26/template.c</path>
<path>dmd26/template.h</path>
<path>dmd26/total.h</path>
<path>dmd26/unialpha.c</path>
<path>dmd26/utf.c</path>
<path>dmd26/utf.h</path>
<path>dmd26/version.c</path>
<path>dmd26/version.h</path>
<path>todo</path>
<path>todo/lib.d</path>
</blacklist>
<build>
<buildtool>make</buildtool>

View File

@@ -765,9 +765,7 @@ tangotests/p.d
tangotests/q.d
tangotests/r.d
tangotests/s.d
tangotests/stdout1.d
tangotests/t.d
tangotests/v.d
test
test/a.d
test/aa1.d

View File

@@ -27,3 +27,8 @@ void func()
{
auto bar = new Bar(12);
}
void main()
{
func();
}