diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFStreamer.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFStreamer.cpp | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFStreamer.cpp b/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFStreamer.cpp new file mode 100644 index 000000000000..90775c1b70f2 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFStreamer.cpp @@ -0,0 +1,335 @@ +//===-- 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); + } +} |
