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