Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1718,7 +1718,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); @@ -1752,15 +1752,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()) { @@ -1816,8 +1809,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. @@ -1840,30 +1841,57 @@ // 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)); + Instruction &ExtDII = *DII.clone(); + ExtDII.insertAfter(&DII); + + unsigned FEBitOffset, FEBitSize, ExtFEBitOffset, ExtFEBitSize; + if (M.getDataLayout().isLittleEndian()) { + FEBitOffset = 0; + FEBitSize = ToBits; + ExtFEBitOffset = ToBits; + ExtFEBitSize = FromBits - ToBits; } 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); + FEBitOffset = ToBits; + FEBitSize = FromBits - ToBits; + ExtFEBitOffset = 0; + ExtFEBitSize = ToBits; } + // 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_lit0, + dwarf::DW_OP_not, + dwarf::DW_OP_mul}); + Ext = DIExpression::appendToStack(*Orig, SextOps); + } else { + SmallVector ZextOps({dwarf::DW_OP_lit0}); + Ext = DIExpression::appendToStack(*Orig, ZextOps); + } + auto ExtFE = DIExpression::createFragmentExpression(Ext, ExtFEBitOffset, ExtFEBitSize); + ExtDII.setOperand(2, MetadataAsValue::get(Ctx, *ExtFE)); + + return true; }; return rewriteDebugUsers(From, To, DomPoint, DT, SignOrZeroExt); }