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::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