Skip to content

Commit fb21efa

Browse files
authored
[SystemZ] Support PrintBranchImmAsAddress in disassembler (#141064)
As noticed in #140471, the SystemZ target currently implements disassembly of PC-relative target addresses differently from other back-ends. This patch brings SystemZ in line with other targets. Specifically, this patch changes the relevant MCInst instructions to carry a PC-relative displacement instead of an absolute target address in their immediate fields. When printing the instruction, this displacement will either be shown as is (e.g. for llvm-mc), or else translated into an absolute address at print time (e.g. for llvm-objdump). The existing llvm-mc based tests using PC-relative operands no longer work and have to be rewritten, but printing displacements makes those tests easier to maintain anyway.
1 parent 2bb5cc5 commit fb21efa

File tree

12 files changed

+1492
-1970
lines changed

12 files changed

+1492
-1970
lines changed

llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,9 @@ static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm,
280280
uint64_t Address, bool isBranch,
281281
const MCDisassembler *Decoder) {
282282
assert(isUInt<N>(Imm) && "Invalid PC-relative offset");
283-
uint64_t Value = SignExtend64<N>(Imm) * 2 + Address;
283+
uint64_t Value = SignExtend64<N>(Imm) * 2;
284284

285-
if (!tryAddingSymbolicOperand(Value, isBranch, Address, 2, N / 8,
285+
if (!tryAddingSymbolicOperand(Value + Address, isBranch, Address, 2, N / 8,
286286
Inst, Decoder))
287287
Inst.addOperand(MCOperand::createImm(Value));
288288

llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinterCommon.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,22 +148,38 @@ void SystemZInstPrinterCommon::printU48ImmOperand(const MCInst *MI, int OpNum,
148148
printUImmOperand<48>(MI, OpNum, O);
149149
}
150150

151-
void SystemZInstPrinterCommon::printPCRelOperand(const MCInst *MI, int OpNum,
151+
void SystemZInstPrinterCommon::printPCRelOperand(const MCInst *MI,
152+
uint64_t Address, int OpNum,
152153
raw_ostream &O) {
153154
const MCOperand &MO = MI->getOperand(OpNum);
155+
156+
// If the label has already been resolved to an immediate offset (say, when
157+
// we're running the disassembler), just print the immediate.
154158
if (MO.isImm()) {
155-
WithMarkup M = markup(O, Markup::Immediate);
156-
O << "0x";
157-
O.write_hex(MO.getImm());
158-
} else
159+
int64_t Offset = MO.getImm();
160+
if (PrintBranchImmAsAddress)
161+
markup(O, Markup::Target) << formatHex(Address + Offset);
162+
else
163+
markup(O, Markup::Immediate) << formatImm(Offset);
164+
return;
165+
}
166+
167+
// If the branch target is simply an address then print it in hex.
168+
const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(MO.getExpr());
169+
int64_t TargetAddress;
170+
if (BranchTarget && BranchTarget->evaluateAsAbsolute(TargetAddress)) {
171+
markup(O, Markup::Target) << formatHex((uint64_t)TargetAddress);
172+
} else {
173+
// Otherwise, just print the expression.
159174
MO.getExpr()->print(O, &MAI);
175+
}
160176
}
161177

162178
void SystemZInstPrinterCommon::printPCRelTLSOperand(const MCInst *MI,
163179
uint64_t Address, int OpNum,
164180
raw_ostream &O) {
165181
// Output the PC-relative operand.
166-
printPCRelOperand(MI, OpNum, O);
182+
printPCRelOperand(MI, Address, OpNum, O);
167183

168184
// Output the TLS marker if present.
169185
if ((unsigned)OpNum + 1 < MI->getNumOperands()) {

llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinterCommon.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,8 @@ class SystemZInstPrinterCommon : public MCInstPrinter {
7171
void printS32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
7272
void printU32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
7373
void printU48ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
74-
void printPCRelOperand(const MCInst *MI, int OpNum, raw_ostream &O);
75-
void printPCRelOperand(const MCInst *MI, uint64_t /*Address*/, int OpNum,
76-
raw_ostream &O) {
77-
printPCRelOperand(MI, OpNum, O);
78-
}
74+
void printPCRelOperand(const MCInst *MI, uint64_t Address, int OpNum,
75+
raw_ostream &O);
7976
void printPCRelTLSOperand(const MCInst *MI, uint64_t Address, int OpNum,
8077
raw_ostream &O);
8178

0 commit comments

Comments
 (0)