| //===-- 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); | |
| } | |
| } |