336 lines
10 KiB
C++
336 lines
10 KiB
C++
//===-- 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);
|
|
}
|
|
}
|