[RISCV] Support .option {no}exact (#122483)
This implements [the `.option exact` and `.option noexact` proposal](https://github.com/riscv-non-isa/riscv-asm-manual/pull/122) for RISC-V. `.option exact` turns off: - Compression - Branch Relaxation - Linker Relaxation `.option noexact` turns these back on, and is also the default, matching the current behaviour.
This commit is contained in:
parent
27539c3f90
commit
6a371c7744
@ -152,6 +152,9 @@ Changes to the RISC-V Backend
|
||||
handlers.
|
||||
* When the experimental extension `Xqcili` is enabled, `qc.e.li` and `qc.li` may
|
||||
now be used to materialize immediates.
|
||||
* Adds assembler support for ``.option exact``, which disables automatic compression,
|
||||
and branch and linker relaxation. This can be disabled with ``.option noexact``,
|
||||
which is also the default.
|
||||
|
||||
Changes to the WebAssembly Backend
|
||||
----------------------------------
|
||||
|
@ -3205,6 +3205,26 @@ bool RISCVAsmParser::parseDirectiveOption() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Option == "exact") {
|
||||
if (Parser.parseEOL())
|
||||
return true;
|
||||
|
||||
getTargetStreamer().emitDirectiveOptionExact();
|
||||
setFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
|
||||
clearFeatureBits(RISCV::FeatureRelax, "relax");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Option == "noexact") {
|
||||
if (Parser.parseEOL())
|
||||
return true;
|
||||
|
||||
getTargetStreamer().emitDirectiveOptionNoExact();
|
||||
clearFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
|
||||
setFeatureBits(RISCV::FeatureRelax, "relax");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Option == "rvc") {
|
||||
if (Parser.parseEOL())
|
||||
return true;
|
||||
@ -3261,9 +3281,10 @@ bool RISCVAsmParser::parseDirectiveOption() {
|
||||
}
|
||||
|
||||
// Unknown option.
|
||||
Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
|
||||
"'rvc', 'norvc', 'arch', 'relax' or "
|
||||
"'norelax'");
|
||||
Warning(Parser.getTok().getLoc(),
|
||||
"unknown option, expected 'push', 'pop', "
|
||||
"'rvc', 'norvc', 'arch', 'relax', 'norelax', "
|
||||
"'exact', or 'noexact'");
|
||||
Parser.eatToEndOfStatement();
|
||||
return false;
|
||||
}
|
||||
@ -3473,10 +3494,13 @@ bool RISCVAsmParser::parseDirectiveVariantCC() {
|
||||
|
||||
void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
|
||||
MCInst CInst;
|
||||
bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
|
||||
bool Res = false;
|
||||
const MCSubtargetInfo &STI = getSTI();
|
||||
if (!STI.hasFeature(RISCV::FeatureExactAssembly))
|
||||
Res = RISCVRVC::compress(CInst, Inst, STI);
|
||||
if (Res)
|
||||
++RISCVNumInstrsCompressed;
|
||||
S.emitInstruction((Res ? CInst : Inst), getSTI());
|
||||
S.emitInstruction((Res ? CInst : Inst), STI);
|
||||
}
|
||||
|
||||
void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
|
||||
|
@ -171,8 +171,39 @@ bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(
|
||||
}
|
||||
}
|
||||
|
||||
// Given a compressed control flow instruction this function returns
|
||||
// the expanded instruction.
|
||||
static unsigned getRelaxedOpcode(unsigned Op) {
|
||||
switch (Op) {
|
||||
default:
|
||||
return Op;
|
||||
case RISCV::C_BEQZ:
|
||||
return RISCV::BEQ;
|
||||
case RISCV::C_BNEZ:
|
||||
return RISCV::BNE;
|
||||
case RISCV::C_J:
|
||||
case RISCV::C_JAL: // fall through.
|
||||
return RISCV::JAL;
|
||||
case RISCV::BEQ:
|
||||
return RISCV::PseudoLongBEQ;
|
||||
case RISCV::BNE:
|
||||
return RISCV::PseudoLongBNE;
|
||||
case RISCV::BLT:
|
||||
return RISCV::PseudoLongBLT;
|
||||
case RISCV::BGE:
|
||||
return RISCV::PseudoLongBGE;
|
||||
case RISCV::BLTU:
|
||||
return RISCV::PseudoLongBLTU;
|
||||
case RISCV::BGEU:
|
||||
return RISCV::PseudoLongBGEU;
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
if (STI.hasFeature(RISCV::FeatureExactAssembly))
|
||||
return;
|
||||
|
||||
MCInst Res;
|
||||
switch (Inst.getOpcode()) {
|
||||
default:
|
||||
@ -341,36 +372,14 @@ std::pair<bool, bool> RISCVAsmBackend::relaxLEB128(const MCAssembler &Asm,
|
||||
return std::make_pair(Expr.evaluateKnownAbsolute(Value, Asm), false);
|
||||
}
|
||||
|
||||
// Given a compressed control flow instruction this function returns
|
||||
// the expanded instruction.
|
||||
unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
|
||||
switch (Op) {
|
||||
default:
|
||||
return Op;
|
||||
case RISCV::C_BEQZ:
|
||||
return RISCV::BEQ;
|
||||
case RISCV::C_BNEZ:
|
||||
return RISCV::BNE;
|
||||
case RISCV::C_J:
|
||||
case RISCV::C_JAL: // fall through.
|
||||
return RISCV::JAL;
|
||||
case RISCV::BEQ:
|
||||
return RISCV::PseudoLongBEQ;
|
||||
case RISCV::BNE:
|
||||
return RISCV::PseudoLongBNE;
|
||||
case RISCV::BLT:
|
||||
return RISCV::PseudoLongBLT;
|
||||
case RISCV::BGE:
|
||||
return RISCV::PseudoLongBGE;
|
||||
case RISCV::BLTU:
|
||||
return RISCV::PseudoLongBLTU;
|
||||
case RISCV::BGEU:
|
||||
return RISCV::PseudoLongBGEU;
|
||||
}
|
||||
}
|
||||
|
||||
bool RISCVAsmBackend::mayNeedRelaxation(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
// This function has access to two STIs, the member of the AsmBackend, and the
|
||||
// one passed as an argument. The latter is more specific, so we query it for
|
||||
// specific features.
|
||||
if (STI.hasFeature(RISCV::FeatureExactAssembly))
|
||||
return false;
|
||||
|
||||
return getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode();
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,6 @@ public:
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
unsigned getRelaxedOpcode(unsigned Op) const;
|
||||
|
||||
void relaxInstruction(MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
|
@ -47,14 +47,16 @@ RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() {
|
||||
return static_cast<RISCVELFStreamer &>(Streamer);
|
||||
}
|
||||
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionExact() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionNoExact() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
|
||||
|
||||
void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
|
||||
getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
|
||||
|
@ -56,14 +56,16 @@ public:
|
||||
RISCVELFStreamer &getStreamer();
|
||||
RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
|
||||
|
||||
void emitDirectiveOptionPush() override;
|
||||
void emitDirectiveOptionPop() override;
|
||||
void emitDirectiveOptionExact() override;
|
||||
void emitDirectiveOptionNoExact() override;
|
||||
void emitDirectiveOptionPIC() override;
|
||||
void emitDirectiveOptionNoPIC() override;
|
||||
void emitDirectiveOptionRVC() override;
|
||||
void emitDirectiveOptionNoRVC() override;
|
||||
void emitDirectiveOptionPop() override;
|
||||
void emitDirectiveOptionPush() override;
|
||||
void emitDirectiveOptionRelax() override;
|
||||
void emitDirectiveOptionNoRelax() override;
|
||||
void emitDirectiveOptionRVC() override;
|
||||
void emitDirectiveOptionNoRVC() override;
|
||||
void emitDirectiveVariantCC(MCSymbol &Symbol) override;
|
||||
|
||||
void finish() override;
|
||||
|
@ -33,16 +33,18 @@ RISCVTargetStreamer::RISCVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
|
||||
void RISCVTargetStreamer::finish() { finishAttributeSection(); }
|
||||
void RISCVTargetStreamer::reset() {}
|
||||
|
||||
void RISCVTargetStreamer::emitDirectiveOptionPush() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionPop() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionPIC() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionNoPIC() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionRVC() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionRelax() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionNoRelax() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionArch(
|
||||
ArrayRef<RISCVOptionArchArg> Args) {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionExact() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionNoExact() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionPIC() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionNoPIC() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionPop() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionPush() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionRelax() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionNoRelax() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionRVC() {}
|
||||
void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {}
|
||||
void RISCVTargetStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {}
|
||||
void RISCVTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {}
|
||||
void RISCVTargetStreamer::finishAttributeSection() {}
|
||||
@ -125,6 +127,14 @@ void RISCVTargetAsmStreamer::emitDirectiveOptionNoRVC() {
|
||||
OS << "\t.option\tnorvc\n";
|
||||
}
|
||||
|
||||
void RISCVTargetAsmStreamer::emitDirectiveOptionExact() {
|
||||
OS << "\t.option\texact\n";
|
||||
}
|
||||
|
||||
void RISCVTargetAsmStreamer::emitDirectiveOptionNoExact() {
|
||||
OS << "\t.option\tnoexact\n";
|
||||
}
|
||||
|
||||
void RISCVTargetAsmStreamer::emitDirectiveOptionRelax() {
|
||||
OS << "\t.option\trelax\n";
|
||||
}
|
||||
|
@ -41,15 +41,17 @@ public:
|
||||
void finish() override;
|
||||
virtual void reset();
|
||||
|
||||
virtual void emitDirectiveOptionPush();
|
||||
virtual void emitDirectiveOptionPop();
|
||||
virtual void emitDirectiveOptionArch(ArrayRef<RISCVOptionArchArg> Args);
|
||||
virtual void emitDirectiveOptionExact();
|
||||
virtual void emitDirectiveOptionNoExact();
|
||||
virtual void emitDirectiveOptionPIC();
|
||||
virtual void emitDirectiveOptionNoPIC();
|
||||
virtual void emitDirectiveOptionRVC();
|
||||
virtual void emitDirectiveOptionNoRVC();
|
||||
virtual void emitDirectiveOptionPop();
|
||||
virtual void emitDirectiveOptionPush();
|
||||
virtual void emitDirectiveOptionRelax();
|
||||
virtual void emitDirectiveOptionNoRelax();
|
||||
virtual void emitDirectiveOptionArch(ArrayRef<RISCVOptionArchArg> Args);
|
||||
virtual void emitDirectiveOptionRVC();
|
||||
virtual void emitDirectiveOptionNoRVC();
|
||||
virtual void emitDirectiveVariantCC(MCSymbol &Symbol);
|
||||
virtual void emitAttribute(unsigned Attribute, unsigned Value);
|
||||
virtual void finishAttributeSection();
|
||||
@ -78,15 +80,17 @@ class RISCVTargetAsmStreamer : public RISCVTargetStreamer {
|
||||
public:
|
||||
RISCVTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
|
||||
|
||||
void emitDirectiveOptionPush() override;
|
||||
void emitDirectiveOptionPop() override;
|
||||
void emitDirectiveOptionArch(ArrayRef<RISCVOptionArchArg> Args) override;
|
||||
void emitDirectiveOptionExact() override;
|
||||
void emitDirectiveOptionNoExact() override;
|
||||
void emitDirectiveOptionPIC() override;
|
||||
void emitDirectiveOptionNoPIC() override;
|
||||
void emitDirectiveOptionRVC() override;
|
||||
void emitDirectiveOptionNoRVC() override;
|
||||
void emitDirectiveOptionPop() override;
|
||||
void emitDirectiveOptionPush() override;
|
||||
void emitDirectiveOptionRelax() override;
|
||||
void emitDirectiveOptionNoRelax() override;
|
||||
void emitDirectiveOptionArch(ArrayRef<RISCVOptionArchArg> Args) override;
|
||||
void emitDirectiveOptionRVC() override;
|
||||
void emitDirectiveOptionNoRVC() override;
|
||||
void emitDirectiveVariantCC(MCSymbol &Symbol) override;
|
||||
};
|
||||
|
||||
|
@ -1496,6 +1496,10 @@ def FeatureRelax
|
||||
: SubtargetFeature<"relax", "EnableLinkerRelax", "true",
|
||||
"Enable Linker relaxation.">;
|
||||
|
||||
def FeatureExactAssembly
|
||||
: SubtargetFeature<"exact-asm", "EnableExactAssembly", "true",
|
||||
"Enable Exact Assembly (Disables Compression and Relaxation)">;
|
||||
|
||||
foreach i = {1-31} in
|
||||
def FeatureReserveX#i :
|
||||
SubtargetFeature<"reserve-x"#i, "UserReservedRegister[RISCV::X"#i#"]",
|
||||
|
@ -14,6 +14,7 @@
|
||||
; CHECK-NEXT: disable-latency-sched-heuristic - Disable latency scheduling heuristic.
|
||||
; CHECK-NEXT: dlen-factor-2 - Vector unit DLEN(data path width) is half of VLEN.
|
||||
; CHECK-NEXT: e - 'E' (Embedded Instruction Set with 16 GPRs).
|
||||
; CHECK-NEXT: exact-asm - Enable Exact Assembly (Disables Compression and Relaxation).
|
||||
; CHECK-NEXT: experimental - Experimental intrinsics.
|
||||
; CHECK-NEXT: experimental-p - 'P' ('Base P' (Packed SIMD)).
|
||||
; CHECK-NEXT: experimental-rvm23u32 - RISC-V experimental-rvm23u32 profile.
|
||||
|
20
llvm/test/CodeGen/RISCV/option-exact-inlineasm.ll
Normal file
20
llvm/test/CodeGen/RISCV/option-exact-inlineasm.ll
Normal file
@ -0,0 +1,20 @@
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+relax,+c %s --filetype=obj -o - \
|
||||
; RUN: | llvm-objdump --triple=riscv32 --mattr=+c -M no-aliases -dr - \
|
||||
; RUN: | FileCheck %s
|
||||
|
||||
define i32 @foo(ptr noundef %f) nounwind {
|
||||
; CHECK-LABEL: <foo>:
|
||||
; CHECK: auipc ra, 0x0
|
||||
; CHECK-NEXT: R_RISCV_CALL_PLT undefined
|
||||
; CHECK-NEXT: jalr ra, 0x0(ra)
|
||||
; CHECK-NEXT: lw a0, 0x0(a0)
|
||||
; CHECK-NEXT: c.jr ra
|
||||
|
||||
entry:
|
||||
%0 = tail call i32 asm sideeffect "
|
||||
.option exact
|
||||
call undefined@plt
|
||||
lw $0, ($1)
|
||||
.option noexact", "=^cr,^cr"(ptr %f)
|
||||
ret i32 %0
|
||||
}
|
128
llvm/test/MC/RISCV/option-exact.s
Normal file
128
llvm/test/MC/RISCV/option-exact.s
Normal file
@ -0,0 +1,128 @@
|
||||
# RUN: llvm-mc -triple riscv32 -show-encoding -mattr=+c,+relax \
|
||||
# RUN: -M no-aliases %s | FileCheck -check-prefixes=CHECK-ASM,CHECK-INST %s
|
||||
# RUN: llvm-mc -triple riscv32 -filetype=obj -mattr=+c,+relax %s \
|
||||
# RUN: | llvm-objdump --triple=riscv32 --mattr=+c -dr --no-print-imm-hex -M no-aliases - \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP,CHECK-INST %s
|
||||
|
||||
# RUN: llvm-mc -triple riscv64 -show-encoding \
|
||||
# RUN: -M no-aliases -mattr=+c,+relax %s \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-ASM %s
|
||||
# RUN: llvm-mc -triple riscv64 -filetype=obj -mattr=+c,+relax %s \
|
||||
# RUN: | llvm-objdump --triple=riscv64 --mattr=+c -dr --no-print-imm-hex -M no-aliases - \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP,CHECK-INST %s
|
||||
|
||||
## `.option exact` disables a variety of assembler behaviour:
|
||||
## - automatic compression
|
||||
## - branch relaxation (of short branches to longer equivalent sequences)
|
||||
## - linker relaxation (emitting R_RISCV_RELAX)
|
||||
## `.option noexact` enables these behaviours again. It is also the default.
|
||||
|
||||
# CHECK-OBJDUMP: 4108
|
||||
# CHECK-INST: c.lw a0, 0(a0)
|
||||
# CHECK-ASM: # encoding: [0x08,0x41]
|
||||
lw a0, 0(a0)
|
||||
|
||||
# CHECK-OBJDUMP: 4108
|
||||
# CHECK-INST: c.lw a0, 0(a0)
|
||||
# CHECK-ASM: # encoding: [0x08,0x41]
|
||||
c.lw a0, 0(a0)
|
||||
|
||||
# CHECK-ASM: call undefined
|
||||
# CHECK-ASM-SAME: # encoding: [0x97'A',A,A,A,0xe7'A',0x80'A',A,A]
|
||||
# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_call_plt
|
||||
# CHECK-ASM-NEXT: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
|
||||
# CHECK-OBJDUMP: auipc ra, 0
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_CALL_PLT undefined
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_RELAX *ABS*
|
||||
# CHECK-OBJDUMP-NEXT: jalr ra
|
||||
call undefined@plt
|
||||
|
||||
# CHECK-ASM: beq a0, a1, undefined
|
||||
# CHECK-ASM-SAME: # encoding: [0x63'A',A,0xb5'A',A]
|
||||
# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_branch
|
||||
# CHECK-OBJDUMP: bne a0, a1, 0x14
|
||||
# CHECK-OBJDUMP-NEXT: jal zero, 0x10
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_JAL undefined
|
||||
beq a0, a1, undefined
|
||||
|
||||
# CHECK-ASM: c.j undefined
|
||||
# CHECK-ASM-SAME: # encoding: [0bAAAAAA01,0b101AAAAA]
|
||||
# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_rvc_jump
|
||||
# CHECK-OBJDUMP: jal zero, 0x14
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_JAL undefined
|
||||
c.j undefined
|
||||
|
||||
# CHECK-ASM: .option exact
|
||||
.option exact
|
||||
|
||||
# CHECK-OBJDUMP: 00052503
|
||||
# CHECK-INST: lw a0, 0(a0)
|
||||
# CHECK-ASM: # encoding: [0x03,0x25,0x05,0x00]
|
||||
lw a0, 0(a0)
|
||||
|
||||
# CHECK-OBJDUMP: 4108
|
||||
# CHECK-INST: c.lw a0, 0(a0)
|
||||
# CHECK-ASM: # encoding: [0x08,0x41]
|
||||
c.lw a0, 0(a0)
|
||||
|
||||
# CHECK-ASM: call undefined
|
||||
# CHECK-ASM-SAME: # encoding: [0x97'A',A,A,A,0xe7'A',0x80'A',A,A]
|
||||
# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_call_plt
|
||||
# CHECK-ASM-NOT: fixup_riscv_relax
|
||||
# CHECK-OBJDUMP: auipc ra, 0
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_CALL_PLT undefined
|
||||
# CHECK-OBJDUMP-NOT: R_RISCV_RELAX
|
||||
# CHECK-OBJDUMP-NEXT: jalr ra, 0(ra)
|
||||
call undefined@plt
|
||||
|
||||
# CHECK-ASM: beq a0, a1, undefined
|
||||
# CHECK-ASM-SAME: # encoding: [0x63'A',A,0xb5'A',A]
|
||||
# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_branch
|
||||
# CHECK-OBJDUMP: beq a0, a1, 0x26
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_BRANCH undefined
|
||||
beq a0, a1, undefined
|
||||
|
||||
# CHECK-ASM: c.j undefined
|
||||
# CHECK-ASM-SAME: # encoding: [0bAAAAAA01,0b101AAAAA]
|
||||
# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_rvc_jump
|
||||
# CHECK-OBJDUMP: c.j 0x2a
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_RVC_JUMP undefined
|
||||
c.j undefined
|
||||
|
||||
# CHECK-ASM: .option noexact
|
||||
.option noexact
|
||||
|
||||
# CHECK-OBJDUMP: 4108
|
||||
# CHECK-INST: c.lw a0, 0(a0)
|
||||
# CHECK-ASM: # encoding: [0x08,0x41]
|
||||
lw a0, 0(a0)
|
||||
|
||||
# CHECK-OBJDUMP: 4108
|
||||
# CHECK-INST: c.lw a0, 0(a0)
|
||||
# CHECK-ASM: # encoding: [0x08,0x41]
|
||||
c.lw a0, 0(a0)
|
||||
|
||||
# CHECK-ASM: call undefined
|
||||
# CHECK-ASM-SAME: # encoding: [0x97'A',A,A,A,0xe7'A',0x80'A',A,A]
|
||||
# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_call_plt
|
||||
# CHECK-ASM-NEXT: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
|
||||
# CHECK-OBJDUMP: auipc ra, 0
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_CALL_PLT undefined
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_RELAX *ABS*
|
||||
# CHECK-OBJDUMP-NEXT: jalr ra, 0(ra)
|
||||
call undefined@plt
|
||||
|
||||
# CHECK-ASM: beq a0, a1, undefined
|
||||
# CHECK-ASM-SAME: # encoding: [0x63'A',A,0xb5'A',A]
|
||||
# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_branch
|
||||
# CHECK-OBJDUMP: bne a0, a1, 0x40
|
||||
# CHECK-OBJDUMP-NEXT: jal zero, 0x3c
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_JAL undefined
|
||||
beq a0, a1, undefined
|
||||
|
||||
# CHECK-ASM: c.j undefined
|
||||
# CHECK-ASM-SAME: # encoding: [0bAAAAAA01,0b101AAAAA]
|
||||
# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_rvc_jump
|
||||
# CHECK-OBJDUMP: jal zero, 0x40
|
||||
# CHECK-OBJDUMP-NEXT: R_RISCV_JAL undefined
|
||||
c.j undefined
|
@ -53,7 +53,7 @@
|
||||
# CHECK: :[[#@LINE+1]]:13: error: expected newline
|
||||
.option rvc foo
|
||||
|
||||
# CHECK: :[[#@LINE+1]]:12: warning: unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'arch', 'relax' or 'norelax'
|
||||
# CHECK: :[[#@LINE+1]]:12: warning: unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'arch', 'relax', 'norelax', 'exact', or 'noexact'
|
||||
.option bar
|
||||
|
||||
# CHECK: :[[#@LINE+1]]:12: error: .option pop with no .option push
|
||||
|
Loading…
x
Reference in New Issue
Block a user