Skip to content

Commit 1c3ef9e

Browse files
committed
[SystemZ] Support symbolic displacements.
This patch adds support for symbolic displacements, e.g. like 'lg %r0, sym(%r1)', which is done using relocations. This is needed to compile the kernel without disabling the integrated assembler. Review: Ulrich Weigand Differential Revision: https://reviews.llvm.org/D113341
1 parent 0b17336 commit 1c3ef9e

13 files changed

+548
-36
lines changed

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@
4040

4141
using namespace llvm;
4242

43-
// Return true if Expr is in the range [MinValue, MaxValue].
44-
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) {
43+
// Return true if Expr is in the range [MinValue, MaxValue]. If AllowSymbol
44+
// is true any MCExpr is accepted (address displacement).
45+
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue,
46+
bool AllowSymbol = false) {
4547
if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
4648
int64_t Value = CE->getValue();
4749
return Value >= MinValue && Value <= MaxValue;
4850
}
49-
return false;
51+
return AllowSymbol;
5052
}
5153

5254
namespace {
@@ -265,10 +267,10 @@ class SystemZOperand : public MCParsedAsmOperand {
265267
return isMem(MemKind) && Mem.RegKind == RegKind;
266268
}
267269
bool isMemDisp12(MemoryKind MemKind, RegisterKind RegKind) const {
268-
return isMem(MemKind, RegKind) && inRange(Mem.Disp, 0, 0xfff);
270+
return isMem(MemKind, RegKind) && inRange(Mem.Disp, 0, 0xfff, true);
269271
}
270272
bool isMemDisp20(MemoryKind MemKind, RegisterKind RegKind) const {
271-
return isMem(MemKind, RegKind) && inRange(Mem.Disp, -524288, 524287);
273+
return isMem(MemKind, RegKind) && inRange(Mem.Disp, -524288, 524287, true);
272274
}
273275
bool isMemDisp12Len4(RegisterKind RegKind) const {
274276
return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x10);

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ using namespace llvm;
2424
#include "SystemZGenAsmWriter.inc"
2525

2626
void SystemZInstPrinter::printAddress(const MCAsmInfo *MAI, unsigned Base,
27-
int64_t Disp, unsigned Index,
27+
const MCOperand &DispMO, unsigned Index,
2828
raw_ostream &O) {
29-
O << Disp;
29+
printOperand(DispMO, MAI, O);
3030
if (Base || Index) {
3131
O << '(';
3232
if (Index) {
@@ -194,23 +194,23 @@ void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
194194

195195
void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum,
196196
raw_ostream &O) {
197-
printAddress(&MAI, MI->getOperand(OpNum).getReg(),
198-
MI->getOperand(OpNum + 1).getImm(), 0, O);
197+
printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
198+
0, O);
199199
}
200200

201201
void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum,
202202
raw_ostream &O) {
203-
printAddress(&MAI, MI->getOperand(OpNum).getReg(),
204-
MI->getOperand(OpNum + 1).getImm(),
203+
printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
205204
MI->getOperand(OpNum + 2).getReg(), O);
206205
}
207206

208207
void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
209208
raw_ostream &O) {
210209
unsigned Base = MI->getOperand(OpNum).getReg();
211-
uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
210+
const MCOperand &DispMO = MI->getOperand(OpNum + 1);
212211
uint64_t Length = MI->getOperand(OpNum + 2).getImm();
213-
O << Disp << '(' << Length;
212+
printOperand(DispMO, &MAI, O);
213+
O << '(' << Length;
214214
if (Base) {
215215
O << ",";
216216
printRegName(O, Base);
@@ -221,9 +221,10 @@ void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
221221
void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum,
222222
raw_ostream &O) {
223223
unsigned Base = MI->getOperand(OpNum).getReg();
224-
uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
224+
const MCOperand &DispMO = MI->getOperand(OpNum + 1);
225225
unsigned Length = MI->getOperand(OpNum + 2).getReg();
226-
O << Disp << "(";
226+
printOperand(DispMO, &MAI, O);
227+
O << "(";
227228
printRegName(O, Length);
228229
if (Base) {
229230
O << ",";
@@ -234,8 +235,7 @@ void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum,
234235

235236
void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum,
236237
raw_ostream &O) {
237-
printAddress(&MAI, MI->getOperand(OpNum).getReg(),
238-
MI->getOperand(OpNum + 1).getImm(),
238+
printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
239239
MI->getOperand(OpNum + 2).getReg(), O);
240240
}
241241

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ class SystemZInstPrinter : public MCInstPrinter {
3333
static const char *getRegisterName(unsigned RegNo);
3434

3535
// Print an address with the given base, displacement and index.
36-
static void printAddress(const MCAsmInfo *MAI, unsigned Base, int64_t Disp,
37-
unsigned Index, raw_ostream &O);
36+
static void printAddress(const MCAsmInfo *MAI, unsigned Base,
37+
const MCOperand &DispMO, unsigned Index,
38+
raw_ostream &O);
3839

3940
// Print the given operand.
4041
static void printOperand(const MCOperand &MO, const MCAsmInfo *MAI,

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

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "MCTargetDesc/SystemZMCTargetDesc.h"
1111
#include "llvm/ADT/StringSwitch.h"
1212
#include "llvm/MC/MCAsmBackend.h"
13+
#include "llvm/MC/MCAssembler.h"
14+
#include "llvm/MC/MCContext.h"
1315
#include "llvm/MC/MCELFObjectWriter.h"
1416
#include "llvm/MC/MCFixupKindInfo.h"
1517
#include "llvm/MC/MCInst.h"
@@ -21,7 +23,8 @@ using namespace llvm;
2123
// Value is a fully-resolved relocation value: Symbol + Addend [- Pivot].
2224
// Return the bits that should be installed in a relocation field for
2325
// fixup kind Kind.
24-
static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value) {
26+
static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value,
27+
const MCFixup &Fixup, MCContext &Ctx) {
2528
if (Kind < FirstTargetFixupKind)
2629
return Value;
2730

@@ -32,6 +35,24 @@ static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value) {
3235
case SystemZ::FK_390_PC32DBL:
3336
return (int64_t)Value / 2;
3437

38+
case SystemZ::FK_390_12:
39+
if (!isUInt<12>(Value)) {
40+
Ctx.reportError(Fixup.getLoc(), "displacement exceeds uint12");
41+
return 0;
42+
}
43+
return Value;
44+
45+
case SystemZ::FK_390_20: {
46+
if (!isInt<20>(Value)) {
47+
Ctx.reportError(Fixup.getLoc(), "displacement exceeds int20");
48+
return 0;
49+
}
50+
// The high byte of a 20 bit displacement value comes first.
51+
uint64_t DLo = Value & 0xfff;
52+
uint64_t DHi = (Value >> 12) & 0xff;
53+
return (DLo << 8) | DHi;
54+
}
55+
3556
case SystemZ::FK_390_TLS_CALL:
3657
return 0;
3758
}
@@ -95,7 +116,9 @@ SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
95116
{ "FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
96117
{ "FK_390_PC24DBL", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
97118
{ "FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
98-
{ "FK_390_TLS_CALL", 0, 0, 0 }
119+
{ "FK_390_TLS_CALL", 0, 0, 0 },
120+
{ "FK_390_12", 4, 12, 0 },
121+
{ "FK_390_20", 4, 20, 0 }
99122
};
100123

101124
// Fixup kinds from .reloc directive are like R_390_NONE. They
@@ -133,7 +156,7 @@ void SystemZMCAsmBackend::applyFixup(const MCAssembler &Asm,
133156
assert(Offset + Size <= Data.size() && "Invalid fixup offset!");
134157

135158
// Big-endian insertion of Size bytes.
136-
Value = extractBitsForFixup(Kind, Value);
159+
Value = extractBitsForFixup(Kind, Value, Fixup, Asm.getContext());
137160
if (BitSize < 64)
138161
Value &= ((uint64_t)1 << BitSize) - 1;
139162
unsigned ShiftValue = (Size * 8) - 8;

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

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "MCTargetDesc/SystemZMCFixups.h"
1414
#include "MCTargetDesc/SystemZMCTargetDesc.h"
15+
#include "SystemZInstrInfo.h"
1516
#include "llvm/ADT/SmallVector.h"
1617
#include "llvm/MC/MCCodeEmitter.h"
1718
#include "llvm/MC/MCContext.h"
@@ -60,6 +61,12 @@ class SystemZMCCodeEmitter : public MCCodeEmitter {
6061
SmallVectorImpl<MCFixup> &Fixups,
6162
const MCSubtargetInfo &STI) const;
6263

64+
// Return the displacement value for the OpNum operand. If it is a symbol,
65+
// add a fixup for it and return 0.
66+
uint64_t getDispOpValue(const MCInst &MI, unsigned OpNum,
67+
SmallVectorImpl<MCFixup> &Fixups,
68+
SystemZ::FixupKind Kind) const;
69+
6370
// Called by the TableGen code to get the binary encoding of an address.
6471
// The index or length, if any, is encoded first, followed by the base,
6572
// followed by the displacement. In a 20-bit displacement,
@@ -179,12 +186,30 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
179186
llvm_unreachable("Unexpected operand type!");
180187
}
181188

189+
uint64_t SystemZMCCodeEmitter::
190+
getDispOpValue(const MCInst &MI, unsigned OpNum,
191+
SmallVectorImpl<MCFixup> &Fixups,
192+
SystemZ::FixupKind Kind) const {
193+
const MCOperand &MO = MI.getOperand(OpNum);
194+
if (MO.isImm())
195+
return static_cast<uint64_t>(MO.getImm());
196+
if (MO.isExpr()) {
197+
// All instructions follow the pattern where the first displacement has a
198+
// 2 bytes offset, and the second one 4 bytes.
199+
unsigned ByteOffs = Fixups.size() == 0 ? 2 : 4;
200+
Fixups.push_back(MCFixup::create(ByteOffs, MO.getExpr(), (MCFixupKind)Kind));
201+
assert(Fixups.size() <= 2 && "More than two memory operands in MI?");
202+
return 0;
203+
}
204+
llvm_unreachable("Unexpected operand type!");
205+
}
206+
182207
uint64_t SystemZMCCodeEmitter::
183208
getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
184209
SmallVectorImpl<MCFixup> &Fixups,
185210
const MCSubtargetInfo &STI) const {
186211
uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
187-
uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
212+
uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
188213
assert(isUInt<4>(Base) && isUInt<12>(Disp));
189214
return (Base << 12) | Disp;
190215
}
@@ -194,7 +219,7 @@ getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
194219
SmallVectorImpl<MCFixup> &Fixups,
195220
const MCSubtargetInfo &STI) const {
196221
uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
197-
uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
222+
uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20);
198223
assert(isUInt<4>(Base) && isInt<20>(Disp));
199224
return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
200225
}
@@ -204,7 +229,7 @@ getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
204229
SmallVectorImpl<MCFixup> &Fixups,
205230
const MCSubtargetInfo &STI) const {
206231
uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
207-
uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
232+
uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
208233
uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
209234
assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
210235
return (Index << 16) | (Base << 12) | Disp;
@@ -215,7 +240,7 @@ getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
215240
SmallVectorImpl<MCFixup> &Fixups,
216241
const MCSubtargetInfo &STI) const {
217242
uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
218-
uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
243+
uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20);
219244
uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
220245
assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
221246
return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
@@ -227,7 +252,7 @@ getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
227252
SmallVectorImpl<MCFixup> &Fixups,
228253
const MCSubtargetInfo &STI) const {
229254
uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
230-
uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
255+
uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
231256
uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
232257
assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
233258
return (Len << 16) | (Base << 12) | Disp;
@@ -238,7 +263,7 @@ getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
238263
SmallVectorImpl<MCFixup> &Fixups,
239264
const MCSubtargetInfo &STI) const {
240265
uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
241-
uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
266+
uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
242267
uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
243268
assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
244269
return (Len << 16) | (Base << 12) | Disp;
@@ -249,7 +274,7 @@ getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
249274
SmallVectorImpl<MCFixup> &Fixups,
250275
const MCSubtargetInfo &STI) const {
251276
uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
252-
uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
277+
uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
253278
uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
254279
assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
255280
return (Len << 16) | (Base << 12) | Disp;
@@ -260,7 +285,7 @@ getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
260285
SmallVectorImpl<MCFixup> &Fixups,
261286
const MCSubtargetInfo &STI) const {
262287
uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
263-
uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
288+
uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
264289
uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
265290
assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
266291
return (Index << 16) | (Base << 12) | Disp;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ enum FixupKind {
2020
FK_390_PC24DBL,
2121
FK_390_PC32DBL,
2222
FK_390_TLS_CALL,
23+
FK_390_12,
24+
FK_390_20,
2325

2426
// Marker
2527
LastTargetFixupKind,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ static unsigned getAbsoluteReloc(unsigned Kind) {
4646
case FK_Data_2: return ELF::R_390_16;
4747
case FK_Data_4: return ELF::R_390_32;
4848
case FK_Data_8: return ELF::R_390_64;
49+
case SystemZ::FK_390_12: return ELF::R_390_12;
50+
case SystemZ::FK_390_20: return ELF::R_390_20;
4951
}
5052
llvm_unreachable("Unsupported absolute address");
5153
}

llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -775,9 +775,10 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
775775
unsigned OpNo,
776776
const char *ExtraCode,
777777
raw_ostream &OS) {
778-
SystemZInstPrinter::printAddress(MAI, MI->getOperand(OpNo).getReg(),
779-
MI->getOperand(OpNo + 1).getImm(),
780-
MI->getOperand(OpNo + 2).getReg(), OS);
778+
SystemZInstPrinter::
779+
printAddress(MAI, MI->getOperand(OpNo).getReg(),
780+
MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
781+
MI->getOperand(OpNo + 2).getReg(), OS);
781782
return false;
782783
}
783784

llvm/lib/Target/SystemZ/SystemZInstrInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ enum {
4747
CCMaskFirst = (1 << 18),
4848
CCMaskLast = (1 << 19),
4949
IsLogical = (1 << 20),
50-
CCIfNoSignedWrap = (1 << 21)
50+
CCIfNoSignedWrap = (1 << 21),
51+
MemMemOp = (1 << 22)
5152
};
5253

5354
static inline unsigned getAccessSize(unsigned int Flags) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# RUN: not llvm-mc -triple s390x-unknown-unknown -filetype=obj %s 2>&1 | FileCheck %s
2+
3+
.text
4+
5+
# CHECK: error: displacement exceeds uint12
6+
la %r1, b-a(%r1)
7+
8+
# CHECK: error: displacement exceeds int20
9+
lay %r1, d-c(%r1)
10+
11+
# CHECK-NOT: error
12+
lay %r1, b-a(%r1)
13+
14+
.type a,@object
15+
.local a
16+
.comm a,4096
17+
.type b,@object
18+
.local b
19+
.comm b,4,4
20+
21+
.type c,@object
22+
.local c
23+
.comm c,524288
24+
.type d,@object
25+
.local d
26+
.comm d,4,4
27+

0 commit comments

Comments
 (0)