Account for special case of builtin TypeInfos (rt.typeinfo.*)

And aid in debugging by outputting the IR type names if there are type
mismatches when declaring global variables.
This commit is contained in:
Martin 2018-04-08 00:26:45 +02:00
parent 8d5a94c7b8
commit 2dea0e96ee
2 changed files with 25 additions and 7 deletions

View file

@ -1746,6 +1746,14 @@ llvm::Constant *buildStringLiteralConstant(StringExp *se, bool zeroTerm) {
return LLConstantArray::get(at, vals); return LLConstantArray::get(at, vals);
} }
static std::string llvmTypeToString(llvm::Type *type) {
std::string result;
llvm::raw_string_ostream stream(result);
stream << *type;
stream.flush();
return result;
}
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module, llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
llvm::Type *type, llvm::Type *type,
llvm::StringRef mangledName, llvm::StringRef mangledName,
@ -1753,13 +1761,17 @@ llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
llvm::GlobalVariable *existing = llvm::GlobalVariable *existing =
module.getGlobalVariable(mangledName, /*AllowInternal=*/true); module.getGlobalVariable(mangledName, /*AllowInternal=*/true);
if (existing) { if (existing) {
if (existing->getType()->getElementType() != type || const auto existingType = existing->getType()->getElementType();
existing->isConstant() != isConstant || if (existingType != type || existing->isConstant() != isConstant ||
existing->isThreadLocal() != isThreadLocal) { existing->isThreadLocal() != isThreadLocal) {
const auto existingTypeName = llvmTypeToString(existingType);
const auto newTypeName = llvmTypeToString(type);
error(loc, error(loc,
"Global variable type does not match previous declaration with " "Global variable type does not match previous declaration with "
"same mangled name: `%s`", "same mangled name: `%s`",
mangledName.str().c_str()); mangledName.str().c_str());
errorSupplemental(loc, "Previous IR type: %s", existingTypeName.c_str());
errorSupplemental(loc, "New IR type: %s", newTypeName.c_str());
fatal(); fatal();
} }
return existing; return existing;

View file

@ -623,12 +623,18 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState *p) {
Logger::println("typeinfo mangle: %s", mangled); Logger::println("typeinfo mangle: %s", mangled);
} }
// Only declare the symbol if it isn't yet, otherwise the subtype of built-in
// TypeInfos (rt.typeinfo.*) may clash with the base type when compiling the
// rt.typeinfo.* modules.
const auto irMangle = getIRMangledVarName(mangled, LINKd); const auto irMangle = getIRMangledVarName(mangled, LINKd);
LLType *type = DtoType(decl->type)->getPointerElementType(); llvm::GlobalVariable *gvar = gIR->module.getGlobalVariable(irMangle);
// Declare the symbol. We need to keep it mutable as the type is not if (!gvar) {
// declared as immutable on the D side, and e.g. synchronized() can be used LLType *type = DtoType(decl->type)->getPointerElementType();
// on the implicit monitor. // We need to keep the symbol mutable as the type is not declared as
auto gvar = declareGlobal(decl->loc, gIR->module, type, irMangle, false); // immutable on the D side, and e.g. synchronized() can be used on the
// implicit monitor.
gvar = declareGlobal(decl->loc, gIR->module, type, irMangle, false);
}
IrGlobal *irg = getIrGlobal(decl, true); IrGlobal *irg = getIrGlobal(decl, true);
irg->value = gvar; irg->value = gvar;