1 //===-- RISCVELFStreamer.cpp - RISC-V ELF Target Streamer Methods ---------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file provides RISC-V specific target streamer methods.
11 //===----------------------------------------------------------------------===//
13 #include "RISCVELFStreamer.h"
14 #include "RISCVAsmBackend.h"
15 #include "RISCVBaseInfo.h"
16 #include "RISCVMCTargetDesc.h"
17 #include "llvm/BinaryFormat/ELF.h"
18 #include "llvm/MC/MCAsmBackend.h"
19 #include "llvm/MC/MCAssembler.h"
20 #include "llvm/MC/MCCodeEmitter.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCELFObjectWriter.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
27 // This part is for ELF object output.
28 RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer
&S
,
29 const MCSubtargetInfo
&STI
)
30 : RISCVTargetStreamer(S
), CurrentVendor("riscv") {
31 MCAssembler
&MCA
= getStreamer().getAssembler();
32 const FeatureBitset
&Features
= STI
.getFeatureBits();
33 auto &MAB
= static_cast<RISCVAsmBackend
&>(MCA
.getBackend());
34 setTargetABI(RISCVABI::computeTargetABI(STI
.getTargetTriple(), Features
,
35 MAB
.getTargetOptions().getABIName()));
36 setFlagsFromFeatures(STI
);
37 // `j label` in `.option norelax; j label; .option relax; ...; label:` needs a
38 // relocation to ensure the jump target is correct after linking. This is due
39 // to a limitation that shouldForceRelocation has to make the decision upfront
40 // without knowing a possibly future .option relax. When RISCVAsmParser is used,
41 // its ParseInstruction may call setForceRelocs as well.
42 if (STI
.hasFeature(RISCV::FeatureRelax
))
43 static_cast<RISCVAsmBackend
&>(MAB
).setForceRelocs();
46 RISCVELFStreamer
&RISCVTargetELFStreamer::getStreamer() {
47 return static_cast<RISCVELFStreamer
&>(Streamer
);
50 void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
51 void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
52 void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
53 void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
54 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
55 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
56 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
57 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
59 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute
, unsigned Value
) {
60 getStreamer().setAttributeItem(Attribute
, Value
, /*OverwriteExisting=*/true);
63 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute
,
65 getStreamer().setAttributeItem(Attribute
, String
, /*OverwriteExisting=*/true);
68 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute
,
70 StringRef StringValue
) {
71 getStreamer().setAttributeItems(Attribute
, IntValue
, StringValue
,
72 /*OverwriteExisting=*/true);
75 void RISCVTargetELFStreamer::finishAttributeSection() {
76 RISCVELFStreamer
&S
= getStreamer();
77 if (S
.Contents
.empty())
80 S
.emitAttributesSection(CurrentVendor
, ".riscv.attributes",
81 ELF::SHT_RISCV_ATTRIBUTES
, AttributeSection
);
84 void RISCVTargetELFStreamer::finish() {
85 RISCVTargetStreamer::finish();
86 ELFObjectWriter
&W
= getStreamer().getWriter();
87 RISCVABI::ABI ABI
= getTargetABI();
89 unsigned EFlags
= W
.getELFHeaderEFlags();
92 EFlags
|= ELF::EF_RISCV_RVC
;
94 EFlags
|= ELF::EF_RISCV_TSO
;
97 case RISCVABI::ABI_ILP32
:
98 case RISCVABI::ABI_LP64
:
100 case RISCVABI::ABI_ILP32F
:
101 case RISCVABI::ABI_LP64F
:
102 EFlags
|= ELF::EF_RISCV_FLOAT_ABI_SINGLE
;
104 case RISCVABI::ABI_ILP32D
:
105 case RISCVABI::ABI_LP64D
:
106 EFlags
|= ELF::EF_RISCV_FLOAT_ABI_DOUBLE
;
108 case RISCVABI::ABI_ILP32E
:
109 case RISCVABI::ABI_LP64E
:
110 EFlags
|= ELF::EF_RISCV_RVE
;
112 case RISCVABI::ABI_Unknown
:
113 llvm_unreachable("Improperly initialised target ABI");
116 W
.setELFHeaderEFlags(EFlags
);
119 void RISCVTargetELFStreamer::reset() {
120 AttributeSection
= nullptr;
123 void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol
&Symbol
) {
124 getStreamer().getAssembler().registerSymbol(Symbol
);
125 cast
<MCSymbolELF
>(Symbol
).setOther(ELF::STO_RISCV_VARIANT_CC
);
128 void RISCVELFStreamer::reset() {
129 static_cast<RISCVTargetStreamer
*>(getTargetStreamer())->reset();
130 MCELFStreamer::reset();
131 LastMappingSymbols
.clear();
135 void RISCVELFStreamer::emitDataMappingSymbol() {
136 if (LastEMS
== EMS_Data
)
138 emitMappingSymbol("$d");
142 void RISCVELFStreamer::emitInstructionsMappingSymbol() {
143 if (LastEMS
== EMS_Instructions
)
145 emitMappingSymbol("$x");
146 LastEMS
= EMS_Instructions
;
149 void RISCVELFStreamer::emitMappingSymbol(StringRef Name
) {
150 auto *Symbol
= cast
<MCSymbolELF
>(getContext().createLocalSymbol(Name
));
152 Symbol
->setType(ELF::STT_NOTYPE
);
153 Symbol
->setBinding(ELF::STB_LOCAL
);
156 void RISCVELFStreamer::changeSection(MCSection
*Section
, uint32_t Subsection
) {
157 // We have to keep track of the mapping symbol state of any sections we
158 // use. Each one should start off as EMS_None, which is provided as the
159 // default constructor by DenseMap::lookup.
160 LastMappingSymbols
[getPreviousSection().first
] = LastEMS
;
161 LastEMS
= LastMappingSymbols
.lookup(Section
);
163 MCELFStreamer::changeSection(Section
, Subsection
);
166 void RISCVELFStreamer::emitInstruction(const MCInst
&Inst
,
167 const MCSubtargetInfo
&STI
) {
168 emitInstructionsMappingSymbol();
169 MCELFStreamer::emitInstruction(Inst
, STI
);
172 void RISCVELFStreamer::emitBytes(StringRef Data
) {
173 emitDataMappingSymbol();
174 MCELFStreamer::emitBytes(Data
);
177 void RISCVELFStreamer::emitFill(const MCExpr
&NumBytes
, uint64_t FillValue
,
179 emitDataMappingSymbol();
180 MCELFStreamer::emitFill(NumBytes
, FillValue
, Loc
);
183 void RISCVELFStreamer::emitValueImpl(const MCExpr
*Value
, unsigned Size
,
185 emitDataMappingSymbol();
186 MCELFStreamer::emitValueImpl(Value
, Size
, Loc
);
190 MCELFStreamer
*createRISCVELFStreamer(MCContext
&C
,
191 std::unique_ptr
<MCAsmBackend
> MAB
,
192 std::unique_ptr
<MCObjectWriter
> MOW
,
193 std::unique_ptr
<MCCodeEmitter
> MCE
) {
194 RISCVELFStreamer
*S
=
195 new RISCVELFStreamer(C
, std::move(MAB
), std::move(MOW
), std::move(MCE
));