mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-04 03:06:28 +00:00
[RISCV] Support .option relax and .option norelax
This extends the .option support from D45864 to enable/disable the relax feature flag from D44886 During parsing of the relax/norelax directives, the RISCV::FeatureRelax feature bits of the SubtargetInfo stored in the AsmParser are updated appropriately to reflect whether relaxation is currently enabled in the parser. When an instruction is parsed, the parser checks if relaxation is currently enabled and if so, gets a handle to the AsmBackend and sets the ForceRelocs flag. The AsmBackend uses a combination of the original RISCV::FeatureRelax feature bits set by e.g -mattr=+/-relax and the ForceRelocs flag to determine whether to emit relocations for symbol and branch diffs. Diff relocations should therefore only not be emitted if the relax flag was not set on the command line and no instruction was ever parsed in a section with relaxation enabled to ensure correct diffs are emitted. Differential Revision: https://reviews.llvm.org/D46423 Patch by Lewis Revill. llvm-svn: 346655
This commit is contained in:
parent
6478e51fd7
commit
59ae392352
@ -7,12 +7,14 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/RISCVAsmBackend.h"
|
||||
#include "MCTargetDesc/RISCVMCExpr.h"
|
||||
#include "MCTargetDesc/RISCVMCTargetDesc.h"
|
||||
#include "MCTargetDesc/RISCVTargetStreamer.h"
|
||||
#include "Utils/RISCVBaseInfo.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
@ -1164,6 +1166,21 @@ bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
|
||||
bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
|
||||
StringRef Name, SMLoc NameLoc,
|
||||
OperandVector &Operands) {
|
||||
// Ensure that if the instruction occurs when relaxation is enabled,
|
||||
// relocations are forced for the file. Ideally this would be done when there
|
||||
// is enough information to reliably determine if the instruction itself may
|
||||
// cause relaxations. Unfortunately instruction processing stage occurs in the
|
||||
// same pass as relocation emission, so it's too late to set a 'sticky bit'
|
||||
// for the entire file.
|
||||
if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) {
|
||||
auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
|
||||
if (Assembler != nullptr) {
|
||||
RISCVAsmBackend &MAB =
|
||||
static_cast<RISCVAsmBackend &>(Assembler->getBackend());
|
||||
MAB.setForceRelocs();
|
||||
}
|
||||
}
|
||||
|
||||
// First operand is token for instruction
|
||||
Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64()));
|
||||
|
||||
@ -1291,9 +1308,33 @@ bool RISCVAsmParser::parseDirectiveOption() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Option == "relax") {
|
||||
getTargetStreamer().emitDirectiveOptionRelax();
|
||||
|
||||
Parser.Lex();
|
||||
if (Parser.getTok().isNot(AsmToken::EndOfStatement))
|
||||
return Error(Parser.getTok().getLoc(),
|
||||
"unexpected token, expected end of statement");
|
||||
|
||||
setFeatureBits(RISCV::FeatureRelax, "relax");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Option == "norelax") {
|
||||
getTargetStreamer().emitDirectiveOptionNoRelax();
|
||||
|
||||
Parser.Lex();
|
||||
if (Parser.getTok().isNot(AsmToken::EndOfStatement))
|
||||
return Error(Parser.getTok().getLoc(),
|
||||
"unexpected token, expected end of statement");
|
||||
|
||||
clearFeatureBits(RISCV::FeatureRelax, "relax");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unknown option.
|
||||
Warning(Parser.getTok().getLoc(),
|
||||
"unknown option, expected 'rvc' or 'norvc'");
|
||||
"unknown option, expected 'rvc', 'norvc', 'relax' or 'norelax'");
|
||||
Parser.eatToEndOfStatement();
|
||||
return false;
|
||||
}
|
||||
|
@ -7,115 +7,20 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/RISCVFixupKinds.h"
|
||||
#include "MCTargetDesc/RISCVMCTargetDesc.h"
|
||||
#include "RISCVAsmBackend.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCFixupKindInfo.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class RISCVAsmBackend : public MCAsmBackend {
|
||||
const MCSubtargetInfo &STI;
|
||||
uint8_t OSABI;
|
||||
bool Is64Bit;
|
||||
|
||||
public:
|
||||
RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit)
|
||||
: MCAsmBackend(support::little), STI(STI), OSABI(OSABI),
|
||||
Is64Bit(Is64Bit) {}
|
||||
~RISCVAsmBackend() override {}
|
||||
|
||||
// Generate diff expression relocations if the relax feature is enabled,
|
||||
// otherwise it is safe for the assembler to calculate these internally.
|
||||
bool requiresDiffExpressionRelocations() const override {
|
||||
return STI.getFeatureBits()[RISCV::FeatureRelax];
|
||||
}
|
||||
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, MutableArrayRef<char> Data,
|
||||
uint64_t Value, bool IsResolved,
|
||||
const MCSubtargetInfo *STI) const override;
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
createObjectTargetWriter() const override;
|
||||
|
||||
// If linker relaxation is enabled, always emit relocations even if the fixup
|
||||
// can be resolved. This is necessary for correctness as offsets may change
|
||||
// during relaxation.
|
||||
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target) override {
|
||||
return STI.getFeatureBits()[RISCV::FeatureRelax];
|
||||
}
|
||||
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override {
|
||||
llvm_unreachable("Handled by fixupNeedsRelaxationAdvanced");
|
||||
}
|
||||
|
||||
bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
|
||||
uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout,
|
||||
const bool WasForced) const override;
|
||||
|
||||
unsigned getNumFixupKinds() const override {
|
||||
return RISCV::NumTargetFixupKinds;
|
||||
}
|
||||
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
|
||||
const static MCFixupKindInfo Infos[] = {
|
||||
// This table *must* be in the order that the fixup_* kinds are defined in
|
||||
// RISCVFixupKinds.h.
|
||||
//
|
||||
// name offset bits flags
|
||||
{ "fixup_riscv_hi20", 12, 20, 0 },
|
||||
{ "fixup_riscv_lo12_i", 20, 12, 0 },
|
||||
{ "fixup_riscv_lo12_s", 0, 32, 0 },
|
||||
{ "fixup_riscv_pcrel_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_pcrel_lo12_i", 20, 12, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_pcrel_lo12_s", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_relax", 0, 0, 0 }
|
||||
};
|
||||
static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds,
|
||||
"Not all fixup kinds added to Infos array");
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
|
||||
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
|
||||
"Invalid kind!");
|
||||
return Infos[Kind - FirstTargetFixupKind];
|
||||
}
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
unsigned getRelaxedOpcode(unsigned Op) const;
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override;
|
||||
|
||||
|
||||
bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
|
||||
};
|
||||
|
||||
|
||||
bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup,
|
||||
bool Resolved,
|
||||
uint64_t Value,
|
||||
@ -348,8 +253,6 @@ RISCVAsmBackend::createObjectTargetWriter() const {
|
||||
return createRISCVELFObjectWriter(OSABI, Is64Bit);
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,
|
||||
const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
|
118
lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
Normal file
118
lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
Normal file
@ -0,0 +1,118 @@
|
||||
//===-- RISCVAsmBackend.h - RISCV Assembler Backend -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVASMBACKEND_H
|
||||
#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVASMBACKEND_H
|
||||
|
||||
#include "MCTargetDesc/RISCVFixupKinds.h"
|
||||
#include "MCTargetDesc/RISCVMCTargetDesc.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCFixupKindInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAssembler;
|
||||
class MCObjectTargetWriter;
|
||||
class raw_ostream;
|
||||
|
||||
class RISCVAsmBackend : public MCAsmBackend {
|
||||
const MCSubtargetInfo &STI;
|
||||
uint8_t OSABI;
|
||||
bool Is64Bit;
|
||||
bool ForceRelocs = false;
|
||||
|
||||
public:
|
||||
RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit)
|
||||
: MCAsmBackend(support::little), STI(STI), OSABI(OSABI),
|
||||
Is64Bit(Is64Bit) {}
|
||||
~RISCVAsmBackend() override {}
|
||||
|
||||
void setForceRelocs() { ForceRelocs = true; }
|
||||
|
||||
// Generate diff expression relocations if the relax feature is enabled or had
|
||||
// previously been enabled, otherwise it is safe for the assembler to
|
||||
// calculate these internally.
|
||||
bool requiresDiffExpressionRelocations() const override {
|
||||
return STI.getFeatureBits()[RISCV::FeatureRelax] || ForceRelocs;
|
||||
}
|
||||
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, MutableArrayRef<char> Data,
|
||||
uint64_t Value, bool IsResolved,
|
||||
const MCSubtargetInfo *STI) const override;
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
createObjectTargetWriter() const override;
|
||||
|
||||
// If linker relaxation is enabled, or the relax option had previously been
|
||||
// enabled, always emit relocations even if the fixup can be resolved. This is
|
||||
// necessary for correctness as offsets may change during relaxation.
|
||||
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target) override {
|
||||
return STI.getFeatureBits()[RISCV::FeatureRelax] || ForceRelocs;
|
||||
}
|
||||
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override {
|
||||
llvm_unreachable("Handled by fixupNeedsRelaxationAdvanced");
|
||||
}
|
||||
|
||||
bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
|
||||
uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout,
|
||||
const bool WasForced) const override;
|
||||
|
||||
unsigned getNumFixupKinds() const override {
|
||||
return RISCV::NumTargetFixupKinds;
|
||||
}
|
||||
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
|
||||
const static MCFixupKindInfo Infos[] = {
|
||||
// This table *must* be in the order that the fixup_* kinds are defined in
|
||||
// RISCVFixupKinds.h.
|
||||
//
|
||||
// name offset bits flags
|
||||
{ "fixup_riscv_hi20", 12, 20, 0 },
|
||||
{ "fixup_riscv_lo12_i", 20, 12, 0 },
|
||||
{ "fixup_riscv_lo12_s", 0, 32, 0 },
|
||||
{ "fixup_riscv_pcrel_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_pcrel_lo12_i", 20, 12, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_pcrel_lo12_s", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_relax", 0, 0, 0 }
|
||||
};
|
||||
static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds,
|
||||
"Not all fixup kinds added to Infos array");
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
|
||||
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
|
||||
"Invalid kind!");
|
||||
return Infos[Kind - FirstTargetFixupKind];
|
||||
}
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
unsigned getRelaxedOpcode(unsigned Op) const;
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override;
|
||||
|
||||
|
||||
bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -40,3 +40,5 @@ MCELFStreamer &RISCVTargetELFStreamer::getStreamer() {
|
||||
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
|
||||
|
@ -22,6 +22,8 @@ public:
|
||||
|
||||
virtual void emitDirectiveOptionRVC();
|
||||
virtual void emitDirectiveOptionNoRVC();
|
||||
virtual void emitDirectiveOptionRelax();
|
||||
virtual void emitDirectiveOptionNoRelax();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -30,3 +30,11 @@ void RISCVTargetAsmStreamer::emitDirectiveOptionRVC() {
|
||||
void RISCVTargetAsmStreamer::emitDirectiveOptionNoRVC() {
|
||||
OS << "\t.option\tnorvc\n";
|
||||
}
|
||||
|
||||
void RISCVTargetAsmStreamer::emitDirectiveOptionRelax() {
|
||||
OS << "\t.option\trelax\n";
|
||||
}
|
||||
|
||||
void RISCVTargetAsmStreamer::emitDirectiveOptionNoRelax() {
|
||||
OS << "\t.option\tnorelax\n";
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ public:
|
||||
|
||||
virtual void emitDirectiveOptionRVC() = 0;
|
||||
virtual void emitDirectiveOptionNoRVC() = 0;
|
||||
virtual void emitDirectiveOptionRelax() = 0;
|
||||
virtual void emitDirectiveOptionNoRelax() = 0;
|
||||
};
|
||||
|
||||
// This part is for ascii assembly output
|
||||
@ -31,6 +33,8 @@ public:
|
||||
|
||||
void emitDirectiveOptionRVC() override;
|
||||
void emitDirectiveOptionNoRVC() override;
|
||||
void emitDirectiveOptionRelax() override;
|
||||
void emitDirectiveOptionNoRelax() override;
|
||||
};
|
||||
|
||||
}
|
||||
|
20
test/CodeGen/RISCV/fixups-relax-diff.ll
Normal file
20
test/CodeGen/RISCV/fixups-relax-diff.ll
Normal file
@ -0,0 +1,20 @@
|
||||
; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=+relax %s -o - \
|
||||
; RUN: | llvm-readobj -r | FileCheck -check-prefix=RELAX %s
|
||||
; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=-relax %s -o - \
|
||||
; RUN: | llvm-readobj -r | FileCheck -check-prefix=NORELAX %s
|
||||
|
||||
; This test checks that a diff inserted via inline assembly only causes
|
||||
; relocations when relaxation is enabled. This isn't an assembly test
|
||||
; as the assembler takes a different path through LLVM, which is
|
||||
; already covered by the fixups-expr.s test.
|
||||
|
||||
define i32 @main() {
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
store i32 0, i32* %retval, align 4
|
||||
; RELAX: R_RISCV_ADD64 b
|
||||
; RELAX: R_RISCV_SUB64 a
|
||||
; NORELAX-NOT: R_RISCV
|
||||
call void asm sideeffect "a:\0Ab:\0A.dword b-a", ""()
|
||||
ret i32 0
|
||||
}
|
16
test/CodeGen/RISCV/option-norelax.ll
Normal file
16
test/CodeGen/RISCV/option-norelax.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+relax -filetype=obj < %s \
|
||||
; RUN: | llvm-objdump -d -r - | FileCheck %s
|
||||
|
||||
; This test demonstrates that .option norelax has no effect on codegen
|
||||
; when emitting an ELF directly.
|
||||
|
||||
declare i32 @foo(i32)
|
||||
|
||||
define i32 @bar(i32 %a) nounwind {
|
||||
; CHECK-LABEL: bar:
|
||||
; CHECK: R_RISCV_CALL
|
||||
; CHECK: R_RISCV_RELAX
|
||||
tail call void asm sideeffect ".option norelax", ""()
|
||||
%1 = call i32 @foo(i32 %a)
|
||||
ret i32 %1
|
||||
}
|
16
test/CodeGen/RISCV/option-relax.ll
Normal file
16
test/CodeGen/RISCV/option-relax.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; RUN: llc -mtriple=riscv32 -mattr=-relax -filetype=obj < %s \
|
||||
; RUN: | llvm-objdump -d -r - | FileCheck %s
|
||||
|
||||
; This test demonstrates that .option relax has no effect on codegen
|
||||
; when emitting an ELF directly.
|
||||
|
||||
declare i32 @foo(i32)
|
||||
|
||||
define i32 @bar(i32 %a) nounwind {
|
||||
; CHECK-LABEL: bar:
|
||||
; CHECK: R_RISCV_CALL
|
||||
; CHECK-NOT: R_RISCV_RELAX
|
||||
tail call void asm sideeffect ".option relax", ""()
|
||||
%1 = call i32 @foo(i32 %a)
|
||||
ret i32 %1
|
||||
}
|
@ -13,5 +13,5 @@
|
||||
# CHECK: error: unexpected token, expected end of statement
|
||||
.option rvc foo
|
||||
|
||||
# CHECK: warning: unknown option, expected 'rvc' or 'norvc'
|
||||
# CHECK: warning: unknown option, expected 'rvc', 'norvc', 'relax' or 'norelax'
|
||||
.option bar
|
||||
|
66
test/MC/RISCV/option-relax.s
Normal file
66
test/MC/RISCV/option-relax.s
Normal file
@ -0,0 +1,66 @@
|
||||
# RUN: llvm-mc -triple riscv32 < %s \
|
||||
# RUN: | FileCheck -check-prefix=CHECK-INST %s
|
||||
# RUN: llvm-mc -filetype=obj -triple riscv32 < %s \
|
||||
# RUN: | llvm-readobj -r | FileCheck -check-prefix=CHECK-RELOC %s
|
||||
|
||||
# RUN: llvm-mc -triple riscv64 < %s \
|
||||
# RUN: | FileCheck -check-prefix=CHECK-INST %s
|
||||
# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \
|
||||
# RUN: | llvm-readobj -r | FileCheck -check-prefix=CHECK-RELOC %s
|
||||
|
||||
# Check .option relax causes R_RISCV_RELAX to be emitted, and .option
|
||||
# norelax suppresses it. Also check that if .option relax was enabled
|
||||
# at any point and an instruction may have been relaxed, diff & branch
|
||||
# relocations are emitted to ensure correct codegen. See
|
||||
# linker-relaxation.s and fixups-expr.s for behaviour of the relax
|
||||
# attribute.
|
||||
|
||||
.L1:
|
||||
.option norelax
|
||||
# CHECK-INST: .option norelax
|
||||
|
||||
# CHECK-INST: call foo
|
||||
# CHECK-RELOC: R_RISCV_CALL foo 0x0
|
||||
# CHECK-RELOC-NOT: R_RISCV_RELAX foo 0x0
|
||||
call foo
|
||||
|
||||
# CHECK-RELOC-NEXT: R_RISCV_ADD64
|
||||
# CHECK-RELOC-NEXT: R_RISCV_SUB64
|
||||
.dword .L2-.L1
|
||||
# CHECK-RELOC-NEXT: R_RISCV_JAL
|
||||
jal zero, .L1
|
||||
# CHECK-RELOC-NEXT: R_RISCV_BRANCH
|
||||
beq s1, s1, .L1
|
||||
|
||||
.L2:
|
||||
.option relax
|
||||
# CHECK-INST: .option relax
|
||||
|
||||
# CHECK-INST: call bar
|
||||
# CHECK-RELOC-NEXT: R_RISCV_CALL bar 0x0
|
||||
# CHECK-RELOC-NEXT: R_RISCV_RELAX bar 0x0
|
||||
call bar
|
||||
|
||||
# CHECK-RELOC-NEXT: R_RISCV_ADD64
|
||||
# CHECK-RELOC-NEXT: R_RISCV_SUB64
|
||||
.dword .L2-.L1
|
||||
# CHECK-RELOC-NEXT: R_RISCV_JAL
|
||||
jal zero, .L1
|
||||
# CHECK-RELOC-NEXT: R_RISCV_BRANCH
|
||||
beq s1, s1, .L1
|
||||
|
||||
.option norelax
|
||||
# CHECK-INST: .option norelax
|
||||
|
||||
# CHECK-INST: call baz
|
||||
# CHECK-RELOC-NEXT: R_RISCV_CALL baz 0x0
|
||||
# CHECK-RELOC-NOT: R_RISCV_RELAX baz 0x0
|
||||
call baz
|
||||
|
||||
# CHECK-RELOC-NEXT: R_RISCV_ADD64
|
||||
# CHECK-RELOC-NEXT: R_RISCV_SUB64
|
||||
.dword .L2-.L1
|
||||
# CHECK-RELOC-NEXT: R_RISCV_JAL
|
||||
jal zero, .L1
|
||||
# CHECK-RELOC-NEXT: R_RISCV_BRANCH
|
||||
beq s1, s1, .L1
|
Loading…
x
Reference in New Issue
Block a user