| //===-- CSKYELFStreamer.cpp - CSKY ELF Target Streamer Methods ------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file provides CSKY specific target streamer methods. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "CSKYELFStreamer.h" |
| #include "CSKYMCTargetDesc.h" |
| #include "MCTargetDesc/CSKYAsmBackend.h" |
| #include "MCTargetDesc/CSKYBaseInfo.h" |
| #include "llvm/BinaryFormat/ELF.h" |
| #include "llvm/MC/MCAssembler.h" |
| #include "llvm/MC/MCContext.h" |
| #include "llvm/MC/MCSectionELF.h" |
| #include "llvm/MC/MCSubtargetInfo.h" |
| #include "llvm/MC/MCSymbolELF.h" |
| #include "llvm/Support/CSKYAttributes.h" |
| #include "llvm/Support/CSKYTargetParser.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/LEB128.h" |
| |
| using namespace llvm; |
| |
| // This part is for ELF object output. |
| CSKYTargetELFStreamer::CSKYTargetELFStreamer(MCStreamer &S, |
| const MCSubtargetInfo &STI) |
| : CSKYTargetStreamer(S), CurrentVendor("csky") { |
| MCAssembler &MCA = getStreamer().getAssembler(); |
| const FeatureBitset &Features = STI.getFeatureBits(); |
| |
| unsigned EFlags = MCA.getELFHeaderEFlags(); |
| |
| EFlags |= ELF::EF_CSKY_ABIV2; |
| |
| if (Features[CSKY::ProcCK801]) |
| EFlags |= ELF::EF_CSKY_801; |
| else if (Features[CSKY::ProcCK802]) |
| EFlags |= ELF::EF_CSKY_802; |
| else if (Features[CSKY::ProcCK803]) |
| EFlags |= ELF::EF_CSKY_803; |
| else if (Features[CSKY::ProcCK804]) |
| EFlags |= ELF::EF_CSKY_803; |
| else if (Features[CSKY::ProcCK805]) |
| EFlags |= ELF::EF_CSKY_805; |
| else if (Features[CSKY::ProcCK807]) |
| EFlags |= ELF::EF_CSKY_807; |
| else if (Features[CSKY::ProcCK810]) |
| EFlags |= ELF::EF_CSKY_810; |
| else if (Features[CSKY::ProcCK860]) |
| EFlags |= ELF::EF_CSKY_860; |
| else |
| EFlags |= ELF::EF_CSKY_810; |
| |
| if (Features[CSKY::FeatureFPUV2_SF] || Features[CSKY::FeatureFPUV3_SF]) |
| EFlags |= ELF::EF_CSKY_FLOAT; |
| |
| EFlags |= ELF::EF_CSKY_EFV1; |
| |
| MCA.setELFHeaderEFlags(EFlags); |
| } |
| |
| MCELFStreamer &CSKYTargetELFStreamer::getStreamer() { |
| return static_cast<MCELFStreamer &>(Streamer); |
| } |
| |
| void CSKYTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { |
| setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true); |
| } |
| |
| void CSKYTargetELFStreamer::emitTextAttribute(unsigned Attribute, |
| StringRef String) { |
| setAttributeItem(Attribute, String, /*OverwriteExisting=*/true); |
| } |
| |
| void CSKYTargetELFStreamer::finishAttributeSection() { |
| if (Contents.empty()) |
| return; |
| |
| if (AttributeSection) { |
| Streamer.switchSection(AttributeSection); |
| } else { |
| MCAssembler &MCA = getStreamer().getAssembler(); |
| AttributeSection = MCA.getContext().getELFSection( |
| ".csky.attributes", ELF::SHT_CSKY_ATTRIBUTES, 0); |
| Streamer.switchSection(AttributeSection); |
| Streamer.emitInt8(ELFAttrs::Format_Version); |
| } |
| |
| // Vendor size + Vendor name + '\0' |
| const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1; |
| |
| // Tag + Tag Size |
| const size_t TagHeaderSize = 1 + 4; |
| |
| const size_t ContentsSize = calculateContentSize(); |
| |
| Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize); |
| Streamer.emitBytes(CurrentVendor); |
| Streamer.emitInt8(0); // '\0' |
| |
| Streamer.emitInt8(ELFAttrs::File); |
| Streamer.emitInt32(TagHeaderSize + ContentsSize); |
| |
| // Size should have been accounted for already, now |
| // emit each field as its type (ULEB or String). |
| for (AttributeItem item : Contents) { |
| Streamer.emitULEB128IntValue(item.Tag); |
| switch (item.Type) { |
| default: |
| llvm_unreachable("Invalid attribute type"); |
| case AttributeType::Numeric: |
| Streamer.emitULEB128IntValue(item.IntValue); |
| break; |
| case AttributeType::Text: |
| Streamer.emitBytes(item.StringValue); |
| Streamer.emitInt8(0); // '\0' |
| break; |
| case AttributeType::NumericAndText: |
| Streamer.emitULEB128IntValue(item.IntValue); |
| Streamer.emitBytes(item.StringValue); |
| Streamer.emitInt8(0); // '\0' |
| break; |
| } |
| } |
| |
| Contents.clear(); |
| } |
| |
| size_t CSKYTargetELFStreamer::calculateContentSize() const { |
| size_t Result = 0; |
| for (AttributeItem item : Contents) { |
| switch (item.Type) { |
| case AttributeType::Hidden: |
| break; |
| case AttributeType::Numeric: |
| Result += getULEB128Size(item.Tag); |
| Result += getULEB128Size(item.IntValue); |
| break; |
| case AttributeType::Text: |
| Result += getULEB128Size(item.Tag); |
| Result += item.StringValue.size() + 1; // string + '\0' |
| break; |
| case AttributeType::NumericAndText: |
| Result += getULEB128Size(item.Tag); |
| Result += getULEB128Size(item.IntValue); |
| Result += item.StringValue.size() + 1; // string + '\0'; |
| break; |
| } |
| } |
| return Result; |
| } |
| |
| void CSKYELFStreamer::EmitMappingSymbol(StringRef Name) { |
| if (Name == "$d" && State == EMS_Data) |
| return; |
| if (Name == "$t" && State == EMS_Text) |
| return; |
| if (Name == "$t" && State == EMS_None) { |
| State = EMS_Text; |
| return; |
| } |
| |
| State = (Name == "$t" ? EMS_Text : EMS_Data); |
| |
| auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol( |
| Name + "." + Twine(MappingSymbolCounter++))); |
| emitLabel(Symbol); |
| |
| Symbol->setType(ELF::STT_NOTYPE); |
| Symbol->setBinding(ELF::STB_LOCAL); |
| } |
| |
| void CSKYTargetELFStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) { |
| StringRef CPU = STI.getCPU(); |
| CSKY::ArchKind ArchID = CSKY::parseCPUArch(CPU); |
| |
| if (ArchID == CSKY::ArchKind::CK804) |
| ArchID = CSKY::ArchKind::CK803; |
| |
| StringRef CPU_ARCH = CSKY::getArchName(ArchID); |
| |
| if (ArchID == CSKY::ArchKind::INVALID) { |
| CPU = "ck810"; |
| CPU_ARCH = "ck810"; |
| } |
| emitTextAttribute(CSKYAttrs::CSKY_ARCH_NAME, CPU_ARCH); |
| emitTextAttribute(CSKYAttrs::CSKY_CPU_NAME, CPU); |
| |
| unsigned ISAFlag = 0; |
| if (STI.hasFeature(CSKY::HasE1)) |
| ISAFlag |= CSKYAttrs::V2_ISA_E1; |
| |
| if (STI.hasFeature(CSKY::HasE2)) |
| ISAFlag |= CSKYAttrs::V2_ISA_1E2; |
| |
| if (STI.hasFeature(CSKY::Has2E3)) |
| ISAFlag |= CSKYAttrs::V2_ISA_2E3; |
| |
| if (STI.hasFeature(CSKY::HasMP)) |
| ISAFlag |= CSKYAttrs::ISA_MP; |
| |
| if (STI.hasFeature(CSKY::Has3E3r1)) |
| ISAFlag |= CSKYAttrs::V2_ISA_3E3R1; |
| |
| if (STI.hasFeature(CSKY::Has3r1E3r2)) |
| ISAFlag |= CSKYAttrs::V2_ISA_3E3R2; |
| |
| if (STI.hasFeature(CSKY::Has3r2E3r3)) |
| ISAFlag |= CSKYAttrs::V2_ISA_3E3R3; |
| |
| if (STI.hasFeature(CSKY::Has3E7)) |
| ISAFlag |= CSKYAttrs::V2_ISA_3E7; |
| |
| if (STI.hasFeature(CSKY::HasMP1E2)) |
| ISAFlag |= CSKYAttrs::ISA_MP_1E2; |
| |
| if (STI.hasFeature(CSKY::Has7E10)) |
| ISAFlag |= CSKYAttrs::V2_ISA_7E10; |
| |
| if (STI.hasFeature(CSKY::Has10E60)) |
| ISAFlag |= CSKYAttrs::V2_ISA_10E60; |
| |
| if (STI.hasFeature(CSKY::FeatureTrust)) |
| ISAFlag |= CSKYAttrs::ISA_TRUST; |
| |
| if (STI.hasFeature(CSKY::FeatureJAVA)) |
| ISAFlag |= CSKYAttrs::ISA_JAVA; |
| |
| if (STI.hasFeature(CSKY::FeatureCache)) |
| ISAFlag |= CSKYAttrs::ISA_CACHE; |
| |
| if (STI.hasFeature(CSKY::FeatureNVIC)) |
| ISAFlag |= CSKYAttrs::ISA_NVIC; |
| |
| if (STI.hasFeature(CSKY::FeatureDSP)) |
| ISAFlag |= CSKYAttrs::ISA_DSP; |
| |
| if (STI.hasFeature(CSKY::HasDSP1E2)) |
| ISAFlag |= CSKYAttrs::ISA_DSP_1E2; |
| |
| if (STI.hasFeature(CSKY::HasDSPE60)) |
| ISAFlag |= CSKYAttrs::V2_ISA_DSPE60; |
| |
| if (STI.hasFeature(CSKY::FeatureDSPV2)) |
| ISAFlag |= CSKYAttrs::ISA_DSP_ENHANCE; |
| |
| if (STI.hasFeature(CSKY::FeatureDSP_Silan)) |
| ISAFlag |= CSKYAttrs::ISA_DSP_SILAN; |
| |
| if (STI.hasFeature(CSKY::FeatureVDSPV1_128)) |
| ISAFlag |= CSKYAttrs::ISA_VDSP; |
| |
| if (STI.hasFeature(CSKY::FeatureVDSPV2)) |
| ISAFlag |= CSKYAttrs::ISA_VDSP_2; |
| |
| if (STI.hasFeature(CSKY::HasVDSP2E3)) |
| ISAFlag |= CSKYAttrs::ISA_VDSP_2E3; |
| |
| if (STI.hasFeature(CSKY::HasVDSP2E60F)) |
| ISAFlag |= CSKYAttrs::ISA_VDSP_2E60F; |
| |
| emitAttribute(CSKYAttrs::CSKY_ISA_FLAGS, ISAFlag); |
| |
| unsigned ISAExtFlag = 0; |
| if (STI.hasFeature(CSKY::HasFLOATE1)) |
| ISAExtFlag |= CSKYAttrs::ISA_FLOAT_E1; |
| |
| if (STI.hasFeature(CSKY::HasFLOAT1E2)) |
| ISAExtFlag |= CSKYAttrs::ISA_FLOAT_1E2; |
| |
| if (STI.hasFeature(CSKY::HasFLOAT1E3)) |
| ISAExtFlag |= CSKYAttrs::ISA_FLOAT_1E3; |
| |
| if (STI.hasFeature(CSKY::HasFLOAT3E4)) |
| ISAExtFlag |= CSKYAttrs::ISA_FLOAT_3E4; |
| |
| if (STI.hasFeature(CSKY::HasFLOAT7E60)) |
| ISAExtFlag |= CSKYAttrs::ISA_FLOAT_7E60; |
| |
| emitAttribute(CSKYAttrs::CSKY_ISA_EXT_FLAGS, ISAExtFlag); |
| |
| if (STI.hasFeature(CSKY::FeatureDSP)) |
| emitAttribute(CSKYAttrs::CSKY_DSP_VERSION, |
| CSKYAttrs::DSP_VERSION_EXTENSION); |
| if (STI.hasFeature(CSKY::FeatureDSPV2)) |
| emitAttribute(CSKYAttrs::CSKY_DSP_VERSION, CSKYAttrs::DSP_VERSION_2); |
| |
| if (STI.hasFeature(CSKY::FeatureVDSPV2)) |
| emitAttribute(CSKYAttrs::CSKY_VDSP_VERSION, CSKYAttrs::VDSP_VERSION_2); |
| |
| if (STI.hasFeature(CSKY::FeatureFPUV2_SF) || |
| STI.hasFeature(CSKY::FeatureFPUV2_DF)) |
| emitAttribute(CSKYAttrs::CSKY_FPU_VERSION, CSKYAttrs::FPU_VERSION_2); |
| else if (STI.hasFeature(CSKY::FeatureFPUV3_HF) || |
| STI.hasFeature(CSKY::FeatureFPUV3_SF) || |
| STI.hasFeature(CSKY::FeatureFPUV3_DF)) |
| emitAttribute(CSKYAttrs::CSKY_FPU_VERSION, CSKYAttrs::FPU_VERSION_3); |
| |
| bool hasAnyFloatExt = STI.hasFeature(CSKY::FeatureFPUV2_SF) || |
| STI.hasFeature(CSKY::FeatureFPUV2_DF) || |
| STI.hasFeature(CSKY::FeatureFPUV3_HF) || |
| STI.hasFeature(CSKY::FeatureFPUV3_SF) || |
| STI.hasFeature(CSKY::FeatureFPUV3_DF); |
| |
| if (hasAnyFloatExt && STI.hasFeature(CSKY::ModeHardFloat) && |
| STI.hasFeature(CSKY::ModeHardFloatABI)) |
| emitAttribute(CSKYAttrs::CSKY_FPU_ABI, CSKYAttrs::FPU_ABI_HARD); |
| else if (hasAnyFloatExt && STI.hasFeature(CSKY::ModeHardFloat)) |
| emitAttribute(CSKYAttrs::CSKY_FPU_ABI, CSKYAttrs::FPU_ABI_SOFTFP); |
| else |
| emitAttribute(CSKYAttrs::CSKY_FPU_ABI, CSKYAttrs::FPU_ABI_SOFT); |
| |
| unsigned HardFPFlag = 0; |
| if (STI.hasFeature(CSKY::FeatureFPUV3_HF)) |
| HardFPFlag |= CSKYAttrs::FPU_HARDFP_HALF; |
| if (STI.hasFeature(CSKY::FeatureFPUV2_SF) || |
| STI.hasFeature(CSKY::FeatureFPUV3_SF)) |
| HardFPFlag |= CSKYAttrs::FPU_HARDFP_SINGLE; |
| if (STI.hasFeature(CSKY::FeatureFPUV2_DF) || |
| STI.hasFeature(CSKY::FeatureFPUV3_DF)) |
| HardFPFlag |= CSKYAttrs::FPU_HARDFP_DOUBLE; |
| |
| if (HardFPFlag != 0) { |
| emitAttribute(CSKYAttrs::CSKY_FPU_DENORMAL, CSKYAttrs::NEEDED); |
| emitAttribute(CSKYAttrs::CSKY_FPU_EXCEPTION, CSKYAttrs::NEEDED); |
| emitTextAttribute(CSKYAttrs::CSKY_FPU_NUMBER_MODULE, "IEEE 754"); |
| emitAttribute(CSKYAttrs::CSKY_FPU_HARDFP, HardFPFlag); |
| } |
| } |