diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h | 22 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp | 92 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp | 49 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsOptionRecord.h | 80 |
6 files changed, 224 insertions, 44 deletions
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt index c14ee355f80..6b3788ca515 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt @@ -8,5 +8,6 @@ add_llvm_library(LLVMMipsDesc MipsMCExpr.cpp MipsMCTargetDesc.cpp MipsNaClELFStreamer.cpp + MipsOptionRecord.cpp MipsTargetStreamer.cpp ) diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp index fe378292bef..803ab85657d 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp @@ -8,6 +8,30 @@ //===----------------------------------------------------------------------===// #include "MipsELFStreamer.h" +#include "llvm/MC/MCInst.h" + +void MipsELFStreamer::EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCELFStreamer::EmitInstruction(Inst, STI); + + MCContext &Context = getContext(); + const MCRegisterInfo *MCRegInfo = Context.getRegisterInfo(); + + for (unsigned OpIndex = 0; OpIndex < Inst.getNumOperands(); ++OpIndex) { + const MCOperand &Op = Inst.getOperand(OpIndex); + + if (!Op.isReg()) + continue; + + unsigned Reg = Op.getReg(); + RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo); + } +} + +void MipsELFStreamer::EmitMipsOptionRecords() { + for (const auto &I : MipsOptionRecords) + I->EmitMipsOptionRecord(); +} namespace llvm { MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h index 641f8cf7af2..58863be9cc2 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h @@ -15,8 +15,10 @@ #ifndef MIPSELFSTREAMER_H #define MIPSELFSTREAMER_H +#include "MipsOptionRecord.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCELFStreamer.h" -#include "llvm/Support/raw_ostream.h" +#include <memory> namespace llvm { class MCAsmBackend; @@ -25,13 +27,27 @@ class MCContext; class MCSubtargetInfo; class MipsELFStreamer : public MCELFStreamer { + SmallVector<std::unique_ptr<MipsOptionRecord>, 8> MipsOptionRecords; + MipsRegInfoRecord *RegInfoRecord; public: MipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter, const MCSubtargetInfo &STI) - : MCELFStreamer(Context, MAB, OS, Emitter) {} + : MCELFStreamer(Context, MAB, OS, Emitter) { - virtual ~MipsELFStreamer() {} + RegInfoRecord = new MipsRegInfoRecord(this, Context, STI); + MipsOptionRecords.push_back( + std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord)); + } + + /// Overriding this function allows us to add arbitrary behaviour before the + /// \p Inst is actually emitted. For example, we can inspect the operands and + /// gather sufficient information that allows us to reason about the register + /// usage for the translation unit. + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + + /// Emits all the option records stored up until the point it's called. + void EmitMipsOptionRecords(); }; MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp new file mode 100644 index 00000000000..0ef22082132 --- /dev/null +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp @@ -0,0 +1,92 @@ +//===-- MipsOptionRecord.cpp - Abstraction for storing information --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MipsOptionRecord.h" +#include "MipsELFStreamer.h" +#include "llvm/MC/MCSectionELF.h" + +using namespace llvm; + +void MipsRegInfoRecord::EmitMipsOptionRecord() { + MCAssembler &MCA = Streamer->getAssembler(); + Triple T(STI.getTargetTriple()); + uint64_t Features = STI.getFeatureBits(); + + Streamer->PushSection(); + + // We need to distinguish between N64 and the rest because at the moment + // we don't emit .Mips.options for other ELFs other than N64. + // Since .reginfo has the same information as .Mips.options (ODK_REGINFO), + // we can use the same abstraction (MipsRegInfoRecord class) to handle both. + if (Features & Mips::FeatureN64) { + // The EntrySize value of 1 seems strange since the records are neither + // 1-byte long nor fixed length but it matches the value GAS emits. + const MCSectionELF *Sec = + Context.getELFSection(".MIPS.options", ELF::SHT_MIPS_OPTIONS, + ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, + SectionKind::getMetadata(), 1, ""); + MCA.getOrCreateSectionData(*Sec).setAlignment(8); + Streamer->SwitchSection(Sec); + + Streamer->EmitIntValue(1, 1); // kind + Streamer->EmitIntValue(40, 1); // size + Streamer->EmitIntValue(0, 2); // section + Streamer->EmitIntValue(0, 4); // info + Streamer->EmitIntValue(ri_gprmask, 4); + Streamer->EmitIntValue(0, 4); // pad + Streamer->EmitIntValue(ri_cprmask[0], 4); + Streamer->EmitIntValue(ri_cprmask[1], 4); + Streamer->EmitIntValue(ri_cprmask[2], 4); + Streamer->EmitIntValue(ri_cprmask[3], 4); + Streamer->EmitIntValue(ri_gp_value, 8); + } else { + const MCSectionELF *Sec = + Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC, + SectionKind::getMetadata(), 24, ""); + MCA.getOrCreateSectionData(*Sec) + .setAlignment(Features & Mips::FeatureN32 ? 8 : 4); + Streamer->SwitchSection(Sec); + + Streamer->EmitIntValue(ri_gprmask, 4); + Streamer->EmitIntValue(ri_cprmask[0], 4); + Streamer->EmitIntValue(ri_cprmask[1], 4); + Streamer->EmitIntValue(ri_cprmask[2], 4); + Streamer->EmitIntValue(ri_cprmask[3], 4); + assert((ri_gp_value & 0xffffffff) == ri_gp_value); + Streamer->EmitIntValue(ri_gp_value, 4); + } + + Streamer->PopSection(); +} + +void MipsRegInfoRecord::SetPhysRegUsed(unsigned Reg, + const MCRegisterInfo *MCRegInfo) { + unsigned Value = 0; + + for (MCSubRegIterator SubRegIt(Reg, MCRegInfo, true); SubRegIt.isValid(); + ++SubRegIt) { + unsigned CurrentSubReg = *SubRegIt; + + unsigned EncVal = MCRegInfo->getEncodingValue(CurrentSubReg); + Value |= 1 << EncVal; + + if (GPR32RegClass->contains(CurrentSubReg) || + GPR64RegClass->contains(CurrentSubReg)) + ri_gprmask |= Value; + else if (FGR32RegClass->contains(CurrentSubReg) || + FGR64RegClass->contains(CurrentSubReg) || + AFGR64RegClass->contains(CurrentSubReg) || + MSA128BRegClass->contains(CurrentSubReg)) + ri_cprmask[1] |= Value; + else if (COP2RegClass->contains(CurrentSubReg)) + ri_cprmask[2] |= Value; + else if (COP3RegClass->contains(CurrentSubReg)) + ri_cprmask[3] |= Value; + } +} diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 4e7216921b9..4a178e2df7a 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "InstPrinter/MipsInstPrinter.h" +#include "MipsELFStreamer.h" #include "MipsMCTargetDesc.h" #include "MipsTargetObjectFile.h" #include "MipsTargetStreamer.h" @@ -323,11 +324,7 @@ void MipsTargetELFStreamer::emitLabel(MCSymbol *Symbol) { void MipsTargetELFStreamer::finish() { MCAssembler &MCA = getStreamer().getAssembler(); - MCContext &Context = MCA.getContext(); - MCStreamer &OS = getStreamer(); - const MCObjectFileInfo &OFI = *Context.getObjectFileInfo(); - Triple T(STI.getTargetTriple()); - uint64_t Features = STI.getFeatureBits(); + const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo(); // .bss, .text and .data are always at least 16-byte aligned. MCSectionData &TextSectionData = @@ -341,42 +338,12 @@ void MipsTargetELFStreamer::finish() { DataSectionData.setAlignment(std::max(16u, DataSectionData.getAlignment())); BSSSectionData.setAlignment(std::max(16u, BSSSectionData.getAlignment())); - if (T.isArch64Bit() && (Features & Mips::FeatureN64)) { - // The EntrySize value of 1 seems strange since the records are neither - // 1-byte long nor fixed length but it matches the value GAS emits. - const MCSectionELF *Sec = - Context.getELFSection(".MIPS.options", ELF::SHT_MIPS_OPTIONS, - ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, - SectionKind::getMetadata(), 1, ""); - MCA.getOrCreateSectionData(*Sec).setAlignment(8); - OS.SwitchSection(Sec); - - OS.EmitIntValue(1, 1); // kind - OS.EmitIntValue(40, 1); // size - OS.EmitIntValue(0, 2); // section - OS.EmitIntValue(0, 4); // info - OS.EmitIntValue(0, 4); // ri_gprmask - OS.EmitIntValue(0, 4); // pad - OS.EmitIntValue(0, 4); // ri_cpr[0]mask - OS.EmitIntValue(0, 4); // ri_cpr[1]mask - OS.EmitIntValue(0, 4); // ri_cpr[2]mask - OS.EmitIntValue(0, 4); // ri_cpr[3]mask - OS.EmitIntValue(0, 8); // ri_gp_value - } else { - const MCSectionELF *Sec = - Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC, - SectionKind::getMetadata(), 24, ""); - MCA.getOrCreateSectionData(*Sec) - .setAlignment(Features & Mips::FeatureN32 ? 8 : 4); - OS.SwitchSection(Sec); - - OS.EmitIntValue(0, 4); // ri_gprmask - OS.EmitIntValue(0, 4); // ri_cpr[0]mask - OS.EmitIntValue(0, 4); // ri_cpr[1]mask - OS.EmitIntValue(0, 4); // ri_cpr[2]mask - OS.EmitIntValue(0, 4); // ri_cpr[3]mask - OS.EmitIntValue(0, 4); // ri_gp_value - } + // Emit all the option records. + // At the moment we are only emitting .Mips.options (ODK_REGINFO) and + // .reginfo. + MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer); + MEF.EmitMipsOptionRecords(); + emitMipsAbiFlags(); } diff --git a/llvm/lib/Target/Mips/MipsOptionRecord.h b/llvm/lib/Target/Mips/MipsOptionRecord.h new file mode 100644 index 00000000000..c0abce3eadd --- /dev/null +++ b/llvm/lib/Target/Mips/MipsOptionRecord.h @@ -0,0 +1,80 @@ +//===-- MipsOptionRecord.h - Abstraction for storing information ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// MipsOptionRecord - Abstraction for storing arbitrary information in +// ELF files. Arbitrary information (e.g. register usage) can be stored in Mips +// specific ELF sections like .Mips.options. Specific records should subclass +// MipsOptionRecord and provide an implementation to EmitMipsOptionRecord which +// basically just dumps the information into an ELF section. More information +// about .Mips.option can be found in the SysV ABI and the 64-bit ELF Object +// specification. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSOPTIONRECORD_H +#define MIPSOPTIONRECORD_H + +#include "MipsMCTargetDesc.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCRegisterInfo.h" + +using namespace llvm; + +namespace llvm { +class MipsELFStreamer; +class MCSubtargetInfo; +} + +class MipsOptionRecord { +public: + virtual ~MipsOptionRecord(){}; + virtual void EmitMipsOptionRecord() = 0; +}; + +class MipsRegInfoRecord : public MipsOptionRecord { +public: + MipsRegInfoRecord(MipsELFStreamer *S, MCContext &Context, + const MCSubtargetInfo &STI) + : Streamer(S), Context(Context), STI(STI) { + ri_gprmask = 0; + ri_cprmask[0] = ri_cprmask[1] = ri_cprmask[2] = ri_cprmask[3] = 0; + ri_gp_value = 0; + + const MCRegisterInfo *TRI = Context.getRegisterInfo(); + GPR32RegClass = &(TRI->getRegClass(Mips::GPR32RegClassID)); + GPR64RegClass = &(TRI->getRegClass(Mips::GPR64RegClassID)); + FGR32RegClass = &(TRI->getRegClass(Mips::FGR32RegClassID)); + FGR64RegClass = &(TRI->getRegClass(Mips::FGR64RegClassID)); + AFGR64RegClass = &(TRI->getRegClass(Mips::AFGR64RegClassID)); + MSA128BRegClass = &(TRI->getRegClass(Mips::MSA128BRegClassID)); + COP2RegClass = &(TRI->getRegClass(Mips::COP2RegClassID)); + COP3RegClass = &(TRI->getRegClass(Mips::COP3RegClassID)); + } + ~MipsRegInfoRecord() {} + + void EmitMipsOptionRecord(); + void SetPhysRegUsed(unsigned Reg, const MCRegisterInfo *MCRegInfo); + +private: + MipsELFStreamer *Streamer; + MCContext &Context; + const MCSubtargetInfo &STI; + const MCRegisterClass *GPR32RegClass; + const MCRegisterClass *GPR64RegClass; + const MCRegisterClass *FGR32RegClass; + const MCRegisterClass *FGR64RegClass; + const MCRegisterClass *AFGR64RegClass; + const MCRegisterClass *MSA128BRegClass; + const MCRegisterClass *COP2RegClass; + const MCRegisterClass *COP3RegClass; + uint32_t ri_gprmask; + uint32_t ri_cprmask[4]; + int64_t ri_gp_value; +}; +#endif |