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 "MCTargetDesc/RISCVAsmBackend.h"
15 #include "RISCVMCTargetDesc.h"
16 #include "Utils/RISCVBaseInfo.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.
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 
63 MCELFStreamer &RISCVTargetELFStreamer::getStreamer() {
64   return static_cast<MCELFStreamer &>(Streamer);
65 }
66 
67 void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
68 void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
69 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
70 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
71 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
72 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
73 
74 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
75   setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
76 }
77 
78 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
79                                                StringRef String) {
80   setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
81 }
82 
83 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
84                                                   unsigned IntValue,
85                                                   StringRef StringValue) {
86   setAttributeItems(Attribute, IntValue, StringValue,
87                     /*OverwriteExisting=*/true);
88 }
89 
90 void RISCVTargetELFStreamer::finishAttributeSection() {
91   if (Contents.empty())
92     return;
93 
94   if (AttributeSection) {
95     Streamer.SwitchSection(AttributeSection);
96   } else {
97     MCAssembler &MCA = getStreamer().getAssembler();
98     AttributeSection = MCA.getContext().getELFSection(
99         ".riscv.attributes", ELF::SHT_RISCV_ATTRIBUTES, 0);
100     Streamer.SwitchSection(AttributeSection);
101 
102     Streamer.emitInt8(ELFAttrs::Format_Version);
103   }
104 
105   // Vendor size + Vendor name + '\0'
106   const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
107 
108   // Tag + Tag Size
109   const size_t TagHeaderSize = 1 + 4;
110 
111   const size_t ContentsSize = calculateContentSize();
112 
113   Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
114   Streamer.emitBytes(CurrentVendor);
115   Streamer.emitInt8(0); // '\0'
116 
117   Streamer.emitInt8(ELFAttrs::File);
118   Streamer.emitInt32(TagHeaderSize + ContentsSize);
119 
120   // Size should have been accounted for already, now
121   // emit each field as its type (ULEB or String).
122   for (AttributeItem item : Contents) {
123     Streamer.emitULEB128IntValue(item.Tag);
124     switch (item.Type) {
125     default:
126       llvm_unreachable("Invalid attribute type");
127     case AttributeType::Numeric:
128       Streamer.emitULEB128IntValue(item.IntValue);
129       break;
130     case AttributeType::Text:
131       Streamer.emitBytes(item.StringValue);
132       Streamer.emitInt8(0); // '\0'
133       break;
134     case AttributeType::NumericAndText:
135       Streamer.emitULEB128IntValue(item.IntValue);
136       Streamer.emitBytes(item.StringValue);
137       Streamer.emitInt8(0); // '\0'
138       break;
139     }
140   }
141 
142   Contents.clear();
143 }
144 
145 size_t RISCVTargetELFStreamer::calculateContentSize() const {
146   size_t Result = 0;
147   for (AttributeItem item : Contents) {
148     switch (item.Type) {
149     case AttributeType::Hidden:
150       break;
151     case AttributeType::Numeric:
152       Result += getULEB128Size(item.Tag);
153       Result += getULEB128Size(item.IntValue);
154       break;
155     case AttributeType::Text:
156       Result += getULEB128Size(item.Tag);
157       Result += item.StringValue.size() + 1; // string + '\0'
158       break;
159     case AttributeType::NumericAndText:
160       Result += getULEB128Size(item.Tag);
161       Result += getULEB128Size(item.IntValue);
162       Result += item.StringValue.size() + 1; // string + '\0';
163       break;
164     }
165   }
166   return Result;
167 }
168