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.
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::emitDirectiveOptionPIC() {}
70 void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
71 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
72 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
73 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
74 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
75 
76 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
77   setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
78 }
79 
80 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
81                                                StringRef String) {
82   setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
83 }
84 
85 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
86                                                   unsigned IntValue,
87                                                   StringRef StringValue) {
88   setAttributeItems(Attribute, IntValue, StringValue,
89                     /*OverwriteExisting=*/true);
90 }
91 
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 
147 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