mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[RISCV] Support .option rvc and norvc assembler directives
These directives allow the 'C' (compressed) extension to be enabled/disabled within a single file. Differential Revision: https://reviews.llvm.org/D45864 Patch by Kito Cheng llvm-svn: 332107
This commit is contained in:
parent
f736dbd653
commit
ac7024c937
@ -10,6 +10,7 @@
|
||||
#include "MCTargetDesc/RISCVBaseInfo.h"
|
||||
#include "MCTargetDesc/RISCVMCExpr.h"
|
||||
#include "MCTargetDesc/RISCVMCTargetDesc.h"
|
||||
#include "MCTargetDesc/RISCVTargetStreamer.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
@ -37,6 +38,11 @@ class RISCVAsmParser : public MCTargetAsmParser {
|
||||
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
|
||||
bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
|
||||
|
||||
RISCVTargetStreamer &getTargetStreamer() {
|
||||
MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
|
||||
return static_cast<RISCVTargetStreamer &>(TS);
|
||||
}
|
||||
|
||||
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
|
||||
unsigned Kind) override;
|
||||
|
||||
@ -67,6 +73,23 @@ class RISCVAsmParser : public MCTargetAsmParser {
|
||||
|
||||
bool parseOperand(OperandVector &Operands, bool ForceImmediate);
|
||||
|
||||
bool parseDirectiveOption();
|
||||
|
||||
void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
|
||||
if (!(getSTI().getFeatureBits()[Feature])) {
|
||||
MCSubtargetInfo &STI = copySTI();
|
||||
setAvailableFeatures(
|
||||
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
|
||||
}
|
||||
}
|
||||
|
||||
void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
|
||||
if (getSTI().getFeatureBits()[Feature]) {
|
||||
MCSubtargetInfo &STI = copySTI();
|
||||
setAvailableFeatures(
|
||||
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
|
||||
}
|
||||
}
|
||||
public:
|
||||
enum RISCVMatchResultTy {
|
||||
Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
|
||||
@ -984,7 +1007,60 @@ bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
|
||||
return Kind != RISCVMCExpr::VK_RISCV_Invalid;
|
||||
}
|
||||
|
||||
bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
|
||||
bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
// This returns false if this function recognizes the directive
|
||||
// regardless of whether it is successfully handles or reports an
|
||||
// error. Otherwise it returns true to give the generic parser a
|
||||
// chance at recognizing it.
|
||||
StringRef IDVal = DirectiveID.getString();
|
||||
|
||||
if (IDVal == ".option")
|
||||
return parseDirectiveOption();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RISCVAsmParser::parseDirectiveOption() {
|
||||
MCAsmParser &Parser = getParser();
|
||||
// Get the option token.
|
||||
AsmToken Tok = Parser.getTok();
|
||||
// At the moment only identifiers are supported.
|
||||
if (Tok.isNot(AsmToken::Identifier))
|
||||
return Error(Parser.getTok().getLoc(),
|
||||
"unexpected token, expected identifier");
|
||||
|
||||
StringRef Option = Tok.getIdentifier();
|
||||
|
||||
if (Option == "rvc") {
|
||||
getTargetStreamer().emitDirectiveOptionRVC();
|
||||
|
||||
Parser.Lex();
|
||||
if (Parser.getTok().isNot(AsmToken::EndOfStatement))
|
||||
return Error(Parser.getTok().getLoc(),
|
||||
"unexpected token, expected end of statement");
|
||||
|
||||
setFeatureBits(RISCV::FeatureStdExtC, "c");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Option == "norvc") {
|
||||
getTargetStreamer().emitDirectiveOptionNoRVC();
|
||||
|
||||
Parser.Lex();
|
||||
if (Parser.getTok().isNot(AsmToken::EndOfStatement))
|
||||
return Error(Parser.getTok().getLoc(),
|
||||
"unexpected token, expected end of statement");
|
||||
|
||||
clearFeatureBits(RISCV::FeatureStdExtC, "c");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unknown option.
|
||||
Warning(Parser.getTok().getLoc(),
|
||||
"unknown option, expected 'rvc' or 'norvc'");
|
||||
Parser.eatToEndOfStatement();
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeRISCVAsmParser() {
|
||||
RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
|
||||
|
@ -37,3 +37,6 @@ RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
|
||||
MCELFStreamer &RISCVTargetELFStreamer::getStreamer() {
|
||||
return static_cast<MCELFStreamer &>(Streamer);
|
||||
}
|
||||
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
|
||||
void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
|
||||
|
@ -19,6 +19,9 @@ class RISCVTargetELFStreamer : public RISCVTargetStreamer {
|
||||
public:
|
||||
MCELFStreamer &getStreamer();
|
||||
RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
|
||||
|
||||
virtual void emitDirectiveOptionRVC();
|
||||
virtual void emitDirectiveOptionNoRVC();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -74,7 +74,14 @@ createRISCVObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
|
||||
const Triple &TT = STI.getTargetTriple();
|
||||
if (TT.isOSBinFormatELF())
|
||||
return new RISCVTargetELFStreamer(S, STI);
|
||||
return new RISCVTargetStreamer(S);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static MCTargetStreamer *createRISCVAsmTargetStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS,
|
||||
MCInstPrinter *InstPrint,
|
||||
bool isVerboseAsm) {
|
||||
return new RISCVTargetAsmStreamer(S, OS);
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeRISCVTargetMC() {
|
||||
@ -88,5 +95,8 @@ extern "C" void LLVMInitializeRISCVTargetMC() {
|
||||
TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo);
|
||||
TargetRegistry::RegisterObjectTargetStreamer(
|
||||
*T, createRISCVObjectTargetStreamer);
|
||||
|
||||
// Register the asm target streamer.
|
||||
TargetRegistry::RegisterAsmTargetStreamer(*T, createRISCVAsmTargetStreamer);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,21 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RISCVTargetStreamer.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
RISCVTargetStreamer::RISCVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
|
||||
|
||||
// This part is for ascii assembly output
|
||||
RISCVTargetAsmStreamer::RISCVTargetAsmStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS)
|
||||
: RISCVTargetStreamer(S), OS(OS) {}
|
||||
|
||||
void RISCVTargetAsmStreamer::emitDirectiveOptionRVC() {
|
||||
OS << "\t.option\trvc\n";
|
||||
}
|
||||
|
||||
void RISCVTargetAsmStreamer::emitDirectiveOptionNoRVC() {
|
||||
OS << "\t.option\tnorvc\n";
|
||||
}
|
||||
|
@ -17,6 +17,21 @@ namespace llvm {
|
||||
class RISCVTargetStreamer : public MCTargetStreamer {
|
||||
public:
|
||||
RISCVTargetStreamer(MCStreamer &S);
|
||||
|
||||
virtual void emitDirectiveOptionRVC() = 0;
|
||||
virtual void emitDirectiveOptionNoRVC() = 0;
|
||||
};
|
||||
|
||||
// This part is for ascii assembly output
|
||||
class RISCVTargetAsmStreamer : public RISCVTargetStreamer {
|
||||
formatted_raw_ostream &OS;
|
||||
|
||||
public:
|
||||
RISCVTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
|
||||
|
||||
void emitDirectiveOptionRVC() override;
|
||||
void emitDirectiveOptionNoRVC() override;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
15
test/CodeGen/RISCV/option-norvc.ll
Normal file
15
test/CodeGen/RISCV/option-norvc.ll
Normal file
@ -0,0 +1,15 @@
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+c -filetype=obj < %s\
|
||||
; RUN: | llvm-objdump -triple=riscv32 -mattr=+c -d -riscv-no-aliases -\
|
||||
; RUN: | FileCheck -check-prefix=CHECK %s
|
||||
|
||||
; This test demonstrates that .option norvc has no effect on codegen when
|
||||
; emitting an ELF directly.
|
||||
|
||||
define i32 @add(i32 %a, i32 %b) nounwind {
|
||||
; CHECK-LABEL: add:
|
||||
; CHECK: c.add a0, a1
|
||||
; CHECK-NEXT: c.jr ra
|
||||
tail call void asm sideeffect ".option norvc", ""()
|
||||
%add = add nsw i32 %b, %a
|
||||
ret i32 %add
|
||||
}
|
15
test/CodeGen/RISCV/option-rvc.ll
Normal file
15
test/CodeGen/RISCV/option-rvc.ll
Normal file
@ -0,0 +1,15 @@
|
||||
; RUN: llc -mtriple=riscv32 -filetype=obj < %s\
|
||||
; RUN: | llvm-objdump -triple=riscv32 -mattr=+c -d -riscv-no-aliases -\
|
||||
; RUN: | FileCheck -check-prefix=CHECK %s
|
||||
|
||||
; This test demonstrates that .option norvc has no effect on codegen when
|
||||
; emitting an ELF directly.
|
||||
|
||||
define i32 @add(i32 %a, i32 %b) nounwind {
|
||||
; CHECK-LABEL: add:
|
||||
; CHECK: add a0, a1, a0
|
||||
; CHECK-NEXT: jalr zero, ra, 0
|
||||
tail call void asm sideeffect ".option rvc", ""()
|
||||
%add = add nsw i32 %b, %a
|
||||
ret i32 %add
|
||||
}
|
17
test/MC/RISCV/option-invalid.s
Normal file
17
test/MC/RISCV/option-invalid.s
Normal file
@ -0,0 +1,17 @@
|
||||
# RUN: not llvm-mc -triple riscv32 < %s 2>&1 \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK %s
|
||||
|
||||
# CHECK: error: unexpected token, expected identifier
|
||||
.option
|
||||
|
||||
# CHECK: error: unexpected token, expected identifier
|
||||
.option 123
|
||||
|
||||
# CHECK: error: unexpected token, expected identifier
|
||||
.option "str"
|
||||
|
||||
# CHECK: error: unexpected token, expected end of statement
|
||||
.option rvc foo
|
||||
|
||||
# CHECK: warning: unknown option, expected 'rvc' or 'norvc'
|
||||
.option bar
|
90
test/MC/RISCV/option-rvc.s
Normal file
90
test/MC/RISCV/option-rvc.s
Normal file
@ -0,0 +1,90 @@
|
||||
# RUN: llvm-mc -triple riscv32 -show-encoding < %s \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-ALIAS %s
|
||||
# RUN: llvm-mc -triple riscv32 -show-encoding \
|
||||
# RUN: -riscv-no-aliases <%s | FileCheck -check-prefixes=CHECK,CHECK-INST %s
|
||||
# RUN: llvm-mc -triple riscv32 -filetype=obj < %s \
|
||||
# RUN: | llvm-objdump -triple riscv32 -mattr=+c -d - \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-ALIAS %s
|
||||
# RUN: llvm-mc -triple riscv32 -filetype=obj < %s \
|
||||
# RUN: | llvm-objdump -triple riscv32 -mattr=+c -d -riscv-no-aliases - \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-INST %s
|
||||
|
||||
# RUN: llvm-mc -triple riscv64 -show-encoding < %s \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-ALIAS %s
|
||||
# RUN: llvm-mc -triple riscv64 -show-encoding \
|
||||
# RUN: -riscv-no-aliases <%s | FileCheck -check-prefixes=CHECK-INST %s
|
||||
# RUN: llvm-mc -triple riscv64 -filetype=obj < %s \
|
||||
# RUN: | llvm-objdump -triple riscv64 -mattr=+c -d - \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-ALIAS %s
|
||||
# RUN: llvm-mc -triple riscv64 -filetype=obj < %s \
|
||||
# RUN: | llvm-objdump -triple riscv64 -mattr=+c -d -riscv-no-aliases - \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-INST %s
|
||||
|
||||
# CHECK-BYTES: 13 85 05 00
|
||||
# CHECK-ALIAS: mv a0, a1
|
||||
# CHECK-INST: addi a0, a1, 0
|
||||
# CHECK: # encoding: [0x13,0x85,0x05,0x00]
|
||||
addi a0, a1, 0
|
||||
|
||||
# CHECK-BYTES: 13 04 c1 3f
|
||||
# CHECK-ALIAS: addi s0, sp, 1020
|
||||
# CHECK-INST: addi s0, sp, 1020
|
||||
# CHECK: # encoding: [0x13,0x04,0xc1,0x3f]
|
||||
addi s0, sp, 1020
|
||||
|
||||
|
||||
# CHECK: .option rvc
|
||||
.option rvc
|
||||
# CHECK-BYTES: 2e 85
|
||||
# CHECK-ALIAS: add a0, zero, a1
|
||||
# CHECK-INST: c.mv a0, a1
|
||||
# CHECK: # encoding: [0x2e,0x85]
|
||||
addi a0, a1, 0
|
||||
|
||||
# CHECK-BYTES: e0 1f
|
||||
# CHECK-ALIAS: addi s0, sp, 1020
|
||||
# CHECK-INST: c.addi4spn s0, sp, 1020
|
||||
# CHECK: # encoding: [0xe0,0x1f]
|
||||
addi s0, sp, 1020
|
||||
|
||||
# CHECK: .option norvc
|
||||
.option norvc
|
||||
# CHECK-BYTES: 13 85 05 00
|
||||
# CHECK-ALIAS: mv a0, a1
|
||||
# CHECK-INST: addi a0, a1, 0
|
||||
# CHECK: # encoding: [0x13,0x85,0x05,0x00]
|
||||
addi a0, a1, 0
|
||||
|
||||
# CHECK-BYTES: 13 04 c1 3f
|
||||
# CHECK-ALIAS: addi s0, sp, 1020
|
||||
# CHECK-INST: addi s0, sp, 1020
|
||||
# CHECK: # encoding: [0x13,0x04,0xc1,0x3f]
|
||||
addi s0, sp, 1020
|
||||
|
||||
# CHECK: .option rvc
|
||||
.option rvc
|
||||
# CHECK-BYTES: 2e 85
|
||||
# CHECK-ALIAS: add a0, zero, a1
|
||||
# CHECK-INST: c.mv a0, a1
|
||||
# CHECK: # encoding: [0x2e,0x85]
|
||||
addi a0, a1, 0
|
||||
|
||||
# CHECK-BYTES: e0 1f
|
||||
# CHECK-ALIAS: addi s0, sp, 1020
|
||||
# CHECK-INST: c.addi4spn s0, sp, 1020
|
||||
# CHECK: # encoding: [0xe0,0x1f]
|
||||
addi s0, sp, 1020
|
||||
|
||||
# CHECK: .option norvc
|
||||
.option norvc
|
||||
# CHECK-BYTES: 13 85 05 00
|
||||
# CHECK-ALIAS: mv a0, a1
|
||||
# CHECK-INST: addi a0, a1, 0
|
||||
# CHECK: # encoding: [0x13,0x85,0x05,0x00]
|
||||
addi a0, a1, 0
|
||||
|
||||
# CHECK-BYTES: 13 04 c1 3f
|
||||
# CHECK-ALIAS: addi s0, sp, 1020
|
||||
# CHECK-INST: addi s0, sp, 1020
|
||||
# CHECK: # encoding: [0x13,0x04,0xc1,0x3f]
|
||||
addi s0, sp, 1020
|
Loading…
Reference in New Issue
Block a user