summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt1
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp24
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h22
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp92
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp49
-rw-r--r--llvm/lib/Target/Mips/MipsOptionRecord.h80
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
OpenPOWER on IntegriCloud