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