/// \return true if the materialization succeeded.
bool translate(const Constant &C, Register Reg);
+ /// Examine any debug-info attached to the instruction (in the form of
+ /// DPValues) and translate it.
+ void translateDbgInfo(const Instruction &Inst,
+ MachineIRBuilder &MIRBuilder);
+
+ /// Translate a debug-info record of a dbg.value into a DBG_* instruction.
+ /// Pass in all the contents of the record, rather than relying on how it's
+ /// stored.
+ void translateDbgValueRecord(Value *V, bool HasArgList,
+ const DILocalVariable *Variable,
+ const DIExpression *Expression, const DebugLoc &DL,
+ MachineIRBuilder &MIRBuilder);
+
+ /// Translate a debug-info record of a dbg.declare into an indirect DBG_*
+ /// instruction. Pass in all the contents of the record, rather than relying
+ /// on how it's stored.
+ void translateDbgDeclareRecord(Value *Address, bool HasArgList,
+ const DILocalVariable *Variable,
+ const DIExpression *Expression, const DebugLoc &DL,
+ MachineIRBuilder &MIRBuilder);
+
// Translate U as a copy of V.
bool translateCopy(const User &U, const Value &V,
MachineIRBuilder &MIRBuilder);
/// possible.
std::optional<MCRegister> getArgPhysReg(Argument &Arg);
- /// If DebugInst targets an Argument and its expression is an EntryValue,
- /// lower it as an entry in the MF debug table.
- bool translateIfEntryValueArgument(const DbgDeclareInst &DebugInst);
-
- /// If DebugInst targets an Argument and its expression is an EntryValue,
- /// lower as a DBG_VALUE targeting the corresponding livein register for that
- /// Argument.
- bool translateIfEntryValueArgument(const DbgValueInst &DebugInst,
+ /// If debug-info targets an Argument and its expression is an EntryValue,
+ /// lower it as either an entry in the MF debug table (dbg.declare), or a
+ /// DBG_VALUE targeting the corresponding livein register for that Argument
+ /// (dbg.value).
+ bool translateIfEntryValueArgument(bool isDeclare, Value *Arg,
+ const DILocalVariable *Var,
+ const DIExpression *Expr,
+ const DebugLoc &DL,
MachineIRBuilder &MIRBuilder);
bool translateInlineAsm(const CallBase &CB, MachineIRBuilder &MIRBuilder);
// they could have originated from constants, and we don't want a jumpy
// debug experience.
assert((CurrInst->getDebugLoc() == MI.getDebugLoc() ||
- (MI.getParent()->isEntryBlock() && !MI.getDebugLoc())) &&
+ (MI.getParent()->isEntryBlock() && !MI.getDebugLoc()) ||
+ (MI.isDebugInstr())) &&
"Line info was not transferred to all instructions");
}
};
return VRegDef->getOperand(1).getReg().asMCReg();
}
-bool IRTranslator::translateIfEntryValueArgument(const DbgValueInst &DebugInst,
+bool IRTranslator::translateIfEntryValueArgument(bool isDeclare, Value *Val,
+ const DILocalVariable *Var,
+ const DIExpression *Expr,
+ const DebugLoc &DL,
MachineIRBuilder &MIRBuilder) {
- auto *Arg = dyn_cast<Argument>(DebugInst.getValue());
+ auto *Arg = dyn_cast<Argument>(Val);
if (!Arg)
return false;
- const DIExpression *Expr = DebugInst.getExpression();
if (!Expr->isEntryValue())
return false;
std::optional<MCRegister> PhysReg = getArgPhysReg(*Arg);
if (!PhysReg) {
- LLVM_DEBUG(dbgs() << "Dropping dbg.value: expression is entry_value but "
- "couldn't find a physical register\n"
- << DebugInst << "\n");
+ LLVM_DEBUG(dbgs() << "Dropping dbg." << (isDeclare ? "declare" : "value")
+ << ": expression is entry_value but "
+ << "couldn't find a physical register\n");
+ LLVM_DEBUG(dbgs() << *Var << "\n");
return true;
}
- MIRBuilder.buildDirectDbgValue(*PhysReg, DebugInst.getVariable(),
- DebugInst.getExpression());
- return true;
-}
-
-bool IRTranslator::translateIfEntryValueArgument(
- const DbgDeclareInst &DebugInst) {
- auto *Arg = dyn_cast<Argument>(DebugInst.getAddress());
- if (!Arg)
- return false;
-
- const DIExpression *Expr = DebugInst.getExpression();
- if (!Expr->isEntryValue())
- return false;
-
- std::optional<MCRegister> PhysReg = getArgPhysReg(*Arg);
- if (!PhysReg)
- return false;
+ if (isDeclare) {
+ // Append an op deref to account for the fact that this is a dbg_declare.
+ Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
+ MF->setVariableDbgInfo(Var, Expr, *PhysReg, DL);
+ } else {
+ MIRBuilder.buildDirectDbgValue(*PhysReg, Var, Expr);
+ }
- // Append an op deref to account for the fact that this is a dbg_declare.
- Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
- MF->setVariableDbgInfo(DebugInst.getVariable(), Expr, *PhysReg,
- DebugInst.getDebugLoc());
return true;
}
case Intrinsic::dbg_declare: {
const DbgDeclareInst &DI = cast<DbgDeclareInst>(CI);
assert(DI.getVariable() && "Missing variable");
-
- const Value *Address = DI.getAddress();
- if (!Address || isa<UndefValue>(Address)) {
- LLVM_DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
- return true;
- }
-
- assert(DI.getVariable()->isValidLocationForIntrinsic(
- MIRBuilder.getDebugLoc()) &&
- "Expected inlined-at fields to agree");
- auto AI = dyn_cast<AllocaInst>(Address);
- if (AI && AI->isStaticAlloca()) {
- // Static allocas are tracked at the MF level, no need for DBG_VALUE
- // instructions (in fact, they get ignored if they *do* exist).
- MF->setVariableDbgInfo(DI.getVariable(), DI.getExpression(),
- getOrCreateFrameIndex(*AI), DI.getDebugLoc());
- return true;
- }
-
- if (translateIfEntryValueArgument(DI))
- return true;
-
- // A dbg.declare describes the address of a source variable, so lower it
- // into an indirect DBG_VALUE.
- MIRBuilder.buildIndirectDbgValue(getOrCreateVReg(*Address),
- DI.getVariable(), DI.getExpression());
+ translateDbgDeclareRecord(DI.getAddress(), DI.hasArgList(), DI.getVariable(),
+ DI.getExpression(), DI.getDebugLoc(), MIRBuilder);
return true;
}
case Intrinsic::dbg_label: {
case Intrinsic::dbg_value: {
// This form of DBG_VALUE is target-independent.
const DbgValueInst &DI = cast<DbgValueInst>(CI);
- const Value *V = DI.getValue();
- assert(DI.getVariable()->isValidLocationForIntrinsic(
- MIRBuilder.getDebugLoc()) &&
- "Expected inlined-at fields to agree");
- if (!V || DI.hasArgList()) {
- // DI cannot produce a valid DBG_VALUE, so produce an undef DBG_VALUE to
- // terminate any prior location.
- MIRBuilder.buildIndirectDbgValue(0, DI.getVariable(), DI.getExpression());
- return true;
- }
- if (const auto *CI = dyn_cast<Constant>(V)) {
- MIRBuilder.buildConstDbgValue(*CI, DI.getVariable(), DI.getExpression());
- return true;
- }
- if (auto *AI = dyn_cast<AllocaInst>(V);
- AI && AI->isStaticAlloca() && DI.getExpression()->startsWithDeref()) {
- // If the value is an alloca and the expression starts with a
- // dereference, track a stack slot instead of a register, as registers
- // may be clobbered.
- auto ExprOperands = DI.getExpression()->getElements();
- auto *ExprDerefRemoved =
- DIExpression::get(AI->getContext(), ExprOperands.drop_front());
- MIRBuilder.buildFIDbgValue(getOrCreateFrameIndex(*AI), DI.getVariable(),
- ExprDerefRemoved);
- return true;
- }
- if (translateIfEntryValueArgument(DI, MIRBuilder))
- return true;
- for (Register Reg : getOrCreateVRegs(*V)) {
- // FIXME: This does not handle register-indirect values at offset 0. The
- // direct/indirect thing shouldn't really be handled by something as
- // implicit as reg+noreg vs reg+imm in the first place, but it seems
- // pretty baked in right now.
- MIRBuilder.buildDirectDbgValue(Reg, DI.getVariable(), DI.getExpression());
- }
+ translateDbgValueRecord(DI.getValue(), DI.hasArgList(), DI.getVariable(),
+ DI.getExpression(), DI.getDebugLoc(), MIRBuilder);
return true;
}
case Intrinsic::uadd_with_overflow:
}
}
+void IRTranslator::translateDbgValueRecord(Value *V, bool HasArgList,
+ const DILocalVariable *Variable,
+ const DIExpression *Expression,
+ const DebugLoc &DL,
+ MachineIRBuilder &MIRBuilder) {
+ assert(Variable->isValidLocationForIntrinsic(DL) &&
+ "Expected inlined-at fields to agree");
+ // Act as if we're handling a debug intrinsic.
+ MIRBuilder.setDebugLoc(DL);
+
+ if (!V || HasArgList) {
+ // DI cannot produce a valid DBG_VALUE, so produce an undef DBG_VALUE to
+ // terminate any prior location.
+ MIRBuilder.buildIndirectDbgValue(0, Variable, Expression);
+ return;
+ }
+
+ if (const auto *CI = dyn_cast<Constant>(V)) {
+ MIRBuilder.buildConstDbgValue(*CI, Variable, Expression);
+ return;
+ }
+
+ if (auto *AI = dyn_cast<AllocaInst>(V);
+ AI && AI->isStaticAlloca() && Expression->startsWithDeref()) {
+ // If the value is an alloca and the expression starts with a
+ // dereference, track a stack slot instead of a register, as registers
+ // may be clobbered.
+ auto ExprOperands = Expression->getElements();
+ auto *ExprDerefRemoved =
+ DIExpression::get(AI->getContext(), ExprOperands.drop_front());
+ MIRBuilder.buildFIDbgValue(getOrCreateFrameIndex(*AI), Variable,
+ ExprDerefRemoved);
+ return;
+ }
+ if (translateIfEntryValueArgument(false, V, Variable, Expression, DL,
+ MIRBuilder))
+ return;
+ for (Register Reg : getOrCreateVRegs(*V)) {
+ // FIXME: This does not handle register-indirect values at offset 0. The
+ // direct/indirect thing shouldn't really be handled by something as
+ // implicit as reg+noreg vs reg+imm in the first place, but it seems
+ // pretty baked in right now.
+ MIRBuilder.buildDirectDbgValue(Reg, Variable, Expression);
+ }
+ return;
+}
+
+void IRTranslator::translateDbgDeclareRecord(Value *Address, bool HasArgList,
+ const DILocalVariable *Variable,
+ const DIExpression *Expression,
+ const DebugLoc &DL,
+ MachineIRBuilder &MIRBuilder) {
+ if (!Address || isa<UndefValue>(Address)) {
+ LLVM_DEBUG(dbgs() << "Dropping debug info for " << *Variable << "\n");
+ return;
+ }
+
+ assert(Variable->isValidLocationForIntrinsic(DL) &&
+ "Expected inlined-at fields to agree");
+ auto AI = dyn_cast<AllocaInst>(Address);
+ if (AI && AI->isStaticAlloca()) {
+ // Static allocas are tracked at the MF level, no need for DBG_VALUE
+ // instructions (in fact, they get ignored if they *do* exist).
+ MF->setVariableDbgInfo(Variable, Expression,
+ getOrCreateFrameIndex(*AI), DL);
+ return;
+ }
+
+ if (translateIfEntryValueArgument(true, Address, Variable,
+ Expression, DL,
+ MIRBuilder))
+ return;
+
+ // A dbg.declare describes the address of a source variable, so lower it
+ // into an indirect DBG_VALUE.
+ MIRBuilder.setDebugLoc(DL);
+ MIRBuilder.buildIndirectDbgValue(getOrCreateVReg(*Address),
+ Variable, Expression);
+ return;
+}
+
+void IRTranslator::translateDbgInfo(const Instruction &Inst,
+ MachineIRBuilder &MIRBuilder) {
+ for (DPValue &DPV : Inst.getDbgValueRange()) {
+ const DILocalVariable *Variable = DPV.getVariable();
+ const DIExpression *Expression = DPV.getExpression();
+ Value *V = DPV.getVariableLocationOp(0);
+ if (DPV.isDbgDeclare())
+ translateDbgDeclareRecord(V, DPV.hasArgList(), Variable,
+ Expression, DPV.getDebugLoc(), MIRBuilder);
+ else
+ translateDbgValueRecord(V, DPV.hasArgList(), Variable,
+ Expression, DPV.getDebugLoc(), MIRBuilder);
+ }
+}
+
bool IRTranslator::translate(const Instruction &Inst) {
CurBuilder->setDebugLoc(Inst.getDebugLoc());
CurBuilder->setPCSections(Inst.getMetadata(LLVMContext::MD_pcsections));
#ifndef NDEBUG
Verifier.setCurrentInst(&Inst);
#endif // ifndef NDEBUG
+
+ // Translate any debug-info attached to the instruction.
+ translateDbgInfo(Inst, *CurBuilder.get());
+
if (translate(Inst))
continue;