9878662e8a
- Add patch to fix ARM builds: * ldc-1.9.0-fix_arm_build.patch - Update to 1.9.0 and use 0.17.5 to bootstrap - Add patch to fix rpmlint error: * ldc-0.17.5-add_missing_include.patch - Add patches to add LLVM6 support: * ldc-0.17.5-add_support_to_LLVM6.patch * ldc-0.17.5-backport_pr_2315.patch - Add patch to be able to use ldc: * ldc-0.17.5-default-to-pic.patch - update to version 0.17.5: * Added LLVM 5.0 support. * druntime: fixes for Android and addition of core.math.yl2x[p1]() for x86(_64) targets. * dmd-testsuite: backported runnable/cppa.d fix for GCC > 5. * CI updates. OBS-URL: https://build.opensuse.org/request/show/614484 OBS-URL: https://build.opensuse.org/package/show/devel:languages:D/ldc?expand=0&rev=14
434 lines
17 KiB
Diff
434 lines
17 KiB
Diff
From 6ed3ce435845e72ce8c88d39c0f7d3fb950ef54e Mon Sep 17 00:00:00 2001
|
|
From: Johan Engelen <jbc.engelen@gmail.com>
|
|
Date: Mon, 18 Sep 2017 23:11:32 +0200
|
|
Subject: [PATCH] Backport PR #2315.
|
|
|
|
The change is to fix debuginfo build errors with Phobos and LLVM5.0. This PR is mostly copy-pasting from master and fixing compile errors, so not much checking whether things make sense or not for LTS.
|
|
---
|
|
gen/dibuilder.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++++----------
|
|
gen/dibuilder.h | 13 +++++--
|
|
gen/functions.cpp | 11 +++---
|
|
gen/nested.cpp | 103 ++++++++++++++++++++++++++++-------------------------
|
|
4 files changed, 159 insertions(+), 72 deletions(-)
|
|
|
|
diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp
|
|
index f322811ea..1bc9c47c2 100644
|
|
--- a/gen/dibuilder.cpp
|
|
+++ b/gen/dibuilder.cpp
|
|
@@ -62,7 +62,9 @@ Module *ldc::DIBuilder::getDefinedModule(Dsymbol *s) {
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ldc::DIBuilder::DIBuilder(IRState *const IR)
|
|
- : IR(IR), DBuilder(IR->module), CUNode(nullptr) {}
|
|
+ : IR(IR), DBuilder(IR->module), CUNode(nullptr),
|
|
+ isTargetMSVCx64(global.params.targetTriple.isWindowsMSVCEnvironment() &&
|
|
+ global.params.targetTriple.isArch64Bit()) {}
|
|
|
|
llvm::LLVMContext &ldc::DIBuilder::getContext() { return IR->context(); }
|
|
|
|
@@ -75,7 +77,7 @@ ldc::DIScope ldc::DIBuilder::GetCurrentScope() {
|
|
return fn->diLexicalBlocks.top();
|
|
}
|
|
|
|
-void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *var,
|
|
+void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *storage,
|
|
ldc::DILocalVariable divar
|
|
#if LDC_LLVM_VER >= 306
|
|
,
|
|
@@ -83,19 +85,42 @@ void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *var,
|
|
#endif
|
|
) {
|
|
unsigned charnum = (loc.linnum ? loc.charnum : 0);
|
|
+ auto debugLoc = llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope());
|
|
#if LDC_LLVM_VER < 307
|
|
- llvm::Instruction *instr = DBuilder.insertDeclare(var, divar,
|
|
+ llvm::Instruction *instr = DBuilder.insertDeclare(storage, divar,
|
|
#if LDC_LLVM_VER >= 306
|
|
diexpr,
|
|
#endif
|
|
IR->scopebb());
|
|
- instr->setDebugLoc(
|
|
- llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope()));
|
|
+ instr->setDebugLoc(debugLoc);
|
|
+#else // if LLVM >= 3.7
|
|
+ DBuilder.insertDeclare(storage, divar, diexpr, debugLoc, IR->scopebb());
|
|
+#endif
|
|
+}
|
|
+
|
|
+// Sets the (current) value for a debuginfo variable.
|
|
+void ldc::DIBuilder::SetValue(const Loc &loc, llvm::Value *value,
|
|
+ ldc::DILocalVariable divar
|
|
+#if LDC_LLVM_VER >= 306
|
|
+ ,
|
|
+ ldc::DIExpression diexpr
|
|
+#endif
|
|
+ ) {
|
|
+ unsigned charnum = (loc.linnum ? loc.charnum : 0);
|
|
+ auto debugLoc = llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope());
|
|
+#if LDC_LLVM_VER < 307
|
|
+ llvm::Instruction *instr = DBuilder.insertDbgValueIntrinsic(value, divar,
|
|
+#if LDC_LLVM_VER >= 306
|
|
+ diexpr,
|
|
+#endif
|
|
+ IR->scopebb());
|
|
+ instr->setDebugLoc(debugLoc);
|
|
#else // if LLVM >= 3.7
|
|
- DBuilder.insertDeclare(
|
|
- var, divar, diexpr,
|
|
- llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope()),
|
|
- IR->scopebb());
|
|
+ DBuilder.insertDbgValueIntrinsic(value,
|
|
+#if LDC_LLVM_VER < 600
|
|
+ 0,
|
|
+#endif
|
|
+ divar, diexpr, debugLoc, IR->scopebb());
|
|
#endif
|
|
}
|
|
|
|
@@ -852,6 +877,7 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) {
|
|
|
|
void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
|
Type *type, bool isThisPtr,
|
|
+ bool forceAsLocal, bool isRefRVal,
|
|
#if LDC_LLVM_VER >= 306
|
|
llvm::ArrayRef<int64_t> addr
|
|
#else
|
|
@@ -872,13 +898,46 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
|
}
|
|
|
|
// get type description
|
|
- ldc::DIType TD = CreateTypeDescription(type ? type : vd->type, true);
|
|
+ if (!type)
|
|
+ type = vd->type;
|
|
+ ldc::DIType TD = CreateTypeDescription(type, true);
|
|
if (static_cast<llvm::MDNode *>(TD) == nullptr) {
|
|
return; // unsupported
|
|
}
|
|
|
|
- if (vd->storage_class & (STCref | STCout)) {
|
|
+ const bool isRefOrOut = vd->isRef() || vd->isOut(); // incl. special-ref vars
|
|
+
|
|
+ // For MSVC x64 targets, declare params rewritten by ExplicitByvalRewrite as
|
|
+ // DI references, as if they were ref parameters.
|
|
+ const bool isPassedExplicitlyByval =
|
|
+ isTargetMSVCx64 && !isRefOrOut && isaArgument(ll) && addr.empty();
|
|
+
|
|
+ bool useDbgValueIntrinsic = false;
|
|
+ if (isRefOrOut || isPassedExplicitlyByval) {
|
|
+ // With the exception of special-ref loop variables, the reference/pointer
|
|
+ // itself is constant. So we don't have to attach the debug information to a
|
|
+ // memory location and can use llvm.dbg.value to set the constant pointer
|
|
+ // for the DI reference.
|
|
+ useDbgValueIntrinsic =
|
|
+ isPassedExplicitlyByval || (!isSpecialRefVar(vd) && isRefRVal);
|
|
+#if LDC_LLVM_VER >= 308
|
|
+ // Note: createReferenceType expects the size to be the size of a pointer,
|
|
+ // not the size of the type the reference refers to.
|
|
+ TD = DBuilder.createReferenceType(
|
|
+ llvm::dwarf::DW_TAG_reference_type, TD,
|
|
+ gDataLayout->getPointerSizeInBits(), // size (bits)
|
|
+ DtoAlignment(type) * 8); // align (bits)
|
|
+#else
|
|
TD = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, TD);
|
|
+#endif
|
|
+ } else {
|
|
+ // FIXME: For MSVC x64 targets, declare dynamic array and vector parameters
|
|
+ // as DI locals to work around garbage for both cdb and VS debuggers.
|
|
+ if (isTargetMSVCx64) {
|
|
+ TY ty = type->toBasetype()->ty;
|
|
+ if (ty == Tarray || ty == Tvector)
|
|
+ forceAsLocal = true;
|
|
+ }
|
|
}
|
|
|
|
// get variable description
|
|
@@ -886,7 +945,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
|
|
|
#if LDC_LLVM_VER < 308
|
|
unsigned tag;
|
|
- if (vd->isParameter()) {
|
|
+ if (!forceAsLocal && vd->isParameter()) {
|
|
tag = llvm::dwarf::DW_TAG_arg_variable;
|
|
} else {
|
|
tag = llvm::dwarf::DW_TAG_auto_variable;
|
|
@@ -930,7 +989,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
|
Flags // flags
|
|
);
|
|
#else
|
|
- if (vd->isParameter()) {
|
|
+ if (!forceAsLocal && vd->isParameter()) {
|
|
FuncDeclaration *fd = vd->parent->isFuncDeclaration();
|
|
assert(fd);
|
|
size_t argNo = 0;
|
|
@@ -970,14 +1029,23 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
|
#endif
|
|
variableMap[vd] = debugVariable;
|
|
|
|
-// declare
|
|
+ if (useDbgValueIntrinsic) {
|
|
#if LDC_LLVM_VER >= 306
|
|
- Declare(vd->loc, ll, debugVariable, addr.empty()
|
|
- ? DBuilder.createExpression()
|
|
- : DBuilder.createExpression(addr));
|
|
+ SetValue(vd->loc, ll, debugVariable,
|
|
+ addr.empty() ? DBuilder.createExpression()
|
|
+ : DBuilder.createExpression(addr));
|
|
#else
|
|
- Declare(vd->loc, ll, debugVariable);
|
|
+ SetValue(vd->loc, ll, debugVariable);
|
|
#endif
|
|
+ } else {
|
|
+#if LDC_LLVM_VER >= 306
|
|
+ Declare(vd->loc, ll, debugVariable,
|
|
+ addr.empty() ? DBuilder.createExpression()
|
|
+ : DBuilder.createExpression(addr));
|
|
+#else
|
|
+ Declare(vd->loc, ll, debugVariable);
|
|
+#endif
|
|
+ }
|
|
}
|
|
|
|
void
|
|
diff --git a/gen/dibuilder.h b/gen/dibuilder.h
|
|
index fbfa830da..8fc5dea6c 100644
|
|
--- a/gen/dibuilder.h
|
|
+++ b/gen/dibuilder.h
|
|
@@ -79,6 +79,8 @@ class DIBuilder {
|
|
const llvm::MDNode *CUNode;
|
|
#endif
|
|
|
|
+ const bool isTargetMSVCx64;
|
|
+
|
|
DICompileUnit GetCU() {
|
|
#if LDC_LLVM_VER >= 307
|
|
return CUNode;
|
|
@@ -133,7 +135,8 @@ class DIBuilder {
|
|
/// \param addr An array of complex address operations.
|
|
void
|
|
EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Type *type = nullptr,
|
|
- bool isThisPtr = false,
|
|
+ bool isThisPtr = false, bool forceAsLocal = false,
|
|
+ bool isRefRVal = false,
|
|
#if LDC_LLVM_VER >= 306
|
|
llvm::ArrayRef<int64_t> addr = llvm::ArrayRef<int64_t>()
|
|
#else
|
|
@@ -155,12 +158,18 @@ class DIBuilder {
|
|
llvm::LLVMContext &getContext();
|
|
Module *getDefinedModule(Dsymbol *s);
|
|
DIScope GetCurrentScope();
|
|
- void Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar
|
|
+ void Declare(const Loc &loc, llvm::Value *storage, ldc::DILocalVariable divar
|
|
#if LDC_LLVM_VER >= 306
|
|
,
|
|
ldc::DIExpression diexpr
|
|
#endif
|
|
);
|
|
+ void SetValue(const Loc &loc, llvm::Value *value, ldc::DILocalVariable divar
|
|
+#if LDC_LLVM_VER >= 306
|
|
+ ,
|
|
+ ldc::DIExpression diexpr
|
|
+#endif
|
|
+ );
|
|
void AddBaseFields(ClassDeclaration *sd, ldc::DIFile file,
|
|
#if LDC_LLVM_VER >= 306
|
|
std::vector<llvm::Metadata *> &elems
|
|
diff --git a/gen/functions.cpp b/gen/functions.cpp
|
|
index 796124db4..107779ecd 100644
|
|
--- a/gen/functions.cpp
|
|
+++ b/gen/functions.cpp
|
|
@@ -861,10 +861,13 @@ void DtoDefineFunction(FuncDeclaration *fd) {
|
|
++llArgIdx;
|
|
}
|
|
|
|
- if (global.params.symdebug &&
|
|
- !(isaArgument(irparam->value) &&
|
|
- isaArgument(irparam->value)->hasByValAttr())) {
|
|
- gIR->DBuilder.EmitLocalVariable(irparam->value, vd, debugInfoType);
|
|
+ // The debuginfos for captured params are handled later by
|
|
+ // DtoCreateNestedContext().
|
|
+ if (global.params.symdebug && vd->nestedrefs.dim == 0) {
|
|
+ // Reference (ref/out) parameters have no storage themselves as they are
|
|
+ // constant pointers, so pass the reference rvalue to EmitLocalVariable().
|
|
+ gIR->DBuilder.EmitLocalVariable(irparam->value, vd, debugInfoType,
|
|
+ false, false, /*isRefRVal=*/true);
|
|
}
|
|
}
|
|
}
|
|
diff --git a/gen/nested.cpp b/gen/nested.cpp
|
|
index 2a13a1aa6..2b72f9873 100644
|
|
--- a/gen/nested.cpp
|
|
+++ b/gen/nested.cpp
|
|
@@ -58,14 +58,13 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
|
|
|
// Check whether we can access the needed frame
|
|
FuncDeclaration *fd = irfunc->decl;
|
|
- while (fd != vdparent) {
|
|
- if (fd->isStatic()) {
|
|
- error(loc, "function %s cannot access frame of function %s",
|
|
- irfunc->decl->toPrettyChars(), vdparent->toPrettyChars());
|
|
- return new DVarValue(astype, llvm::UndefValue::get(DtoPtrToType(astype)));
|
|
- }
|
|
+ while (fd && fd != vdparent) {
|
|
fd = getParentFunc(fd, false);
|
|
- assert(fd);
|
|
+ }
|
|
+ if (!fd) {
|
|
+ error(loc, "function %s cannot access frame of function %s",
|
|
+ irfunc->decl->toPrettyChars(), vdparent->toPrettyChars());
|
|
+ return new DVarValue(astype, llvm::UndefValue::get(DtoPtrToType(astype)));
|
|
}
|
|
|
|
// is the nested variable in this scope?
|
|
@@ -73,38 +72,32 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
|
return makeVarDValue(astype, vd);
|
|
}
|
|
|
|
- LLValue *dwarfValue = nullptr;
|
|
-#if LDC_LLVM_VER >= 306
|
|
- std::vector<int64_t> dwarfAddr;
|
|
-#else
|
|
- std::vector<LLValue *> dwarfAddr;
|
|
-#endif
|
|
-
|
|
// get the nested context
|
|
LLValue *ctx = nullptr;
|
|
- if (irfunc->nestedVar) {
|
|
- // If this function has its own nested context struct, always load it.
|
|
- ctx = irfunc->nestedVar;
|
|
- dwarfValue = ctx;
|
|
+ bool skipDIDeclaration = false;
|
|
+ auto currentCtx = irfunc->nestedVar;
|
|
+ if (currentCtx) {
|
|
+ Logger::println("Using own nested context of current function");
|
|
+ ctx = currentCtx;
|
|
} else if (irfunc->decl->isMember2()) {
|
|
- // If this is a member function of a nested class without its own
|
|
- // context, load the vthis member.
|
|
+ Logger::println(
|
|
+ "Current function is member of nested class, loading vthis");
|
|
+
|
|
AggregateDeclaration *cd = irfunc->decl->isMember2();
|
|
LLValue *val = irfunc->thisArg;
|
|
if (cd->isClassDeclaration()) {
|
|
val = DtoLoad(val);
|
|
}
|
|
ctx = DtoLoad(DtoGEPi(val, 0, getVthisIdx(cd), ".vthis"));
|
|
+ skipDIDeclaration = true;
|
|
} else {
|
|
- // Otherwise, this is a simple nested function, load from the context
|
|
- // argument.
|
|
+ Logger::println("Regular nested function, loading context arg");
|
|
+
|
|
ctx = DtoLoad(irfunc->nestArg);
|
|
- dwarfValue = irfunc->nestArg;
|
|
- if (global.params.symdebug) {
|
|
- gIR->DBuilder.OpDeref(dwarfAddr);
|
|
- }
|
|
}
|
|
+
|
|
assert(ctx);
|
|
+ IF_LOG { Logger::cout() << "Context: " << *ctx << '\n'; }
|
|
|
|
DtoCreateNestedContextType(vdparent->isFuncDeclaration());
|
|
assert(isIrLocalCreated(vd));
|
|
@@ -112,11 +105,9 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
|
////////////////////////////////////
|
|
// Extract variable from nested context
|
|
|
|
- LLValue *val = DtoBitCast(ctx, LLPointerType::getUnqual(irfunc->frameType));
|
|
- IF_LOG {
|
|
- Logger::cout() << "Context: " << *val << '\n';
|
|
- Logger::cout() << "of type: " << *irfunc->frameType << '\n';
|
|
- }
|
|
+ const auto frameType = LLPointerType::getUnqual(irfunc->frameType);
|
|
+ IF_LOG { Logger::cout() << "casting to: " << *irfunc->frameType << '\n'; }
|
|
+ LLValue *val = DtoBitCast(ctx, frameType);
|
|
|
|
IrLocal *const irLocal = getIrLocal(vd);
|
|
const auto vardepth = irLocal->nestedDepth;
|
|
@@ -135,10 +126,6 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
|
IF_LOG Logger::println("Same depth");
|
|
} else {
|
|
// Load frame pointer and index that...
|
|
- if (dwarfValue && global.params.symdebug) {
|
|
- gIR->DBuilder.OpOffset(dwarfAddr, val, vardepth);
|
|
- gIR->DBuilder.OpDeref(dwarfAddr);
|
|
- }
|
|
IF_LOG Logger::println("Lower depth");
|
|
val = DtoGEPi(val, 0, vardepth);
|
|
IF_LOG Logger::cout() << "Frame index: " << *val << '\n';
|
|
@@ -150,27 +137,42 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
|
const auto idx = irLocal->nestedIndex;
|
|
assert(idx != -1 && "Nested context not yet resolved for variable.");
|
|
|
|
- if (dwarfValue && global.params.symdebug) {
|
|
- gIR->DBuilder.OpOffset(dwarfAddr, val, idx);
|
|
- }
|
|
+#if LDC_LLVM_VER >= 306
|
|
+ std::vector<int64_t> dwarfAddrOps;
|
|
+#else
|
|
+ std::vector<LLValue *> dwarfAddrOps;
|
|
+#endif
|
|
|
|
- val = DtoGEPi(val, 0, idx, vd->toChars());
|
|
+ LLValue *gep = DtoGEPi(val, 0, idx, vd->toChars());
|
|
+ val = gep;
|
|
IF_LOG {
|
|
Logger::cout() << "Addr: " << *val << '\n';
|
|
Logger::cout() << "of type: " << *val->getType() << '\n';
|
|
}
|
|
- if (byref || (vd->isParameter() && getIrParameter(vd)->arg &&
|
|
- getIrParameter(vd)->arg->byref)) {
|
|
+ const bool isRefOrOut = vd->isRef() || vd->isOut();
|
|
+ if (isSpecialRefVar(vd)) {
|
|
+ // Handled appropriately by makeVarDValue() and EmitLocalVariable(), pass
|
|
+ // storage of pointer (reference lvalue).
|
|
+ } else if (byref || isRefOrOut) {
|
|
val = DtoAlignedLoad(val);
|
|
- // dwarfOpDeref(dwarfAddr);
|
|
+ // ref/out variables get a reference-debuginfo-type in EmitLocalVariable();
|
|
+ // pass the GEP as reference lvalue in that case.
|
|
+ if (!isRefOrOut)
|
|
+ gIR->DBuilder.OpDeref(dwarfAddrOps);
|
|
IF_LOG {
|
|
Logger::cout() << "Was byref, now: " << *irLocal->value << '\n';
|
|
Logger::cout() << "of type: " << *irLocal->value->getType() << '\n';
|
|
}
|
|
}
|
|
|
|
- if (dwarfValue && global.params.symdebug) {
|
|
- gIR->DBuilder.EmitLocalVariable(dwarfValue, vd, nullptr, false, dwarfAddr);
|
|
+ if (!skipDIDeclaration && global.params.symdebug) {
|
|
+#if LDC_LLVM_VER < 500
|
|
+ // Because we are passing a GEP instead of an alloca to
|
|
+ // llvm.dbg.declare, we have to make the address dereference explicit.
|
|
+ gIR->DBuilder.OpDeref(dwarfAddrOps);
|
|
+#endif
|
|
+ gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false,
|
|
+ /*forceAsLocal=*/true, false, dwarfAddrOps);
|
|
}
|
|
|
|
return makeVarDValue(astype, vd, val);
|
|
@@ -532,12 +534,17 @@ void DtoCreateNestedContext(FuncDeclaration *fd) {
|
|
|
|
if (global.params.symdebug) {
|
|
#if LDC_LLVM_VER >= 306
|
|
- LLSmallVector<int64_t, 2> addr;
|
|
+ LLSmallVector<int64_t, 2> dwarfAddrOps;
|
|
#else
|
|
- LLSmallVector<LLValue *, 2> addr;
|
|
+ LLSmallVector<LLValue *, 2> dwarfAddrOps;
|
|
+#endif
|
|
+#if LDC_LLVM_VER < 500
|
|
+ // Because we are passing a GEP instead of an alloca to
|
|
+ // llvm.dbg.declare, we have to make the address dereference explicit.
|
|
+ gIR->DBuilder.OpDeref(dwarfAddrOps);
|
|
#endif
|
|
- gIR->DBuilder.OpOffset(addr, frameType, irLocal->nestedIndex);
|
|
- gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, addr);
|
|
+ gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, false, false,
|
|
+ dwarfAddrOps);
|
|
}
|
|
}
|
|
}
|