From be185263baf841d97a8eb440018e6c93a7db9f40 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 26 Dec 2013 13:24:41 +0100 Subject: [PATCH 1/2] Disable internalizing of nested functions. This works around linking problems such as rejectedsoftware/vibe.d#338, caused by the frontend appending template instances to the wrong module. GitHub: Fixes #558. --- gen/tollvm.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 10241e71..c3a7d31b 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -382,6 +382,10 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) llvm_unreachable("not global/function"); } + // The logic here should be sound in theory, but as long as the frontend + // keeps inserting templates into wrong modules, this yields to linking + // errors (see e.g. GitHub issue #558). +#if 0 // Check if sym is a nested function and we can declare it as internal. // // Nested naked functions and the implicitly generated __require/__ensure @@ -427,7 +431,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) } } } - +#endif // default to external linkage return llvm::GlobalValue::ExternalLinkage; } From 333d538a23d17f1a58b8e3d9d753f3248cb587be Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 26 Dec 2013 12:42:31 +0100 Subject: [PATCH 2/2] Handle differing LLVM types for AA literals. This unsfortunately more or less duplicates the code we have for emitting ArrayLiteralExps, but with the different iteration strategies, having a single implementation would wind up even messier. Unfortunately, no regression test case yet, as I found this deep inside vibe.d. --- gen/toir.cpp | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 2f3acc09..da480042 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -3253,6 +3253,36 @@ DValue* RemoveExp::toElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// +/// Constructs an array initializer constant with the given constants as its +/// elements. If the element types differ (unions, …), an anonymous struct +/// literal is emitted (as for array constant initializers). +static llvm::Constant* arrayConst(std::vector& vals, + Type* nominalElemType) +{ + if (vals.size() == 0) + { + llvm::ArrayType* type = llvm::ArrayType::get(DtoType(nominalElemType), 0); + return llvm::ConstantArray::get(type, vals); + } + + llvm::Type* elementType = NULL; + bool differentTypes = false; + for (std::vector::iterator i = vals.begin(), end = vals.end(); + i != end; ++i) + { + if (!elementType) + elementType = (*i)->getType(); + else + differentTypes |= (elementType != (*i)->getType()); + } + + if (differentTypes) + return llvm::ConstantStruct::getAnon(vals, true); + + llvm::ArrayType *t = llvm::ArrayType::get(elementType, vals.size()); + return llvm::ConstantArray::get(t, vals); +} + DValue* AssocArrayLiteralExp::toElem(IRState* p) { Logger::print("AssocArrayLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars()); @@ -3307,16 +3337,16 @@ DValue* AssocArrayLiteralExp::toElem(IRState* p) LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) }; - LLArrayType* arrtype = LLArrayType::get(DtoType(indexType), keys->dim); - LLConstant* initval = LLConstantArray::get(arrtype, keysInits); - LLConstant* globalstore = new LLGlobalVariable(*gIR->module, arrtype, false, LLGlobalValue::InternalLinkage, initval, ".aaKeysStorage"); + LLConstant* initval = arrayConst(keysInits, indexType); + LLConstant* globalstore = new LLGlobalVariable(*gIR->module, initval->getType(), + false, LLGlobalValue::InternalLinkage, initval, ".aaKeysStorage"); LLConstant* slice = llvm::ConstantExpr::getGetElementPtr(globalstore, idxs, true); slice = DtoConstSlice(DtoConstSize_t(keys->dim), slice); LLValue* keysArray = DtoAggrPaint(slice, funcTy->getParamType(1)); - arrtype = LLArrayType::get(DtoType(vtype), values->dim); - initval = LLConstantArray::get(arrtype, valuesInits); - globalstore = new LLGlobalVariable(*gIR->module, arrtype, false, LLGlobalValue::InternalLinkage, initval, ".aaValuesStorage"); + initval = arrayConst(valuesInits, vtype); + globalstore = new LLGlobalVariable(*gIR->module, initval->getType(), + false, LLGlobalValue::InternalLinkage, initval, ".aaValuesStorage"); slice = llvm::ConstantExpr::getGetElementPtr(globalstore, idxs, true); slice = DtoConstSlice(DtoConstSize_t(keys->dim), slice); LLValue* valuesArray = DtoAggrPaint(slice, funcTy->getParamType(2));