// this section based on their sizes
SHT_X86_64_UNWIND = 0x70000001, // Unwind information
+ SHT_MIPS_REGINFO = 0x70000006, // Register usage information
+ SHT_MIPS_OPTIONS = 0x7000000d, // General options
+
SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type.
SHT_LOUSER = 0x80000000, // Lowest type reserved for applications.
SHT_HIUSER = 0xffffffff // Highest type reserved for applications.
// All sections with the GPREL flag are grouped into a global data area
// for faster accesses
- SHF_HEX_GPREL = 0x10000000
+ SHF_HEX_GPREL = 0x10000000,
+ // Do not strip this section. FIXME: We need target specific SHF_ enums.
+ SHF_MIPS_NOSTRIP = 0x8000000
};
// Section Group Flags
case ELF::SHT_FINI_ARRAY:
case ELF::SHT_PREINIT_ARRAY:
case ELF::SHT_X86_64_UNWIND:
+ case ELF::SHT_MIPS_REGINFO:
+ case ELF::SHT_MIPS_OPTIONS:
// Nothing to do.
break;
MipsMCCodeEmitter.cpp
MipsMCTargetDesc.cpp
MipsELFObjectWriter.cpp
+ MipsReginfo.cpp
)
add_dependencies(LLVMMipsDesc MipsCommonTableGen)
--- /dev/null
+//===-- MipsReginfo.cpp - Registerinfo handling --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// .reginfo
+// Elf32_Word ri_gprmask
+// Elf32_Word ri_cprmask[4]
+// Elf32_Word ri_gp_value
+//
+// .MIPS.options - N64
+// Elf64_Byte kind (ODK_REGINFO)
+// Elf64_Byte size (40 bytes)
+// Elf64_Section section (0)
+// Elf64_Word info (unused)
+// Elf64_Word ri_gprmask ()
+// Elf64_Word ri_pad ()
+// Elf64_Word[4] ri_cprmask ()
+// Elf64_Addr ri_gp_value ()
+//
+// .MIPS.options - N32
+// Elf32_Byte kind (ODK_REGINFO)
+// Elf32_Byte size (36 bytes)
+// Elf32_Section section (0)
+// Elf32_Word info (unused)
+// Elf32_Word ri_gprmask ()
+// Elf32_Word ri_pad ()
+// Elf32_Word[4] ri_cprmask ()
+// Elf32_Addr ri_gp_value ()
+//
+//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/MipsReginfo.h"
+#include "MipsSubtarget.h"
+#include "MipsTargetObjectFile.h"
+#include "llvm/MC/MCStreamer.h"
+
+using namespace llvm;
+
+// Integrated assembler version
+void
+MipsReginfo::emitMipsReginfoSectionCG(MCStreamer &OS,
+ const TargetLoweringObjectFile &TLOF,
+ const MipsSubtarget &MST) const
+{
+
+ if (OS.hasRawTextSupport())
+ return;
+
+ const MipsTargetObjectFile &TLOFELF =
+ static_cast<const MipsTargetObjectFile &>(TLOF);
+ OS.SwitchSection(TLOFELF.getReginfoSection());
+
+ // .reginfo
+ if (MST.isABI_O32()) {
+ 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
+ }
+ // .MIPS.options
+ else if (MST.isABI_N64()) {
+ 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 llvm_unreachable("Unsupported abi for reginfo");
+}
+
--- /dev/null
+//=== MipsReginfo.h - MipsReginfo -----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENCE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSREGINFO_H
+#define MIPSREGINFO_H
+
+namespace llvm {
+ class MCStreamer;
+ class TargetLoweringObjectFile;
+ class MipsSubtarget;
+
+ class MipsReginfo {
+ void anchor();
+ public:
+ MipsReginfo() {}
+
+ void emitMipsReginfoSectionCG(MCStreamer &OS,
+ const TargetLoweringObjectFile &TLOF,
+ const MipsSubtarget &MST) const;
+ };
+
+} // namespace llvm
+
+#endif
+
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "mips-asm-printer"
-#include "MipsAsmPrinter.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips.h"
+#include "MipsAsmPrinter.h"
#include "MipsInstrInfo.h"
#include "MipsMCInstLower.h"
#include "llvm/ADT/SmallString.h"
// return to previous section
if (OutStreamer.hasRawTextSupport())
OutStreamer.EmitRawText(StringRef("\t.previous"));
+
+}
+
+void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) {
+
+ // Emit Mips ELF register info
+ Subtarget->getMReginfo().emitMipsReginfoSectionCG(
+ OutStreamer, getObjFileLowering(), *Subtarget);
}
MachineLocation
void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
const char *Modifier = 0);
void EmitStartOfAsmFile(Module &M);
+ void EmitEndOfAsmFile(Module &M);
virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const;
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
};
#ifndef MIPSSUBTARGET_H
#define MIPSSUBTARGET_H
+#include "MCTargetDesc/MipsReginfo.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <string>
InstrItineraryData InstrItins;
+ // The instance to the register info section object
+ MipsReginfo MRI;
+
public:
virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
AntiDepBreakMode& Mode,
bool hasSwap() const { return HasSwap; }
bool hasBitCount() const { return HasBitCount; }
bool hasFPIdx() const { return HasFPIdx; }
+
+ // Grab MipsRegInfo object
+ const MipsReginfo &getMReginfo() const { return MRI; }
};
} // End llvm namespace
ELF::SHF_WRITE |ELF::SHF_ALLOC,
SectionKind::getBSS());
+ // Register info information
+ const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>();
+ if (Subtarget.isABI_N64() || Subtarget.isABI_N32())
+ ReginfoSection =
+ getContext().getELFSection(".MIPS.options",
+ ELF::SHT_MIPS_OPTIONS,
+ ELF::SHF_ALLOC |ELF::SHF_MIPS_NOSTRIP,
+ SectionKind::getMetadata());
+ else
+ ReginfoSection =
+ getContext().getELFSection(".reginfo",
+ ELF::SHT_MIPS_REGINFO,
+ ELF::SHF_ALLOC,
+ SectionKind::getMetadata());
}
// A address must be loaded from a small section if its size is less than the
class MipsTargetObjectFile : public TargetLoweringObjectFileELF {
const MCSection *SmallDataSection;
const MCSection *SmallBSSSection;
+ const MCSection *ReginfoSection;
public:
void Initialize(MCContext &Ctx, const TargetMachine &TM);
const TargetMachine &TM) const;
// TODO: Classify globals as mips wishes.
+ const MCSection *getReginfoSection() const { return ReginfoSection; }
};
} // end namespace llvm
--- /dev/null
+ ; RUN: llc -filetype=obj -march=mips64el -mcpu=mips64 %s -o - \
+ ; RUN: | elf-dump --dump-section-data | FileCheck --check-prefix=CHECK_64 %s
+ ; RUN: llc -filetype=obj -march=mipsel -mcpu=mips32 %s -o - \
+ ; RUN: | elf-dump --dump-section-data | FileCheck --check-prefix=CHECK_32 %s
+
+; Check for register information sections.
+;
+
+@str = private unnamed_addr constant [12 x i8] c"hello world\00"
+
+define i32 @main() nounwind {
+entry:
+; Check that the appropriate relocations were created.
+
+; check for .MIPS.options
+; CHECK_64: (('sh_name', 0x{{[0-9|a-f]+}}) # '.MIPS.options'
+; CHECK_64-NEXT: ('sh_type', 0x7000000d)
+; CHECK_64-NEXT: ('sh_flags', 0x0000000008000002)
+
+; check for .reginfo
+; CHECK_32: (('sh_name', 0x{{[0-9|a-f]+}}) # '.reginfo'
+; CHECK_32-NEXT: ('sh_type', 0x70000006)
+; CHECK_32-NEXT: ('sh_flags', 0x00000002)
+
+
+ %puts = tail call i32 @puts(i8* getelementptr inbounds ([12 x i8]* @str, i64 0, i64 0))
+ ret i32 0
+
+}
+declare i32 @puts(i8* nocapture) nounwind
+