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/MCAsmBackend.h" 19 #include "llvm/MC/MCCodeEmitter.h" 20 #include "llvm/MC/MCContext.h" 21 #include "llvm/MC/MCObjectWriter.h" 22 #include "llvm/MC/MCSectionELF.h" 23 #include "llvm/MC/MCSubtargetInfo.h" 24 #include "llvm/MC/MCValue.h" 25 #include "llvm/Support/LEB128.h" 26 #include "llvm/Support/RISCVAttributes.h" 27 28 using namespace llvm; 29 30 // This part is for ELF object output. 31 RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S, 32 const MCSubtargetInfo &STI) 33 : RISCVTargetStreamer(S), CurrentVendor("riscv") { 34 MCAssembler &MCA = getStreamer().getAssembler(); 35 const FeatureBitset &Features = STI.getFeatureBits(); 36 auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend()); 37 RISCVABI::ABI ABI = MAB.getTargetABI(); 38 assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI"); 39 40 unsigned EFlags = MCA.getELFHeaderEFlags(); 41 42 if (Features[RISCV::FeatureStdExtC]) 43 EFlags |= ELF::EF_RISCV_RVC; 44 45 switch (ABI) { 46 case RISCVABI::ABI_ILP32: 47 case RISCVABI::ABI_LP64: 48 break; 49 case RISCVABI::ABI_ILP32F: 50 case RISCVABI::ABI_LP64F: 51 EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE; 52 break; 53 case RISCVABI::ABI_ILP32D: 54 case RISCVABI::ABI_LP64D: 55 EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE; 56 break; 57 case RISCVABI::ABI_ILP32E: 58 EFlags |= ELF::EF_RISCV_RVE; 59 break; 60 case RISCVABI::ABI_Unknown: 61 llvm_unreachable("Improperly initialised target ABI"); 62 } 63 64 MCA.setELFHeaderEFlags(EFlags); 65 } 66 67 MCELFStreamer &RISCVTargetELFStreamer::getStreamer() { 68 return static_cast<MCELFStreamer &>(Streamer); 69 } 70 71 void RISCVTargetELFStreamer::emitDirectiveOptionPush() {} 72 void RISCVTargetELFStreamer::emitDirectiveOptionPop() {} 73 void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {} 74 void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {} 75 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {} 76 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {} 77 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {} 78 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {} 79 80 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { 81 setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true); 82 } 83 84 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute, 85 StringRef String) { 86 setAttributeItem(Attribute, String, /*OverwriteExisting=*/true); 87 } 88 89 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, 90 unsigned IntValue, 91 StringRef StringValue) { 92 setAttributeItems(Attribute, IntValue, StringValue, 93 /*OverwriteExisting=*/true); 94 } 95 96 void RISCVTargetELFStreamer::finishAttributeSection() { 97 if (Contents.empty()) 98 return; 99 100 if (AttributeSection) { 101 Streamer.SwitchSection(AttributeSection); 102 } else { 103 MCAssembler &MCA = getStreamer().getAssembler(); 104 AttributeSection = MCA.getContext().getELFSection( 105 ".riscv.attributes", ELF::SHT_RISCV_ATTRIBUTES, 0); 106 Streamer.SwitchSection(AttributeSection); 107 108 Streamer.emitInt8(ELFAttrs::Format_Version); 109 } 110 111 // Vendor size + Vendor name + '\0' 112 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1; 113 114 // Tag + Tag Size 115 const size_t TagHeaderSize = 1 + 4; 116 117 const size_t ContentsSize = calculateContentSize(); 118 119 Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize); 120 Streamer.emitBytes(CurrentVendor); 121 Streamer.emitInt8(0); // '\0' 122 123 Streamer.emitInt8(ELFAttrs::File); 124 Streamer.emitInt32(TagHeaderSize + ContentsSize); 125 126 // Size should have been accounted for already, now 127 // emit each field as its type (ULEB or String). 128 for (AttributeItem item : Contents) { 129 Streamer.emitULEB128IntValue(item.Tag); 130 switch (item.Type) { 131 default: 132 llvm_unreachable("Invalid attribute type"); 133 case AttributeType::Numeric: 134 Streamer.emitULEB128IntValue(item.IntValue); 135 break; 136 case AttributeType::Text: 137 Streamer.emitBytes(item.StringValue); 138 Streamer.emitInt8(0); // '\0' 139 break; 140 case AttributeType::NumericAndText: 141 Streamer.emitULEB128IntValue(item.IntValue); 142 Streamer.emitBytes(item.StringValue); 143 Streamer.emitInt8(0); // '\0' 144 break; 145 } 146 } 147 148 Contents.clear(); 149 } 150 151 size_t RISCVTargetELFStreamer::calculateContentSize() const { 152 size_t Result = 0; 153 for (AttributeItem item : Contents) { 154 switch (item.Type) { 155 case AttributeType::Hidden: 156 break; 157 case AttributeType::Numeric: 158 Result += getULEB128Size(item.Tag); 159 Result += getULEB128Size(item.IntValue); 160 break; 161 case AttributeType::Text: 162 Result += getULEB128Size(item.Tag); 163 Result += item.StringValue.size() + 1; // string + '\0' 164 break; 165 case AttributeType::NumericAndText: 166 Result += getULEB128Size(item.Tag); 167 Result += getULEB128Size(item.IntValue); 168 Result += item.StringValue.size() + 1; // string + '\0'; 169 break; 170 } 171 } 172 return Result; 173 } 174 175 namespace { 176 class RISCVELFStreamer : public MCELFStreamer { 177 static std::pair<unsigned, unsigned> getRelocPairForSize(unsigned Size) { 178 switch (Size) { 179 default: 180 llvm_unreachable("unsupported fixup size"); 181 case 1: 182 return std::make_pair(RISCV::fixup_riscv_add_8, RISCV::fixup_riscv_sub_8); 183 case 2: 184 return std::make_pair(RISCV::fixup_riscv_add_16, 185 RISCV::fixup_riscv_sub_16); 186 case 4: 187 return std::make_pair(RISCV::fixup_riscv_add_32, 188 RISCV::fixup_riscv_sub_32); 189 case 8: 190 return std::make_pair(RISCV::fixup_riscv_add_64, 191 RISCV::fixup_riscv_sub_64); 192 } 193 } 194 195 static bool requiresFixups(MCContext &C, const MCExpr *Value, 196 const MCExpr *&LHS, const MCExpr *&RHS) { 197 const auto *MBE = dyn_cast<MCBinaryExpr>(Value); 198 if (MBE == nullptr) 199 return false; 200 201 MCValue E; 202 if (!Value->evaluateAsRelocatable(E, nullptr, nullptr)) 203 return false; 204 if (E.getSymA() == nullptr || E.getSymB() == nullptr) 205 return false; 206 207 const auto &A = E.getSymA()->getSymbol(); 208 const auto &B = E.getSymB()->getSymbol(); 209 210 LHS = 211 MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C), 212 MCConstantExpr::create(E.getConstant(), C), C); 213 RHS = E.getSymB(); 214 215 return (A.isInSection() ? A.getSection().hasInstructions() 216 : !A.getName().empty()) || 217 (B.isInSection() ? B.getSection().hasInstructions() 218 : !B.getName().empty()); 219 } 220 221 public: 222 RISCVELFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> MAB, 223 std::unique_ptr<MCObjectWriter> MOW, 224 std::unique_ptr<MCCodeEmitter> MCE) 225 : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {} 226 227 void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override { 228 const MCExpr *A, *B; 229 if (!requiresFixups(getContext(), Value, A, B)) 230 return MCELFStreamer::emitValueImpl(Value, Size, Loc); 231 232 MCStreamer::emitValueImpl(Value, Size, Loc); 233 234 MCDataFragment *DF = getOrCreateDataFragment(); 235 flushPendingLabels(DF, DF->getContents().size()); 236 MCDwarfLineEntry::make(this, getCurrentSectionOnly()); 237 238 unsigned Add, Sub; 239 std::tie(Add, Sub) = getRelocPairForSize(Size); 240 241 DF->getFixups().push_back(MCFixup::create( 242 DF->getContents().size(), A, static_cast<MCFixupKind>(Add), Loc)); 243 DF->getFixups().push_back(MCFixup::create( 244 DF->getContents().size(), B, static_cast<MCFixupKind>(Sub), Loc)); 245 246 DF->getContents().resize(DF->getContents().size() + Size, 0); 247 } 248 }; 249 } // namespace 250 251 namespace llvm { 252 MCELFStreamer *createRISCVELFStreamer(MCContext &C, 253 std::unique_ptr<MCAsmBackend> MAB, 254 std::unique_ptr<MCObjectWriter> MOW, 255 std::unique_ptr<MCCodeEmitter> MCE, 256 bool RelaxAll) { 257 RISCVELFStreamer *S = 258 new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)); 259 S->getAssembler().setRelaxAll(RelaxAll); 260 return S; 261 } 262 } // namespace llvm 263