Add support of parsing .csky_attribute directive and emit related target attributes in .csky.attribute section. It does not emit attribute directive in assembly code, so only emit target attributes in ELF streamer. In ELF streamer, it handles the header EFlag and the csky_attribute section which contains some attribute items. The EFlag and attribute items are calculated from feature bits based on Subtarget.
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);
|
|
}
|
|
}
|