1 //===-- RISCVELFStreamer.cpp - RISCV ELF Target Streamer Methods ----------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file provides RISCV specific target streamer methods.
10 //
11 //===----------------------------------------------------------------------===//
12
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/MCContext.h"
19 #include "llvm/MC/MCSectionELF.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/Support/LEB128.h"
22 #include "llvm/Support/RISCVAttributes.h"
23
24 using namespace llvm;
25
26 // This part is for ELF object output.
RISCVTargetELFStreamer(MCStreamer & S,const MCSubtargetInfo & STI)27 RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
28 const MCSubtargetInfo &STI)
29 : RISCVTargetStreamer(S), CurrentVendor("riscv") {
30 MCAssembler &MCA = getStreamer().getAssembler();
31 const FeatureBitset &Features = STI.getFeatureBits();
32 auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
33 RISCVABI::ABI ABI = MAB.getTargetABI();
34 assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");
35
36 unsigned EFlags = MCA.getELFHeaderEFlags();
37
38 if (Features[RISCV::FeatureStdExtC])
39 EFlags |= ELF::EF_RISCV_RVC;
40
41 switch (ABI) {
42 case RISCVABI::ABI_ILP32:
43 case RISCVABI::ABI_LP64:
44 break;
45 case RISCVABI::ABI_ILP32F:
46 case RISCVABI::ABI_LP64F:
47 EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
48 break;
49 case RISCVABI::ABI_ILP32D:
50 case RISCVABI::ABI_LP64D:
51 EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
52 break;
53 case RISCVABI::ABI_ILP32E:
54 EFlags |= ELF::EF_RISCV_RVE;
55 break;
56 case RISCVABI::ABI_Unknown:
57 llvm_unreachable("Improperly initialised target ABI");
58 }
59
60 MCA.setELFHeaderEFlags(EFlags);
61 }
62
getStreamer()63 MCELFStreamer &RISCVTargetELFStreamer::getStreamer() {
64 return static_cast<MCELFStreamer &>(Streamer);
65 }
66
emitDirectiveOptionPush()67 void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
emitDirectiveOptionPop()68 void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
emitDirectiveOptionPIC()69 void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
emitDirectiveOptionNoPIC()70 void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
emitDirectiveOptionRVC()71 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
emitDirectiveOptionNoRVC()72 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
emitDirectiveOptionRelax()73 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
emitDirectiveOptionNoRelax()74 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
75
emitAttribute(unsigned Attribute,unsigned Value)76 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
77 setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
78 }
79
emitTextAttribute(unsigned Attribute,StringRef String)80 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
81 StringRef String) {
82 setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
83 }
84
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)85 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
86 unsigned IntValue,
87 StringRef StringValue) {
88 setAttributeItems(Attribute, IntValue, StringValue,
89 /*OverwriteExisting=*/true);
90 }
91
finishAttributeSection()92 void RISCVTargetELFStreamer::finishAttributeSection() {
93 if (Contents.empty())
94 return;
95
96 if (AttributeSection) {
97 Streamer.SwitchSection(AttributeSection);
98 } else {
99 MCAssembler &MCA = getStreamer().getAssembler();
100 AttributeSection = MCA.getContext().getELFSection(
101 ".riscv.attributes", ELF::SHT_RISCV_ATTRIBUTES, 0);
102 Streamer.SwitchSection(AttributeSection);
103
104 Streamer.emitInt8(ELFAttrs::Format_Version);
105 }
106
107 // Vendor size + Vendor name + '\0'
108 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
109
110 // Tag + Tag Size
111 const size_t TagHeaderSize = 1 + 4;
112
113 const size_t ContentsSize = calculateContentSize();
114
115 Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
116 Streamer.emitBytes(CurrentVendor);
117 Streamer.emitInt8(0); // '\0'
118
119 Streamer.emitInt8(ELFAttrs::File);
120 Streamer.emitInt32(TagHeaderSize + ContentsSize);
121
122 // Size should have been accounted for already, now
123 // emit each field as its type (ULEB or String).
124 for (AttributeItem item : Contents) {
125 Streamer.emitULEB128IntValue(item.Tag);
126 switch (item.Type) {
127 default:
128 llvm_unreachable("Invalid attribute type");
129 case AttributeType::Numeric:
130 Streamer.emitULEB128IntValue(item.IntValue);
131 break;
132 case AttributeType::Text:
133 Streamer.emitBytes(item.StringValue);
134 Streamer.emitInt8(0); // '\0'
135 break;
136 case AttributeType::NumericAndText:
137 Streamer.emitULEB128IntValue(item.IntValue);
138 Streamer.emitBytes(item.StringValue);
139 Streamer.emitInt8(0); // '\0'
140 break;
141 }
142 }
143
144 Contents.clear();
145 }
146
calculateContentSize() const147 size_t RISCVTargetELFStreamer::calculateContentSize() const {
148 size_t Result = 0;
149 for (AttributeItem item : Contents) {
150 switch (item.Type) {
151 case AttributeType::Hidden:
152 break;
153 case AttributeType::Numeric:
154 Result += getULEB128Size(item.Tag);
155 Result += getULEB128Size(item.IntValue);
156 break;
157 case AttributeType::Text:
158 Result += getULEB128Size(item.Tag);
159 Result += item.StringValue.size() + 1; // string + '\0'
160 break;
161 case AttributeType::NumericAndText:
162 Result += getULEB128Size(item.Tag);
163 Result += getULEB128Size(item.IntValue);
164 Result += item.StringValue.size() + 1; // string + '\0';
165 break;
166 }
167 }
168 return Result;
169 }
170