Skip to content

Commit 52ebb65

Browse files
committed
Remove changes affecting non-RISCV targets
1 parent 94877ce commit 52ebb65

File tree

9 files changed

+290
-15
lines changed

9 files changed

+290
-15
lines changed

llvm/include/llvm/MC/MCInstrAnalysis.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ class LLVM_ABI MCInstrAnalysis {
182182
evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
183183
uint64_t &Target) const;
184184

185+
/// Given an instruction that accesses a memory address, try to compute
186+
/// the target address. Return true on success, and the address in \p Target.
187+
virtual bool evaluateInstruction(const MCInst &Inst, uint64_t Addr,
188+
uint64_t Size, uint64_t &Target) const;
189+
185190
/// Given an instruction tries to get the address of a memory operand. Returns
186191
/// the address on success.
187192
virtual std::optional<uint64_t>

llvm/lib/MC/MCInstrAnalysis.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ bool MCInstrAnalysis::evaluateBranch(const MCInst & /*Inst*/, uint64_t /*Addr*/,
3030
return false;
3131
}
3232

33+
bool MCInstrAnalysis::evaluateInstruction(const MCInst &Inst, uint64_t Addr,
34+
uint64_t Size,
35+
uint64_t &Target) const {
36+
return false;
37+
}
38+
3339
std::optional<uint64_t> MCInstrAnalysis::evaluateMemoryOperandAddress(
3440
const MCInst &Inst, const MCSubtargetInfo *STI, uint64_t Addr,
3541
uint64_t Size) const {

llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp

Lines changed: 103 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
#include "llvm/MC/MCSubtargetInfo.h"
3030
#include "llvm/MC/TargetRegistry.h"
3131
#include "llvm/Support/ErrorHandling.h"
32+
#include "llvm/Support/MathExtras.h"
3233
#include <bitset>
34+
#include <cstdint>
3335

3436
#define GET_INSTRINFO_MC_DESC
3537
#define ENABLE_INSTR_PREDICATE_VERIFIER
@@ -129,6 +131,7 @@ namespace {
129131
class RISCVMCInstrAnalysis : public MCInstrAnalysis {
130132
int64_t GPRState[31] = {};
131133
std::bitset<31> GPRValidMask;
134+
unsigned int ArchRegWidth;
132135

133136
static bool isGPR(MCRegister Reg) {
134137
return Reg >= RISCV::X0 && Reg <= RISCV::X31;
@@ -165,8 +168,8 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
165168
}
166169

167170
public:
168-
explicit RISCVMCInstrAnalysis(const MCInstrInfo *Info)
169-
: MCInstrAnalysis(Info) {}
171+
explicit RISCVMCInstrAnalysis(const MCInstrInfo *Info, unsigned int ArchRegWidth)
172+
: MCInstrAnalysis(Info), ArchRegWidth(ArchRegWidth) {}
170173

171174
void resetState() override { GPRValidMask.reset(); }
172175

@@ -182,6 +185,17 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
182185
}
183186

184187
switch (Inst.getOpcode()) {
188+
case RISCV::C_LUI:
189+
case RISCV::LUI: {
190+
setGPRState(Inst.getOperand(0).getReg(),
191+
SignExtend64<32>(Inst.getOperand(1).getImm() << 12));
192+
break;
193+
}
194+
case RISCV::AUIPC: {
195+
setGPRState(Inst.getOperand(0).getReg(),
196+
Addr + SignExtend64<32>(Inst.getOperand(1).getImm() << 12));
197+
break;
198+
}
185199
default: {
186200
// Clear the state of all defined registers for instructions that we don't
187201
// explicitly support.
@@ -193,10 +207,6 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
193207
}
194208
break;
195209
}
196-
case RISCV::AUIPC:
197-
setGPRState(Inst.getOperand(0).getReg(),
198-
Addr + SignExtend64<32>(Inst.getOperand(1).getImm() << 12));
199-
break;
200210
}
201211
}
202212

@@ -234,6 +244,83 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
234244
return false;
235245
}
236246

247+
bool evaluateInstruction(const MCInst &Inst, uint64_t Addr, uint64_t Size,
248+
uint64_t &Target) const override {
249+
switch(Inst.getOpcode()) {
250+
default:
251+
return false;
252+
case RISCV::C_ADDI:
253+
case RISCV::ADDI: {
254+
MCRegister Reg = Inst.getOperand(1).getReg();
255+
auto TargetRegState = getGPRState(Reg);
256+
if (TargetRegState && Reg != RISCV::X0) {
257+
Target = *TargetRegState + Inst.getOperand(2).getImm();
258+
Target &= maskTrailingOnes<uint64_t>(ArchRegWidth);
259+
return true;
260+
}
261+
break;
262+
}
263+
case RISCV::C_ADDIW:
264+
case RISCV::ADDIW: {
265+
MCRegister Reg = Inst.getOperand(1).getReg();
266+
auto TargetRegState = getGPRState(Reg);
267+
if (TargetRegState && Reg != RISCV::X0) {
268+
Target = *TargetRegState + Inst.getOperand(2).getImm();
269+
Target = SignExtend64<32>(Target);
270+
return true;
271+
}
272+
break;
273+
}
274+
case RISCV::LB:
275+
case RISCV::LH:
276+
case RISCV::LD:
277+
case RISCV::LW:
278+
case RISCV::LBU:
279+
case RISCV::LHU:
280+
case RISCV::LWU:
281+
case RISCV::SB:
282+
case RISCV::SH:
283+
case RISCV::SW:
284+
case RISCV::SD:
285+
case RISCV::FLH:
286+
case RISCV::FLW:
287+
case RISCV::FLD:
288+
case RISCV::FSH:
289+
case RISCV::FSW:
290+
case RISCV::FSD:
291+
case RISCV::C_LD:
292+
case RISCV::C_SD:
293+
case RISCV::C_FLD:
294+
case RISCV::C_FSD:
295+
case RISCV::C_SW:
296+
case RISCV::C_LW:
297+
case RISCV::C_FSW:
298+
case RISCV::C_FLW:
299+
case RISCV::C_LBU:
300+
case RISCV::C_LH:
301+
case RISCV::C_LHU:
302+
case RISCV::C_SB:
303+
case RISCV::C_SH:
304+
case RISCV::C_LWSP:
305+
case RISCV::C_SWSP:
306+
case RISCV::C_LDSP:
307+
case RISCV::C_SDSP:
308+
case RISCV::C_FLWSP:
309+
case RISCV::C_FSWSP:
310+
case RISCV::C_FLDSP:
311+
case RISCV::C_FSDSP: {
312+
MCRegister Reg = Inst.getOperand(1).getReg();
313+
auto TargetRegState = getGPRState(Reg);
314+
if (TargetRegState && Reg != RISCV::X0) {
315+
Target = *TargetRegState + Inst.getOperand(2).getImm();
316+
return true;
317+
}
318+
break;
319+
}
320+
}
321+
return false;
322+
}
323+
237324
bool isTerminator(const MCInst &Inst) const override {
238325
if (MCInstrAnalysis::isTerminator(Inst))
239326
return true;
@@ -327,8 +414,12 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
327414

328415
} // end anonymous namespace
329416

330-
static MCInstrAnalysis *createRISCVInstrAnalysis(const MCInstrInfo *Info) {
331-
return new RISCVMCInstrAnalysis(Info);
417+
static MCInstrAnalysis *createRISCV32InstrAnalysis(const MCInstrInfo *Info) {
418+
return new RISCVMCInstrAnalysis(Info, 32);
419+
}
420+
421+
static MCInstrAnalysis *createRISCV64InstrAnalysis(const MCInstrInfo *Info) {
422+
return new RISCVMCInstrAnalysis(Info, 64);
332423
}
333424

334425
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMC() {
@@ -344,12 +435,14 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMC() {
344435
TargetRegistry::RegisterELFStreamer(*T, createRISCVELFStreamer);
345436
TargetRegistry::RegisterObjectTargetStreamer(
346437
*T, createRISCVObjectTargetStreamer);
347-
TargetRegistry::RegisterMCInstrAnalysis(*T, createRISCVInstrAnalysis);
348-
349438
// Register the asm target streamer.
350439
TargetRegistry::RegisterAsmTargetStreamer(*T, createRISCVAsmTargetStreamer);
351440
// Register the null target streamer.
352441
TargetRegistry::RegisterNullTargetStreamer(*T,
353442
createRISCVNullTargetStreamer);
354443
}
444+
TargetRegistry::RegisterMCInstrAnalysis(getTheRISCV32Target(),
445+
createRISCV32InstrAnalysis);
446+
TargetRegistry::RegisterMCInstrAnalysis(getTheRISCV64Target(),
447+
createRISCV64InstrAnalysis);
355448
}
Binary file not shown.
Binary file not shown.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
if not "RISCV" in config.root.targets:
2+
config.unsupported = True
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# RUN: llvm-objdump -d %p/Inputs/riscv-ar-coverage | FileCheck %s
2+
3+
# CHECK: 0000000000001000 <_start>:
4+
# CHECK-NEXT: 1000: 00001517 auipc a0, 0x1
5+
# CHECK-NEXT: 1004: 00450513 addi a0, a0, 0x4 <target>
6+
# CHECK-NEXT: 1008: 00001517 auipc a0, 0x1
7+
# CHECK-NEXT: 100c: 1571 addi a0, a0, -0x4 <target>
8+
# CHECK-NEXT: 100e: 6509 lui a0, 0x2
9+
# CHECK-NEXT: 1010: 0045059b addiw a1, a0, 0x4 <target>
10+
# CHECK-NEXT: 1014: 6509 lui a0, 0x2
11+
# CHECK-NEXT: 1016: 2511 addiw a0, a0, 0x4 <target>
12+
# CHECK-NEXT: 1018: 00102537 lui a0, 0x102
13+
# CHECK-NEXT: 101c: c50c sw a1, 0x8(a0) <far_target>
14+
# CHECK-NEXT: 101e: 00102537 lui a0, 0x102
15+
# CHECK-NEXT: 1022: 4508 lw a0, 0x8(a0) <far_target>
16+
# CHECK-NEXT: 1024: 6509 lui a0, 0x2
17+
# CHECK-NEXT: 1026: 6585 lui a1, 0x1
18+
# CHECK-NEXT: 1028: 0306 slli t1, t1, 0x1
19+
# CHECK-NEXT: 102a: 0511 addi a0, a0, 0x4 <target>
20+
# CHECK-NEXT: 102c: 0505 addi a0, a0, 0x1
21+
# CHECK-NEXT: 102e: 00200037 lui zero, 0x200
22+
# CHECK-NEXT: 1032: 00a02423 sw a0, 0x8(zero)
23+
# CHECK-NEXT: 1036: 00101097 auipc ra, 0x101
24+
# CHECK-NEXT: 103a: fd6080e7 jalr -0x2a(ra) <func>
25+
# CHECK-NEXT: 103e: 00102437 lui s0, 0x102
26+
# CHECK-NEXT: 1042: 8800 sb s0, 0x0(s0) <target+0xffffc>
27+
# CHECK-NEXT: 1044: 00102137 lui sp, 0x102
28+
# CHECK-NEXT: 1048: 4522 lw a0, 0x8(sp) <far_target>
29+
30+
.global _start
31+
.text
32+
33+
# The core of the feature being added was address resolution for instruction
34+
# sequences where a register is populated by immediate values via two
35+
# separate instructions. First by an instruction that provides the upper bits
36+
# (auipc, lui ...) followed by another instruction for the lower bits (addi,
37+
# jalr, ld ...).
38+
39+
40+
_start:
41+
# Test block 1-3 each focus on a certain starting instruction in a sequences,
42+
# the ones that provide the upper bits. The other sequence is another
43+
# instruction the provides the lower bits. The second instruction is
44+
# arbitrarily chosen to increase code coverage
45+
46+
# test block #1
47+
lla a0, target # addi
48+
auipc a0, 0x1
49+
c.addi a0, -0x4 # c.addi
50+
51+
# test block #2
52+
c.lui a0, 0x2
53+
addiw a1, a0, 0x4 # addiw
54+
c.lui a0, 0x2
55+
c.addiw a0, 0x4 # c.addiw
56+
57+
# test block #3
58+
lui a0, 0x102
59+
sw a1, 0x8(a0) # sw
60+
lui a0, 0x102
61+
c.lw a0, 0x8(a0) # lw
62+
63+
# Test block 4 tests instruction interleaving, essentially the code's
64+
# ability to keep track of a valid sequence even if multiple other unrelated
65+
# instructions separate the two
66+
67+
# test #4
68+
lui a0, 0x2
69+
lui a1, 0x1 # unrelated instruction
70+
slli t1, t1, 0x1 # unrelated instruction
71+
addi a0, a0, 0x4
72+
addi a0, a0, 0x1
73+
74+
# Test 5 ensures that an instruction writing into the zero register does
75+
# not trigger resolution because that register's value cannot change and
76+
# the sequence is equivalent to never running the first instruction
77+
78+
# test #5
79+
lui x0, 0x200
80+
sw a0, 0x8(x0)
81+
82+
# Test 6 ensures that the newly added functionality is compatible with
83+
# code that already worked for branch instructions
84+
85+
# test #6
86+
call func
87+
88+
# test #7 zcb extension
89+
lui x8, 0x102
90+
# the immediate value for Zcb extension is heavily bounded, so we will relax
91+
# the requirement of hitting one of the labels and focus on correctness of the
92+
# resolution. This can be verified by looking at the source: The upper bits of
93+
# lui make the far jump related to .skip 0x100000 and then 8 more bytes must be
94+
# traversed before we hit far_target--.skip 0x4 and .word 1 in target. Adding 8
95+
# to address resolved for the instruction below yields exactly the desired label.
96+
c.sb x8, 0(x8)
97+
98+
# test #8 stack based load/stores
99+
lui sp, 0x102
100+
c.lwsp a0, 0x8(sp)
101+
102+
# these are the labels that the instructions above are expecteed to resolve to
103+
.section .data
104+
.skip 0x4
105+
target:
106+
.word 1
107+
.skip 0x100000
108+
far_target:
109+
.word 2
110+
func:
111+
ret
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# RUN: llvm-objdump -d %p/Inputs/riscv-ar | FileCheck %s
2+
3+
# CHECK: auipc a0, {{-?0x[0-9a-fA-F]+}}
4+
# CHECK: ld a0, {{-?0x[0-9a-fA-F]+}}(a0) <ldata+0xfa4>
5+
# CHECK: auipc a0, {{-?0x[0-9a-fA-F]+}}
6+
# CHECK: addi a0, a0, {{-?0x[0-9a-fA-F]+}} <gdata>
7+
# CHECK: auipc a0, {{-?0x[0-9a-fA-F]+}}
8+
# CHECK: addi a0, a0, {{-?0x[0-9a-fA-F]+}} <gdata>
9+
# CHECK: auipc a0, {{-?0x[0-9a-fA-F]+}}
10+
# CHECK: lw a0, {{-?0x[0-9a-fA-F]+}}(a0) <gdata>
11+
# CHECK: auipc a0, {{-?0x[0-9a-fA-F]+}}
12+
# CHECK: addi a0, a0, {{-?0x[0-9a-fA-F]+}} <ldata>
13+
# CHECK: auipc ra, {{-?0x[0-9a-fA-F]+}}
14+
# CHECK: jalr {{-?0x[0-9a-fA-F]+}}(ra) <func>
15+
# CHECK: auipc t1, {{-?0x[0-9a-fA-F]+}}
16+
# CHECK: jr {{-?0x[0-9a-fA-F]+}}(t1) <func>
17+
# CHECK: lui a0, {{-?0x[0-9a-fA-F]+}}
18+
# CHECK: addiw a0, a0, {{-?0x[0-9a-fA-F]+}} <gdata+0x12242678>
19+
# CHECK: lui a0, {{-?0x[0-9a-fA-F]+}}
20+
# CHECK: addiw a0, a0, {{-?0x[0-9a-fA-F]+}} <gdata+0x1438ad>
21+
# CHECK: slli a0, a0, {{-?0x[0-9a-fA-F]+}}
22+
# CHECK: addi a0, a0, {{-?0x[0-9a-fA-F]+}}
23+
# CHECK: slli a0, a0, {{-?0x[0-9a-fA-F]+}}
24+
# CHECK: addi a0, a0, {{-?0x[0-9a-fA-F]+}}
25+
# CHECK: slli a0, a0, {{-?0x[0-9a-fA-F]+}}
26+
# CHECK: addi a0, a0, {{-?0x[0-9a-fA-F]+}}
27+
# CHECK: lui a0, {{-?0x[0-9a-fA-F]+}}
28+
# CHECK: lui a0, {{-?0x[0-9a-fA-F]+}}
29+
# CHECK: addiw a0, a0, {{-?0x[0-9a-fA-F]+}} <_start+0xfefff>
30+
31+
.global _start
32+
.text
33+
_start:
34+
la a0, gdata
35+
lla a0, gdata
36+
lla a0, gdata
37+
lw a0, gdata
38+
lla a0, ldata
39+
40+
call func
41+
tail func
42+
43+
li a0, 0x12345678
44+
li a0, 0x1234567890abcdef
45+
li a0, 0x10000
46+
li a0, 0xfffff
47+
48+
.skip 0x100000
49+
func:
50+
ret
51+
52+
ldata:
53+
.int 0
54+
55+
.data
56+
gdata:
57+
.int 0

0 commit comments

Comments
 (0)