Index: lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -395,6 +395,10 @@ assert(LocationKind != Register); emitOp(dwarf::DW_OP_xderef); break; + case dwarf::DW_OP_deref_size: + emitOp(dwarf::DW_OP_deref_size); + emitUnsigned(Op->getArg(0)); + break; default: llvm_unreachable("unhandled opcode found in expression"); } Index: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ lib/CodeGen/PrologEpilogInserter.cpp @@ -1094,12 +1094,33 @@ assert(i == 0 && "Frame indices can only appear as the first " "operand of a DBG_VALUE machine instruction"); unsigned Reg; + MachineFrameInfo &MFI = MF.getFrameInfo(); + unsigned FrameIdx = MI.getOperand(0).getIndex(); + unsigned Size = MFI.getObjectSize(FrameIdx); + int64_t Offset = - TFI->getFrameIndexReference(MF, MI.getOperand(0).getIndex(), Reg); + TFI->getFrameIndexReference(MF, FrameIdx, Reg); MI.getOperand(0).ChangeToRegister(Reg, false /*isDef*/); MI.getOperand(0).setIsDebug(); - auto *DIExpr = DIExpression::prepend(MI.getDebugExpression(), - DIExpression::NoDeref, Offset); + + const DIExpression *DIExpr = MI.getDebugExpression(); + auto isImplicit = [](const DIExpression &Exp) { + if (Exp.isValid()) + for (auto I : Exp.expr_ops()) { + if (I.getOp() == dwarf::DW_OP_stack_value) + return true; + } + return false; + }; + + // If we already have a Implicit location expression we need to insert + // a deref before preprending a Memory location expression. + if (isImplicit(*DIExpr)) { + SmallVector Ops = { + dwarf::DW_OP_deref_size, Size}; + DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, DIExpression::WithStackValue); + } + DIExpr = DIExpression::prepend(DIExpr, DIExpression::NoDeref, Offset); MI.getOperand(3).setMetadata(DIExpr); continue; } Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -817,6 +817,7 @@ return 3; case dwarf::DW_OP_constu: case dwarf::DW_OP_plus_uconst: + case dwarf::DW_OP_deref_size: return 2; default: return 1; @@ -871,6 +872,7 @@ case dwarf::DW_OP_shr: case dwarf::DW_OP_shra: case dwarf::DW_OP_deref: + case dwarf::DW_OP_deref_size: case dwarf::DW_OP_xderef: case dwarf::DW_OP_lit0: case dwarf::DW_OP_not: Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1717,7 +1717,7 @@ /// changes are made. static bool rewriteDebugUsers( Instruction &From, Value &To, Instruction &DomPoint, DominatorTree &DT, - function_ref RewriteExpr) { + function_ref RewriteExpr) { // Find debug users of From. SmallVector Users; findDbgUsers(Users, &From); @@ -1751,15 +1751,8 @@ if (DeleteOrSalvage.count(DII)) continue; - LLVMContext &Ctx = DII->getContext(); - DbgValReplacement DVR = RewriteExpr(*DII); - if (!DVR) - continue; - - DII->setOperand(0, wrapValueInMetadata(Ctx, &To)); - DII->setOperand(2, MetadataAsValue::get(Ctx, *DVR)); - LLVM_DEBUG(dbgs() << "REWRITE: " << *DII << '\n'); - Changed = true; + if (RewriteExpr(*DII)) + Changed = true; } if (!DeleteOrSalvage.empty()) { @@ -1815,8 +1808,16 @@ Type *FromTy = From.getType(); Type *ToTy = To.getType(); - auto Identity = [&](DbgVariableIntrinsic &DII) -> DbgValReplacement { - return DII.getExpression(); + auto Identity = [&](DbgVariableIntrinsic &DII) -> bool { + LLVMContext &Ctx = DII.getContext(); + DbgValReplacement DVR = DII.getExpression(); + if (!DVR) + return false; + + DII.setOperand(0, wrapValueInMetadata(Ctx, &To)); + DII.setOperand(2, MetadataAsValue::get(Ctx, *DVR)); + LLVM_DEBUG(dbgs() << "REWRITE: " << DII << '\n'); + return true; }; // Handle no-op conversions. @@ -1839,30 +1840,67 @@ // The width of the result has shrunk. Use sign/zero extension to describe // the source variable's high bits. - auto SignOrZeroExt = [&](DbgVariableIntrinsic &DII) -> DbgValReplacement { + auto SignOrZeroExt = [&](DbgVariableIntrinsic &DII) -> bool { DILocalVariable *Var = DII.getVariable(); // Without knowing signedness, sign/zero extension isn't possible. auto Signedness = Var->getSignedness(); if (!Signedness) - return None; + return false; bool Signed = *Signedness == DIBasicType::Signedness::Signed; + LLVMContext &Ctx = DII.getContext(); + DbgValReplacement Orig = DII.getExpression(); + if (!Orig) + return false; - if (!Signed) { - // In the unsigned case, assume that a debugger will initialize the - // high bits to 0 and do a no-op conversion. - return Identity(DII); + DII.setOperand(0, wrapValueInMetadata(Ctx, &To)); + + unsigned FEBitOffset, FEBitSize, ExtFEBitOffset, ExtFEBitSize; + const DataLayout &DL = M.getDataLayout(); + const unsigned BitsPerByte = 8; + FEBitSize = ToBits; + ExtFEBitSize = FromBits - ToBits; + if (DL.isLittleEndian()) { + FEBitOffset = 0; + ExtFEBitOffset = FEBitSize; + } else { + FEBitOffset = ExtFEBitSize; + ExtFEBitOffset = 0; + } + + if (auto OrigFI = (*Orig)->getFragmentInfo()) { + // TODO: Handle fragments of fragments. + return false; + } + + // The low bits remain as they were. + auto FE = DIExpression::createFragmentExpression(*Orig, FEBitOffset, FEBitSize); + DII.setOperand(2, MetadataAsValue::get(Ctx, *FE)); + + // The high bits are either zero or sign extended. + DIExpression *Ext; + if (Signed) { + SmallVector SextOps({dwarf::DW_OP_constu, (ToBits - 1), + dwarf::DW_OP_shr, + dwarf::DW_OP_constu, 1, + dwarf::DW_OP_and, + dwarf::DW_OP_lit0, + dwarf::DW_OP_not, + dwarf::DW_OP_mul}); + Ext = DIExpression::appendToStack(*Orig, SextOps); } else { - // In the signed case, the high bits are given by sign extension, i.e: - // (To >> (ToBits - 1)) * ((2 ^ FromBits) - 1) - // Calculate the high bits and OR them together with the low bits. - SmallVector Ops({dwarf::DW_OP_dup, dwarf::DW_OP_constu, - (ToBits - 1), dwarf::DW_OP_shr, - dwarf::DW_OP_lit0, dwarf::DW_OP_not, - dwarf::DW_OP_mul, dwarf::DW_OP_or}); - return DIExpression::appendToStack(DII.getExpression(), Ops); + SmallVector ZextOps({dwarf::DW_OP_lit0}); + Ext = DIExpression::appendToStack(*Orig, ZextOps); + } + for (unsigned I = 0, E = ExtFEBitSize/BitsPerByte; I < E; ++I) { + Instruction &ExtDII = *DII.clone(); + ExtDII.insertAfter(&DII); + auto ExtFE = DIExpression::createFragmentExpression(Ext, ExtFEBitOffset + I*BitsPerByte, BitsPerByte); + ExtDII.setOperand(2, MetadataAsValue::get(Ctx, *ExtFE)); } + + return true; }; return rewriteDebugUsers(From, To, DomPoint, DT, SignOrZeroExt); } Index: test/Transforms/InstCombine/cast-set-preserve-signed-dbg-val.ll =================================================================== --- test/Transforms/InstCombine/cast-set-preserve-signed-dbg-val.ll +++ test/Transforms/InstCombine/cast-set-preserve-signed-dbg-val.ll @@ -13,8 +13,9 @@ ; Preserve the dbg.value for the DCE'd 32-bit 'and'. ; ; The high 16 bits of the original 'and' require sign-extending the new 16-bit and: - ; CHECK-NEXT: call void @llvm.dbg.value(metadata i16 [[and]], metadata [[C:![0-9]+]], - ; CHECK-SAME: metadata !DIExpression(DW_OP_dup, DW_OP_constu, 15, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value) + ; CHECK-NEXT: call void @llvm.dbg.value(metadata i16 [[and]], metadata [[C:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 16)), !dbg !12 + ; CHECK-NEXT: call void @llvm.dbg.value(metadata i16 [[and]], metadata [[C]], metadata !DIExpression(DW_OP_constu, 15, DW_OP_shr, DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 24, 8)), !dbg !12 + ; CHECK-NEXT: call void @llvm.dbg.value(metadata i16 [[and]], metadata [[C]], metadata !DIExpression(DW_OP_constu, 15, DW_OP_shr, DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 16, 8)), !dbg !12 %D = trunc i32 %C to i16, !dbg !42 call void @llvm.dbg.value(metadata i16 %D, metadata !38, metadata !DIExpression()), !dbg !42 Index: unittests/Transforms/Utils/LocalTest.cpp =================================================================== --- unittests/Transforms/Utils/LocalTest.cpp +++ unittests/Transforms/Utils/LocalTest.cpp @@ -777,7 +777,7 @@ SmallVector ADbgVals; findDbgValues(ADbgVals, &A); - EXPECT_EQ(6U, ADbgVals.size()); + EXPECT_EQ(18U, ADbgVals.size()); // Check that %a has a dbg.value with a DIExpression matching \p Ops. auto hasADbgVal = [&](ArrayRef Ops) { @@ -788,31 +788,69 @@ }; // Case 1: The original expr is empty, so no deref is needed. - EXPECT_TRUE(hasADbgVal({DW_OP_dup, DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, - DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value})); + EXPECT_TRUE(hasADbgVal({DW_OP_constu, 31, DW_OP_shr, DW_OP_constu, 1, + DW_OP_and, DW_OP_lit0, DW_OP_not, DW_OP_mul, + DW_OP_stack_value, DW_OP_LLVM_fragment, 56, 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_constu, 31, DW_OP_shr, DW_OP_constu, 1, + DW_OP_and, DW_OP_lit0, DW_OP_not, DW_OP_mul, + DW_OP_stack_value, DW_OP_LLVM_fragment, 48, 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_constu, 31, DW_OP_shr, DW_OP_constu, 1, + DW_OP_and, DW_OP_lit0, DW_OP_not, DW_OP_mul, + DW_OP_stack_value, DW_OP_LLVM_fragment, 40, 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_constu, 31, DW_OP_shr, DW_OP_constu, 1, + DW_OP_and, DW_OP_lit0, DW_OP_not, DW_OP_mul, + DW_OP_stack_value, DW_OP_LLVM_fragment, 32, 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_LLVM_fragment, 0, 32})); // Case 2: Perform an address calculation with the original expr, deref it, // then sign-extend the result. - EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_dup, - DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, DW_OP_not, - DW_OP_mul, DW_OP_or, DW_OP_stack_value})); + EXPECT_TRUE(hasADbgVal({ DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_constu, + 31, DW_OP_shr, DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, + DW_OP_not, DW_OP_mul, DW_OP_stack_value, + DW_OP_LLVM_fragment, 56, 8})); + EXPECT_TRUE(hasADbgVal({ DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_constu, + 31, DW_OP_shr, DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, + DW_OP_not, DW_OP_mul, DW_OP_stack_value, + DW_OP_LLVM_fragment, 48, 8})); + EXPECT_TRUE(hasADbgVal({ DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_constu, + 31, DW_OP_shr, DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, + DW_OP_not, DW_OP_mul, DW_OP_stack_value, + DW_OP_LLVM_fragment, 40, 8})); + EXPECT_TRUE(hasADbgVal({ DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_constu, + 31, DW_OP_shr, DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, + DW_OP_not, DW_OP_mul, DW_OP_stack_value, + DW_OP_LLVM_fragment, 32, 8})); + EXPECT_TRUE(hasADbgVal({ DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_fragment, 0, + 32})); // Case 3: Insert the sign-extension logic before the DW_OP_stack_value. - EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_dup, DW_OP_constu, 31, - DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, - DW_OP_stack_value})); - - // Cases 4-6: Just like cases 1-3, but preserve the fragment at the end. - EXPECT_TRUE(hasADbgVal({DW_OP_dup, DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, - DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value, - DW_OP_LLVM_fragment, 0, 8})); - EXPECT_TRUE( - hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_dup, DW_OP_constu, - 31, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, - DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); - EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_dup, DW_OP_constu, 31, - DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, - DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_constu, 31, DW_OP_shr, + DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, DW_OP_not, + DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 56, + 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_constu, 31, DW_OP_shr, + DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, DW_OP_not, + DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 48, + 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_constu, 31, DW_OP_shr, + DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, DW_OP_not, + DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 40, + 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_constu, 31, DW_OP_shr, + DW_OP_constu, 1, DW_OP_and, DW_OP_lit0, DW_OP_not, + DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 32, + 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_stack_value, + DW_OP_LLVM_fragment, 0, 32})); + + // Cases 4-6: Just like cases 1-3, but no transform as we abort on + // pre-existing fragment. + EXPECT_TRUE(hasADbgVal({DW_OP_LLVM_fragment, 0, 8})); + + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_fragment, 0, 8})); + + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_stack_value, + DW_OP_LLVM_fragment, 0, 8})); verifyModule(*M, &errs(), &BrokenDebugInfo); ASSERT_FALSE(BrokenDebugInfo);