| //===-- CSKYELFStreamer.h - CSKY ELF Target Streamer -----------*- C++ -*--===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_LIB_TARGET_CSKY_CSKYELFSTREAMER_H |
| #define LLVM_LIB_TARGET_CSKY_CSKYELFSTREAMER_H |
| |
| #include "CSKYTargetStreamer.h" |
| #include "llvm/MC/MCCodeEmitter.h" |
| #include "llvm/MC/MCELFStreamer.h" |
| #include "llvm/MC/MCObjectWriter.h" |
| |
| namespace llvm { |
| |
| class CSKYTargetELFStreamer : public CSKYTargetStreamer { |
| private: |
| enum class AttributeType { Hidden, Numeric, Text, NumericAndText }; |
| |
| struct AttributeItem { |
| AttributeType Type; |
| unsigned Tag; |
| unsigned IntValue; |
| std::string StringValue; |
| }; |
| |
| StringRef CurrentVendor; |
| SmallVector<AttributeItem, 64> Contents; |
| |
| MCSection *AttributeSection = nullptr; |
| |
| AttributeItem *getAttributeItem(unsigned Attribute) { |
| for (size_t i = 0; i < Contents.size(); ++i) |
| if (Contents[i].Tag == Attribute) |
| return &Contents[i]; |
| return nullptr; |
| } |
| |
| void setAttributeItem(unsigned Attribute, unsigned Value, |
| bool OverwriteExisting) { |
| // Look for existing attribute item. |
| if (AttributeItem *Item = getAttributeItem(Attribute)) { |
| if (!OverwriteExisting) |
| return; |
| Item->Type = AttributeType::Numeric; |
| Item->IntValue = Value; |
| return; |
| } |
| |
| // Create new attribute item. |
| Contents.push_back({AttributeType::Numeric, Attribute, Value, ""}); |
| } |
| |
| void setAttributeItem(unsigned Attribute, StringRef Value, |
| bool OverwriteExisting) { |
| // Look for existing attribute item. |
| if (AttributeItem *Item = getAttributeItem(Attribute)) { |
| if (!OverwriteExisting) |
| return; |
| Item->Type = AttributeType::Text; |
| Item->StringValue = std::string(Value); |
| return; |
| } |
| |
| // Create new attribute item. |
| Contents.push_back({AttributeType::Text, Attribute, 0, std::string(Value)}); |
| } |
| |
| void setAttributeItems(unsigned Attribute, unsigned IntValue, |
| StringRef StringValue, bool OverwriteExisting) { |
| // Look for existing attribute item. |
| if (AttributeItem *Item = getAttributeItem(Attribute)) { |
| if (!OverwriteExisting) |
| return; |
| Item->Type = AttributeType::NumericAndText; |
| Item->IntValue = IntValue; |
| Item->StringValue = std::string(StringValue); |
| return; |
| } |
| |
| // Create new attribute item. |
| Contents.push_back({AttributeType::NumericAndText, Attribute, IntValue, |
| std::string(StringValue)}); |
| } |
| |
| void emitAttribute(unsigned Attribute, unsigned Value) override; |
| void emitTextAttribute(unsigned Attribute, StringRef String) override; |
| void finishAttributeSection() override; |
| size_t calculateContentSize() const; |
| |
| void emitTargetAttributes(const MCSubtargetInfo &STI) override; |
| |
| public: |
| MCELFStreamer &getStreamer(); |
| CSKYTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); |
| }; |
| |
| class CSKYELFStreamer : public MCELFStreamer { |
| int64_t MappingSymbolCounter = 0; |
| |
| void EmitMappingSymbol(StringRef Name); |
| |
| public: |
| friend class CSKYTargetELFStreamer; |
| |
| enum ElfMappingSymbol { EMS_None, EMS_Text, EMS_Data }; |
| |
| ElfMappingSymbol State; |
| |
| CSKYELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, |
| std::unique_ptr<MCObjectWriter> OW, |
| std::unique_ptr<MCCodeEmitter> Emitter) |
| : MCELFStreamer(Context, std::move(TAB), std::move(OW), |
| std::move(Emitter)), |
| State(EMS_None) {} |
| |
| ~CSKYELFStreamer() override = default; |
| |
| void emitFill(const MCExpr &NumBytes, uint64_t FillValue, |
| SMLoc Loc) override { |
| EmitMappingSymbol("$d"); |
| MCObjectStreamer::emitFill(NumBytes, FillValue, Loc); |
| } |
| void emitBytes(StringRef Data) override { |
| EmitMappingSymbol("$d"); |
| MCELFStreamer::emitBytes(Data); |
| } |
| void emitInstruction(const MCInst &Inst, |
| const MCSubtargetInfo &STI) override { |
| EmitMappingSymbol("$t"); |
| MCELFStreamer::emitInstruction(Inst, STI); |
| } |
| void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override { |
| EmitMappingSymbol("$d"); |
| MCELFStreamer::emitValueImpl(Value, Size, Loc); |
| } |
| void reset() override { |
| MappingSymbolCounter = 0; |
| State = EMS_None; |
| MCELFStreamer::reset(); |
| } |
| }; |
| |
| } // namespace llvm |
| #endif |