diff --git a/compiler/codegen.cpp b/compiler/codegen.cpp index 49c7eef09..59697e5c1 100644 --- a/compiler/codegen.cpp +++ b/compiler/codegen.cpp @@ -2411,6 +2411,23 @@ static void interpolateExpr(SourcePtr source, unsigned offset, unsigned length, } } +static bool verifierSafeParseAssemblyInto(llvm::MemoryBufferRef buf, + llvm::SMDiagnostic &err) { + materializeDebugInfoForTypes(); + vector stubs; + for (llvm::Function &f : llvmModule->functions()) { + if (f.isDeclaration()) + continue; + for (llvm::BasicBlock &bb : f) + if (bb.getTerminator() == nullptr) + stubs.push_back(new llvm::UnreachableInst(llvmContext, &bb)); + } + bool failed = llvm::parseAssemblyInto(buf, llvmModule, nullptr, err); + for (llvm::Instruction *stub : stubs) + stub->eraseFromParent(); + return failed; +} + static bool interpolateLLVMCode(LLVMCodePtr llvmBody, string &out, EnvPtr env) { SourcePtr source = llvmBody->location.source; unsigned startingOffset = llvmBody->location.offset; @@ -2513,8 +2530,7 @@ void codegenLLVMBody(InvokeEntry *entry, llvm::StringRef callableName) { std::unique_ptr buf = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(out.str())); - if (llvm::parseAssemblyInto(buf->getMemBufferRef(), llvmModule, nullptr, - err)) { + if (verifierSafeParseAssemblyInto(buf->getMemBufferRef(), err)) { llvm::errs() << out.str(); err.print("\n", llvm::errs()); llvm::errs() << "\n"; @@ -4157,8 +4173,7 @@ static void codegenTopLevelLLVMRecursive(ModulePtr m) { std::unique_ptr buf = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(code)); - if (llvm::parseAssemblyInto(buf->getMemBufferRef(), llvmModule, nullptr, - err)) { + if (verifierSafeParseAssemblyInto(buf->getMemBufferRef(), err)) { err.print("\n", llvm::errs()); llvm::errs() << "\n"; error("llvm assembly parse error"); @@ -4462,6 +4477,9 @@ llvm::TargetMachine *initLLVM(llvm::StringRef targetTriple, llvm::sys::path::parent_path(absFileName)), "ceramic compiler " CERAMIC_COMPILER_VERSION, optLevel > 0, flags, 0); + llvmModule->addModuleFlag(llvm::Module::Warning, "Debug Info Version", + llvm::DEBUG_METADATA_VERSION); + llvmModule->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 4); } else { llvmDIBuilder = nullptr; llvmDICompileUnit = nullptr; diff --git a/compiler/types.cpp b/compiler/types.cpp index fa7e2ab68..3bddc8c64 100644 --- a/compiler/types.cpp +++ b/compiler/types.cpp @@ -1318,9 +1318,7 @@ static void declareLLVMType(TypePtr t) { declareLLVMType(reprType); t->llType = reprType->llType; if (llvmDIBuilder != nullptr) - t->debugInfo.reset(llvmDIBuilder->createReplaceableCompositeType( - llvm::dwarf::DW_TAG_structure_type, typeName(t), - /*Scope=*/nullptr, /*File=*/nullptr, /*Line=*/0)); + t->debugInfo.reset(reprType->getDebugInfo()); break; } default: @@ -1633,13 +1631,8 @@ static void defineLLVMType(TypePtr t) { declareLLVMType(reprType); if (!reprType->defined) defineLLVMType(reprType); - - if (llvmDIBuilder != nullptr) { - llvm::MDNode *placeholderNode = x->getDebugInfo(); - if (placeholderNode) - placeholderNode->replaceAllUsesWith( - llvmTypeDebugInfo(reprType)); - } + if (llvmDIBuilder != nullptr) + t->debugInfo.reset(reprType->getDebugInfo()); break; } default: @@ -1682,16 +1675,33 @@ void materializeDebugInfoForTypes() { if (llvmDIBuilder == nullptr) return; - auto sweep = [](auto ®istry) { + bool changed = true; + while (changed) { + changed = false; + auto sweep = [&](auto ®istry) { + for (auto &bucket : registry) + for (auto &t : bucket) + if (t->llType != nullptr && !t->defined) { + llvmType(t.ptr()); + changed = true; + } + }; + + sweep(recordTypes); + sweep(tupleTypes); + sweep(unionTypes); + sweep(variantTypes); + } + + auto resolveCycles = [](auto ®istry) { for (auto &bucket : registry) for (auto &t : bucket) - if (t->llType != nullptr && !t->defined) - llvmType(t.ptr()); + if (t->debugInfo && !t->debugInfo->isResolved()) + t->debugInfo->resolveCycles(); }; - - sweep(recordTypes); - sweep(tupleTypes); - sweep(unionTypes); - sweep(variantTypes); + resolveCycles(recordTypes); + resolveCycles(tupleTypes); + resolveCycles(unionTypes); + resolveCycles(variantTypes); } } // namespace ceramic