Skip to content

Commit a0eee6c

Browse files
committed
[SystemZ] Allow symbols in immediate asm operands
Currently mentioning any symbols in immediate asm operands is not supported, for example: error: invalid operand for instruction lghi %r4,foo_end-foo The immediate problem is that is*Imm() and print*Operand() functions do not accept MCExprs, but simply relaxing these checks is not enough: after symbol addresses are computed, range checks need to run against resolved values. Add a number of SystemZ::FixupKind members for each kind of immediate value and process them in SystemZMCAsmBackend::applyFixup(). Only perform the range checks, do not change anything. Adjust the tests: move previously failing cases like the one shown above out of insn-bad.s. Reviewed By: uweigand Differential Revision: https://reviews.llvm.org/D154899
1 parent e6c62a2 commit a0eee6c

14 files changed

+390
-199
lines changed

llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ class SystemZOperand : public MCParsedAsmOperand {
237237
return Kind == KindImm;
238238
}
239239
bool isImm(int64_t MinValue, int64_t MaxValue) const {
240-
return Kind == KindImm && inRange(Imm, MinValue, MaxValue);
240+
return Kind == KindImm && inRange(Imm, MinValue, MaxValue, true);
241241
}
242242
const MCExpr *getImm() const {
243243
assert(Kind == KindImm && "Not an immediate");

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,24 @@ void SystemZInstPrinter::printInst(const MCInst *MI, uint64_t Address,
8383
template <unsigned N>
8484
void SystemZInstPrinter::printUImmOperand(const MCInst *MI, int OpNum,
8585
raw_ostream &O) {
86-
int64_t Value = MI->getOperand(OpNum).getImm();
86+
const MCOperand &MO = MI->getOperand(OpNum);
87+
if (MO.isExpr()) {
88+
O << *MO.getExpr();
89+
return;
90+
}
91+
uint64_t Value = static_cast<uint64_t>(MO.getImm());
8792
assert(isUInt<N>(Value) && "Invalid uimm argument");
8893
O << markup("<imm:") << Value << markup(">");
8994
}
9095

9196
template <unsigned N>
9297
void SystemZInstPrinter::printSImmOperand(const MCInst *MI, int OpNum,
9398
raw_ostream &O) {
99+
const MCOperand &MO = MI->getOperand(OpNum);
100+
if (MO.isExpr()) {
101+
O << *MO.getExpr();
102+
return;
103+
}
94104
int64_t Value = MI->getOperand(OpNum).getImm();
95105
assert(isInt<N>(Value) && "Invalid simm argument");
96106
O << markup("<imm:") << Value << markup(">");

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

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value,
4747
return (int64_t)Value / 2;
4848
};
4949

50+
auto handleImmValue = [&](bool IsSigned, unsigned W) -> uint64_t {
51+
if (!(IsSigned ? checkFixupInRange(minIntN(W), maxIntN(W))
52+
: checkFixupInRange(0, maxUIntN(W))))
53+
return 0;
54+
return Value;
55+
};
56+
5057
switch (unsigned(Kind)) {
5158
case SystemZ::FK_390_PC12DBL:
5259
return handlePCRelFixupValue(12);
@@ -57,22 +64,41 @@ static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value,
5764
case SystemZ::FK_390_PC32DBL:
5865
return handlePCRelFixupValue(32);
5966

60-
case SystemZ::FK_390_12:
61-
if (!checkFixupInRange(0, maxUIntN(12)))
62-
return 0;
63-
return Value;
67+
case SystemZ::FK_390_TLS_CALL:
68+
return 0;
6469

65-
case SystemZ::FK_390_20: {
66-
if (!checkFixupInRange(minIntN(20), maxIntN(20)))
67-
return 0;
70+
case SystemZ::FK_390_S8Imm:
71+
return handleImmValue(true, 8);
72+
case SystemZ::FK_390_S16Imm:
73+
return handleImmValue(true, 16);
74+
case SystemZ::FK_390_S20Imm: {
75+
Value = handleImmValue(true, 20);
76+
// S20Imm is used only for signed 20-bit displacements.
6877
// The high byte of a 20 bit displacement value comes first.
6978
uint64_t DLo = Value & 0xfff;
7079
uint64_t DHi = (Value >> 12) & 0xff;
7180
return (DLo << 8) | DHi;
7281
}
73-
74-
case SystemZ::FK_390_TLS_CALL:
75-
return 0;
82+
case SystemZ::FK_390_S32Imm:
83+
return handleImmValue(true, 32);
84+
case SystemZ::FK_390_U1Imm:
85+
return handleImmValue(false, 1);
86+
case SystemZ::FK_390_U2Imm:
87+
return handleImmValue(false, 2);
88+
case SystemZ::FK_390_U3Imm:
89+
return handleImmValue(false, 3);
90+
case SystemZ::FK_390_U4Imm:
91+
return handleImmValue(false, 4);
92+
case SystemZ::FK_390_U8Imm:
93+
return handleImmValue(false, 8);
94+
case SystemZ::FK_390_U12Imm:
95+
return handleImmValue(false, 12);
96+
case SystemZ::FK_390_U16Imm:
97+
return handleImmValue(false, 16);
98+
case SystemZ::FK_390_U32Imm:
99+
return handleImmValue(false, 32);
100+
case SystemZ::FK_390_U48Imm:
101+
return handleImmValue(false, 48);
76102
}
77103

78104
llvm_unreachable("Unknown fixup kind!");
@@ -130,16 +156,6 @@ SystemZMCAsmBackend::getFixupKind(StringRef Name) const {
130156

131157
const MCFixupKindInfo &
132158
SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
133-
const static MCFixupKindInfo Infos[SystemZ::NumTargetFixupKinds] = {
134-
{ "FK_390_PC12DBL", 4, 12, MCFixupKindInfo::FKF_IsPCRel },
135-
{ "FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
136-
{ "FK_390_PC24DBL", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
137-
{ "FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
138-
{ "FK_390_TLS_CALL", 0, 0, 0 },
139-
{ "FK_390_12", 4, 12, 0 },
140-
{ "FK_390_20", 4, 20, 0 }
141-
};
142-
143159
// Fixup kinds from .reloc directive are like R_390_NONE. They
144160
// do not require any extra processing.
145161
if (Kind >= FirstLiteralRelocationKind)
@@ -150,7 +166,7 @@ SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
150166

151167
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
152168
"Invalid kind!");
153-
return Infos[Kind - FirstTargetFixupKind];
169+
return SystemZ::MCFixupKindInfos[Kind - FirstTargetFixupKind];
154170
}
155171

156172
bool SystemZMCAsmBackend::shouldForceRelocation(const MCAssembler &,

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

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,19 @@ class SystemZMCCodeEmitter : public MCCodeEmitter {
6363
SmallVectorImpl<MCFixup> &Fixups,
6464
const MCSubtargetInfo &STI) const;
6565

66-
// Return the displacement value for the OpNum operand. If it is a symbol,
67-
// add a fixup for it and return 0.
68-
uint64_t getDispOpValue(const MCInst &MI, unsigned OpNum,
69-
SmallVectorImpl<MCFixup> &Fixups,
70-
const MCSubtargetInfo &STI, unsigned OpSize,
71-
SystemZ::FixupKind Kind) const;
72-
73-
// Called by the TableGen code to get the binary encoding of an address.
74-
// The index or length, if any, is encoded first, followed by the base,
75-
// followed by the displacement. In a 20-bit displacement,
76-
// the low 12 bits are encoded before the high 8 bits.
77-
template <unsigned N>
66+
// Return the encoded immediate value for the OpNum operand. If it is a
67+
// symbol, add a fixup for it and return 0.
68+
template <SystemZ::FixupKind Kind>
69+
uint64_t getImmOpValue(const MCInst &MI, unsigned OpNum,
70+
SmallVectorImpl<MCFixup> &Fixups,
71+
const MCSubtargetInfo &STI) const;
72+
73+
// Called by the TableGen code to get the binary encoding of a length value.
74+
// Length values are encoded by subtracting 1 from the actual value.
75+
template <SystemZ::FixupKind Kind>
7876
uint64_t getLenEncoding(const MCInst &MI, unsigned OpNum,
7977
SmallVectorImpl<MCFixup> &Fixups,
8078
const MCSubtargetInfo &STI) const;
81-
uint64_t getDisp12Encoding(const MCInst &MI, unsigned OpNum,
82-
SmallVectorImpl<MCFixup> &Fixups,
83-
const MCSubtargetInfo &STI) const;
84-
uint64_t getDisp20Encoding(const MCInst &MI, unsigned OpNum,
85-
SmallVectorImpl<MCFixup> &Fixups,
86-
const MCSubtargetInfo &STI) const;
8779

8880
// Operand OpNum of MI needs a PC-relative fixup of kind Kind at
8981
// Offset bytes from the start of MI. Add the fixup to Fixups
@@ -161,23 +153,26 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
161153
const MCSubtargetInfo &STI) const {
162154
if (MO.isReg())
163155
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
156+
// SystemZAsmParser::parseAnyRegister() produces KindImm when registers are
157+
// specified as integers.
164158
if (MO.isImm())
165159
return static_cast<uint64_t>(MO.getImm());
166160
llvm_unreachable("Unexpected operand type!");
167161
}
168162

169-
uint64_t SystemZMCCodeEmitter::getDispOpValue(const MCInst &MI, unsigned OpNum,
170-
SmallVectorImpl<MCFixup> &Fixups,
171-
const MCSubtargetInfo &STI,
172-
unsigned OpSize,
173-
SystemZ::FixupKind Kind) const {
163+
template <SystemZ::FixupKind Kind>
164+
uint64_t SystemZMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNum,
165+
SmallVectorImpl<MCFixup> &Fixups,
166+
const MCSubtargetInfo &STI) const {
174167
const MCOperand &MO = MI.getOperand(OpNum);
175168
if (MO.isImm())
176169
return static_cast<uint64_t>(MO.getImm());
177170
if (MO.isExpr()) {
178171
unsigned MIBitSize = MCII.get(MI.getOpcode()).getSize() * 8;
179172
uint32_t RawBitOffset = getOperandBitOffset(MI, OpNum, STI);
180-
uint32_t BitOffset = MIBitSize - RawBitOffset - OpSize;
173+
unsigned OpBitSize =
174+
SystemZ::MCFixupKindInfos[Kind - FirstTargetFixupKind].TargetSize;
175+
uint32_t BitOffset = MIBitSize - RawBitOffset - OpBitSize;
181176
Fixups.push_back(MCFixup::create(BitOffset >> 3, MO.getExpr(),
182177
(MCFixupKind)Kind, MI.getLoc()));
183178
assert(Fixups.size() <= 2 && "More than two memory operands in MI?");
@@ -186,28 +181,12 @@ uint64_t SystemZMCCodeEmitter::getDispOpValue(const MCInst &MI, unsigned OpNum,
186181
llvm_unreachable("Unexpected operand type!");
187182
}
188183

189-
template <unsigned N>
184+
template <SystemZ::FixupKind Kind>
190185
uint64_t
191186
SystemZMCCodeEmitter::getLenEncoding(const MCInst &MI, unsigned OpNum,
192187
SmallVectorImpl<MCFixup> &Fixups,
193188
const MCSubtargetInfo &STI) const {
194-
return getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI) - 1;
195-
}
196-
197-
uint64_t
198-
SystemZMCCodeEmitter::getDisp12Encoding(const MCInst &MI, unsigned OpNum,
199-
SmallVectorImpl<MCFixup> &Fixups,
200-
const MCSubtargetInfo &STI) const {
201-
return getDispOpValue(MI, OpNum, Fixups, STI, 12,
202-
SystemZ::FixupKind::FK_390_12);
203-
}
204-
205-
uint64_t
206-
SystemZMCCodeEmitter::getDisp20Encoding(const MCInst &MI, unsigned OpNum,
207-
SmallVectorImpl<MCFixup> &Fixups,
208-
const MCSubtargetInfo &STI) const {
209-
return getDispOpValue(MI, OpNum, Fixups, STI, 20,
210-
SystemZ::FixupKind::FK_390_20);
189+
return getImmOpValue<Kind>(MI, OpNum, Fixups, STI) - 1;
211190
}
212191

213192
uint64_t

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

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_LIB_TARGET_SYSTEMZ_MCTARGETDESC_SYSTEMZMCFIXUPS_H
1111

1212
#include "llvm/MC/MCFixup.h"
13+
#include "llvm/MC/MCFixupKindInfo.h"
1314

1415
namespace llvm {
1516
namespace SystemZ {
@@ -20,13 +21,46 @@ enum FixupKind {
2021
FK_390_PC24DBL,
2122
FK_390_PC32DBL,
2223
FK_390_TLS_CALL,
23-
FK_390_12,
24-
FK_390_20,
24+
25+
FK_390_S8Imm,
26+
FK_390_S16Imm,
27+
FK_390_S20Imm,
28+
FK_390_S32Imm,
29+
FK_390_U1Imm,
30+
FK_390_U2Imm,
31+
FK_390_U3Imm,
32+
FK_390_U4Imm,
33+
FK_390_U8Imm,
34+
FK_390_U12Imm,
35+
FK_390_U16Imm,
36+
FK_390_U32Imm,
37+
FK_390_U48Imm,
2538

2639
// Marker
2740
LastTargetFixupKind,
2841
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
2942
};
43+
44+
const static MCFixupKindInfo MCFixupKindInfos[SystemZ::NumTargetFixupKinds] = {
45+
{"FK_390_PC12DBL", 4, 12, MCFixupKindInfo::FKF_IsPCRel},
46+
{"FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
47+
{"FK_390_PC24DBL", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
48+
{"FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
49+
{"FK_390_TLS_CALL", 0, 0, 0},
50+
{"FK_390_S8Imm", 0, 8, 0},
51+
{"FK_390_S16Imm", 0, 16, 0},
52+
{"FK_390_S20Imm", 4, 20, 0},
53+
{"FK_390_S32Imm", 0, 32, 0},
54+
{"FK_390_U1Imm", 0, 1, 0},
55+
{"FK_390_U2Imm", 0, 2, 0},
56+
{"FK_390_U3Imm", 0, 3, 0},
57+
{"FK_390_U4Imm", 0, 4, 0},
58+
{"FK_390_U8Imm", 0, 8, 0},
59+
{"FK_390_U12Imm", 4, 12, 0},
60+
{"FK_390_U16Imm", 0, 16, 0},
61+
{"FK_390_U32Imm", 0, 32, 0},
62+
{"FK_390_U48Imm", 0, 48, 0},
63+
};
3064
} // end namespace SystemZ
3165
} // end namespace llvm
3266

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

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,24 @@ SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI)
4343
// Return the relocation type for an absolute value of MCFixupKind Kind.
4444
static unsigned getAbsoluteReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
4545
switch (Kind) {
46-
case FK_Data_1: return ELF::R_390_8;
47-
case FK_Data_2: return ELF::R_390_16;
48-
case FK_Data_4: return ELF::R_390_32;
49-
case FK_Data_8: return ELF::R_390_64;
50-
case SystemZ::FK_390_12: return ELF::R_390_12;
51-
case SystemZ::FK_390_20: return ELF::R_390_20;
46+
case FK_Data_1:
47+
case SystemZ::FK_390_U8Imm:
48+
case SystemZ::FK_390_S8Imm:
49+
return ELF::R_390_8;
50+
case SystemZ::FK_390_U12Imm:
51+
return ELF::R_390_12;
52+
case FK_Data_2:
53+
case SystemZ::FK_390_U16Imm:
54+
case SystemZ::FK_390_S16Imm:
55+
return ELF::R_390_16;
56+
case SystemZ::FK_390_S20Imm:
57+
return ELF::R_390_20;
58+
case FK_Data_4:
59+
case SystemZ::FK_390_U32Imm:
60+
case SystemZ::FK_390_S32Imm:
61+
return ELF::R_390_32;
62+
case FK_Data_8:
63+
return ELF::R_390_64;
5264
}
5365
Ctx.reportError(Loc, "Unsupported absolute address");
5466
return 0;
@@ -57,13 +69,24 @@ static unsigned getAbsoluteReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
5769
// Return the relocation type for a PC-relative value of MCFixupKind Kind.
5870
static unsigned getPCRelReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
5971
switch (Kind) {
60-
case FK_Data_2: return ELF::R_390_PC16;
61-
case FK_Data_4: return ELF::R_390_PC32;
62-
case FK_Data_8: return ELF::R_390_PC64;
63-
case SystemZ::FK_390_PC12DBL: return ELF::R_390_PC12DBL;
64-
case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL;
65-
case SystemZ::FK_390_PC24DBL: return ELF::R_390_PC24DBL;
66-
case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL;
72+
case FK_Data_2:
73+
case SystemZ::FK_390_U16Imm:
74+
case SystemZ::FK_390_S16Imm:
75+
return ELF::R_390_PC16;
76+
case FK_Data_4:
77+
case SystemZ::FK_390_U32Imm:
78+
case SystemZ::FK_390_S32Imm:
79+
return ELF::R_390_PC32;
80+
case FK_Data_8:
81+
return ELF::R_390_PC64;
82+
case SystemZ::FK_390_PC12DBL:
83+
return ELF::R_390_PC12DBL;
84+
case SystemZ::FK_390_PC16DBL:
85+
return ELF::R_390_PC16DBL;
86+
case SystemZ::FK_390_PC24DBL:
87+
return ELF::R_390_PC24DBL;
88+
case SystemZ::FK_390_PC32DBL:
89+
return ELF::R_390_PC32DBL;
6790
}
6891
Ctx.reportError(Loc, "Unsupported PC-relative address");
6992
return 0;

llvm/lib/Target/SystemZ/SystemZOperands.td

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class ImmediateTLSAsmOperand<string name>
2323

2424
class ImmediateOp<ValueType vt, string asmop> : Operand<vt> {
2525
let PrintMethod = "print"#asmop#"Operand";
26+
let EncoderMethod = "getImmOpValue<SystemZ::FK_390_"#asmop#">";
2627
let DecoderMethod = "decode"#asmop#"Operand";
2728
let ParserMatchClass = !cast<AsmOperandClass>(asmop);
2829
let OperandType = "OPERAND_IMMEDIATE";
@@ -509,11 +510,11 @@ class Imm64 : ImmLeaf<i64, [{}]>, Operand<i64> {
509510
}
510511
def imm64 : Imm64;
511512
def len4imm64 : Imm64 {
512-
let EncoderMethod = "getLenEncoding<4>";
513+
let EncoderMethod = "getLenEncoding<SystemZ::FK_390_U4Imm>";
513514
let DecoderMethod = "decodeLenOperand<4>";
514515
}
515516
def len8imm64 : Imm64 {
516-
let EncoderMethod = "getLenEncoding<8>";
517+
let EncoderMethod = "getLenEncoding<SystemZ::FK_390_U8Imm>";
517518
let DecoderMethod = "decodeLenOperand<8>";
518519
}
519520

@@ -590,14 +591,14 @@ def pcrel32 : PCRelAddress<i64, "pcrel32", PCRel32> {
590591
//===----------------------------------------------------------------------===//
591592

592593
// 12-bit displacement operands.
593-
let EncoderMethod = "getDisp12Encoding",
594+
let EncoderMethod = "getImmOpValue<SystemZ::FK_390_U12Imm>",
594595
DecoderMethod = "decodeU12ImmOperand" in {
595596
def disp12imm32 : Operand<i32>;
596597
def disp12imm64 : Operand<i64>;
597598
}
598599

599600
// 20-bit displacement operands.
600-
let EncoderMethod = "getDisp20Encoding",
601+
let EncoderMethod = "getImmOpValue<SystemZ::FK_390_S20Imm>",
601602
DecoderMethod = "decodeS20ImmOperand" in {
602603
def disp20imm32 : Operand<i32>;
603604
def disp20imm64 : Operand<i64>;

0 commit comments

Comments
 (0)