Added Subtarget support into RegisterInfo

Added HasABICall and HasAbsoluteCall (equivalent to gcc -mabicall and 
-mno-shared). HasAbsoluteCall is not implemented but HasABICall is the 
default for o32 ABI. Now, both should help into a more accurate 
relocation types implementation. 
Added IsLinux is needed to choose between asm directives.
Instruction name strings cleanup.
AsmPrinter improved.

llvm-svn: 53551
This commit is contained in:
Bruno Cardoso Lopes 2008-07-14 14:42:54 +00:00
parent a696ca66e9
commit 80ab8f9649
9 changed files with 200 additions and 116 deletions

View File

@ -15,6 +15,7 @@
#define DEBUG_TYPE "mips-asm-printer"
#include "Mips.h"
#include "MipsSubtarget.h"
#include "MipsInstrInfo.h"
#include "MipsTargetMachine.h"
#include "MipsMachineFunction.h"
@ -44,21 +45,19 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed");
namespace {
struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
const MipsSubtarget *Subtarget;
MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM,
const TargetAsmInfo *T):
AsmPrinter(O, TM, T) {}
AsmPrinter(O, TM, T) {
Subtarget = &TM.getSubtarget<MipsSubtarget>();
}
virtual const char *getPassName() const {
return "Mips Assembly Printer";
}
enum SetDirectiveFlags {
REORDER, // enables instruction reordering.
NOREORDER, // disables instruction reordering.
MACRO, // enables GAS macros.
NOMACRO // disables GAS macros.
};
void printOperand(const MachineInstr *MI, int opNum);
void printMemOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
@ -68,13 +67,13 @@ namespace {
unsigned int getSavedRegsBitmask(bool isFloat, MachineFunction &MF);
void printHex32(unsigned int Value);
const char *emitCurrentABIString(void);
void emitFunctionStart(MachineFunction &MF);
void emitFunctionEnd(MachineFunction &MF);
void emitFrameDirective(MachineFunction &MF);
void emitMaskDirective(MachineFunction &MF);
void emitFMaskDirective(MachineFunction &MF);
void emitSetDirective(SetDirectiveFlags Flag);
bool printInstruction(const MachineInstr *MI); // autogenerated.
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
@ -125,6 +124,10 @@ FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o,
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Mask directives
//===----------------------------------------------------------------------===//
/// Mask directive for GPR
void MipsAsmPrinter::
emitMaskDirective(MachineFunction &MF)
@ -159,37 +162,6 @@ emitFMaskDirective(MachineFunction &MF)
O << ",0" << "\n";
}
/// Frame Directive
void MipsAsmPrinter::
emitFrameDirective(MachineFunction &MF)
{
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
unsigned stackReg = RI.getFrameRegister(MF);
unsigned returnReg = RI.getRARegister();
unsigned stackSize = MF.getFrameInfo()->getStackSize();
O << "\t.frame\t" << "$" << LowercaseString(RI.get(stackReg).AsmName)
<< "," << stackSize << ","
<< "$" << LowercaseString(RI.get(returnReg).AsmName)
<< "\n";
}
/// Emit Set directives.
void MipsAsmPrinter::
emitSetDirective(SetDirectiveFlags Flag)
{
O << "\t.set\t";
switch(Flag) {
case REORDER: O << "reorder" << "\n"; break;
case NOREORDER: O << "noreorder" << "\n"; break;
case MACRO: O << "macro" << "\n"; break;
case NOMACRO: O << "nomacro" << "\n"; break;
default: break;
}
}
// Create a bitmask with all callee saved registers for CPU
// or Floating Point registers. For CPU registers consider RA,
// GP and FP for saving if necessary.
@ -231,6 +203,44 @@ printHex32(unsigned int Value)
O << std::dec;
}
//===----------------------------------------------------------------------===//
// Frame and Set directives
//===----------------------------------------------------------------------===//
/// Frame Directive
void MipsAsmPrinter::
emitFrameDirective(MachineFunction &MF)
{
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
unsigned stackReg = RI.getFrameRegister(MF);
unsigned returnReg = RI.getRARegister();
unsigned stackSize = MF.getFrameInfo()->getStackSize();
O << "\t.frame\t" << "$" << LowercaseString(RI.get(stackReg).AsmName)
<< "," << stackSize << ","
<< "$" << LowercaseString(RI.get(returnReg).AsmName)
<< "\n";
}
/// Emit Set directives.
const char * MipsAsmPrinter::
emitCurrentABIString(void)
{
switch(Subtarget->getTargetABI()) {
case MipsSubtarget::O32: return "abi32";
case MipsSubtarget::O64: return "abiO64";
case MipsSubtarget::N32: return "abiN32";
case MipsSubtarget::N64: return "abi64";
case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64
default: break;
}
assert(0 && "Unknown Mips ABI");
return NULL;
}
/// Emit the directives used by GAS on the start of functions
void MipsAsmPrinter::
emitFunctionStart(MachineFunction &MF)
@ -244,18 +254,16 @@ emitFunctionStart(MachineFunction &MF)
O << "\t.globl\t" << CurrentFnName << "\n";
O << "\t.ent\t" << CurrentFnName << "\n";
O << "\t.type\t" << CurrentFnName << ", @function\n";
if ((TAI->hasDotTypeDotSizeDirective()) && Subtarget->isLinux())
O << "\t.type\t" << CurrentFnName << ", @function\n";
O << CurrentFnName << ":\n";
emitFrameDirective(MF);
emitMaskDirective(MF);
emitFMaskDirective(MF);
if (TM.getRelocationModel() == Reloc::Static) {
emitSetDirective(NOREORDER);
emitSetDirective(NOMACRO);
}
O << "\n";
}
@ -263,12 +271,15 @@ emitFunctionStart(MachineFunction &MF)
void MipsAsmPrinter::
emitFunctionEnd(MachineFunction &MF)
{
if (TM.getRelocationModel() == Reloc::Static) {
emitSetDirective(MACRO);
emitSetDirective(REORDER);
}
// There are instruction for this macros, but they must
// always be at the function end, and we can't emit and
// break with BB logic.
O << "\t.set\tmacro\n";
O << "\t.set\treorder\n";
O << "\t.end\t" << CurrentFnName << "\n";
if (TAI->hasDotTypeDotSizeDirective() && !Subtarget->isLinux())
O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << "\n";
}
/// runOnMachineFunction - This uses the printMachineInstruction()
@ -441,6 +452,18 @@ bool MipsAsmPrinter::
doInitialization(Module &M)
{
Mang = new Mangler(M);
// Tell the assembler which ABI we are using
O << "\t.section .mdebug." << emitCurrentABIString() << "\n";
// TODO: handle O64 ABI
if (Subtarget->isABI_EABI())
O << "\t.section .gcc_compiled_long" <<
(Subtarget->isGP32bit() ? "32" : "64") << "\n";
// return to previous section
O << "\t.previous" << "\n";
return false; // success
}
@ -548,8 +571,11 @@ doFinalization(Module &M)
}
O << "\t.align " << Align << "\n";
O << "\t.type " << name << ",@object\n";
O << "\t.size " << name << "," << Size << "\n";
if (TAI->hasDotTypeDotSizeDirective()) {
O << "\t.type " << name << ",@object\n";
O << "\t.size " << name << "," << Size << "\n";
}
O << name << ":\n";
EmitGlobalConstant(C);
}

View File

@ -11,8 +11,9 @@
//
//===----------------------------------------------------------------------===//
#include "Mips.h"
//#include "Mips.h"
#include "MipsInstrInfo.h"
#include "MipsTargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "MipsGenInstrInfo.inc"
@ -21,7 +22,7 @@ using namespace llvm;
MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm)
: TargetInstrInfoImpl(MipsInsts, array_lengthof(MipsInsts)),
TM(tm), RI(*this) {}
TM(tm), RI(*TM.getSubtargetImpl(), *this) {}
static bool isZeroImm(const MachineOperand &op) {
return op.isImmediate() && op.getImm() == 0;

View File

@ -31,7 +31,8 @@ def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
// Hi and Lo nodes are used to handle global addresses. Used on
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
// static model. (nothing to do with Mips Registers Hi and Lo)
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
//def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>;
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
// Return
@ -125,7 +126,7 @@ class ArithR<bits<6> op, bits<6> func, string instr_asm, SDNode OpNode,
func,
(outs CPURegs:$dst),
(ins CPURegs:$b, CPURegs:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>;
let isCommutable = 1 in
@ -134,7 +135,7 @@ class ArithOverflowR<bits<6> op, bits<6> func, string instr_asm>:
func,
(outs CPURegs:$dst),
(ins CPURegs:$b, CPURegs:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[], IIAlu>;
// Arithmetic 2 register operands
@ -143,7 +144,7 @@ class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
FI< op,
(outs CPURegs:$dst),
(ins CPURegs:$b, Od:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>;
// Arithmetic Multiply ADD/SUB
@ -153,7 +154,7 @@ class MArithR<bits<6> func, string instr_asm> :
func,
(outs CPURegs:$rs),
(ins CPURegs:$rt),
!strconcat(instr_asm, " $rs, $rt"),
!strconcat(instr_asm, "\t$rs, $rt"),
[], IIImul>;
// Logical
@ -162,14 +163,14 @@ class LogicR<bits<6> func, string instr_asm, SDNode OpNode>:
func,
(outs CPURegs:$dst),
(ins CPURegs:$b, CPURegs:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>;
class LogicI<bits<6> op, string instr_asm, SDNode OpNode>:
FI< op,
(outs CPURegs:$dst),
(ins CPURegs:$b, uimm16:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>;
class LogicNOR<bits<6> op, bits<6> func, string instr_asm>:
@ -177,7 +178,7 @@ class LogicNOR<bits<6> op, bits<6> func, string instr_asm>:
func,
(outs CPURegs:$dst),
(ins CPURegs:$b, CPURegs:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>;
// Shifts
@ -187,7 +188,7 @@ class LogicR_shift_imm<bits<6> func, string instr_asm, SDNode OpNode>:
func,
(outs CPURegs:$dst),
(ins CPURegs:$b, shamt:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu>;
class LogicR_shift_reg<bits<6> func, string instr_asm, SDNode OpNode>:
@ -195,7 +196,7 @@ class LogicR_shift_reg<bits<6> func, string instr_asm, SDNode OpNode>:
func,
(outs CPURegs:$dst),
(ins CPURegs:$b, CPURegs:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>;
// Load Upper Imediate
@ -203,7 +204,7 @@ class LoadUpper<bits<6> op, string instr_asm>:
FI< op,
(outs CPURegs:$dst),
(ins uimm16:$imm),
!strconcat(instr_asm, " $dst, $imm"),
!strconcat(instr_asm, "\t$dst, $imm"),
[], IIAlu>;
// Memory Load/Store
@ -212,14 +213,14 @@ class LoadM<bits<6> op, string instr_asm, PatFrag OpNode>:
FI< op,
(outs CPURegs:$dst),
(ins mem:$addr),
!strconcat(instr_asm, " $dst, $addr"),
!strconcat(instr_asm, "\t$dst, $addr"),
[(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>;
class StoreM<bits<6> op, string instr_asm, PatFrag OpNode>:
FI< op,
(outs),
(ins CPURegs:$dst, mem:$addr),
!strconcat(instr_asm, " $dst, $addr"),
!strconcat(instr_asm, "\t$dst, $addr"),
[(OpNode CPURegs:$dst, addr:$addr)], IIStore>;
// Conditional Branch
@ -228,7 +229,7 @@ class CBranch<bits<6> op, string instr_asm, PatFrag cond_op>:
FI< op,
(outs),
(ins CPURegs:$a, CPURegs:$b, brtarget:$offset),
!strconcat(instr_asm, " $a, $b, $offset"),
!strconcat(instr_asm, "\t$a, $b, $offset"),
[(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)],
IIBranch>;
@ -237,7 +238,7 @@ class CBranchZero<bits<6> op, string instr_asm, PatFrag cond_op>:
FI< op,
(outs),
(ins CPURegs:$src, brtarget:$offset),
!strconcat(instr_asm, " $src, $offset"),
!strconcat(instr_asm, "\t$src, $offset"),
[(brcond (cond_op CPURegs:$src, 0), bb:$offset)],
IIBranch>;
}
@ -249,7 +250,7 @@ class SetCC_R<bits<6> op, bits<6> func, string instr_asm,
func,
(outs CPURegs:$dst),
(ins CPURegs:$b, CPURegs:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))],
IIAlu>;
@ -258,7 +259,7 @@ class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op,
FI< op,
(outs CPURegs:$dst),
(ins CPURegs:$b, Od:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))],
IIAlu>;
@ -268,7 +269,7 @@ class JumpFJ<bits<6> op, string instr_asm>:
FJ< op,
(outs),
(ins brtarget:$target),
!strconcat(instr_asm, " $target"),
!strconcat(instr_asm, "\t$target"),
[(br bb:$target)], IIBranch>;
let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in
@ -277,7 +278,7 @@ class JumpFR<bits<6> op, bits<6> func, string instr_asm>:
func,
(outs),
(ins CPURegs:$target),
!strconcat(instr_asm, " $target"),
!strconcat(instr_asm, "\t$target"),
[(brind CPURegs:$target)], IIBranch>;
// Jump and Link (Call)
@ -289,7 +290,7 @@ let isCall=1, hasDelaySlot=1,
FJ< op,
(outs),
(ins calltarget:$target),
!strconcat(instr_asm, " $target"),
!strconcat(instr_asm, "\t$target"),
[(MipsJmpLink imm:$target)], IIBranch>;
let rd=31 in
@ -298,14 +299,14 @@ let isCall=1, hasDelaySlot=1,
func,
(outs),
(ins CPURegs:$rs),
!strconcat(instr_asm, " $rs"),
!strconcat(instr_asm, "\t$rs"),
[(MipsJmpLink CPURegs:$rs)], IIBranch>;
class BranchLink<string instr_asm>:
FI< 0x1,
(outs),
(ins CPURegs:$rs, brtarget:$target),
!strconcat(instr_asm, " $rs, $target"),
!strconcat(instr_asm, "\t$rs, $target"),
[], IIBranch>;
}
@ -315,7 +316,7 @@ class MulDiv<bits<6> func, string instr_asm, InstrItinClass itin>:
func,
(outs),
(ins CPURegs:$a, CPURegs:$b),
!strconcat(instr_asm, " $a, $b"),
!strconcat(instr_asm, "\t$a, $b"),
[], itin>;
// Move from Hi/Lo
@ -324,7 +325,7 @@ class MoveFromTo<bits<6> func, string instr_asm>:
func,
(outs CPURegs:$dst),
(ins),
!strconcat(instr_asm, " $dst"),
!strconcat(instr_asm, "\t$dst"),
[], IIHiLo>;
// Count Leading Ones/Zeros in Word
@ -333,7 +334,7 @@ class CountLeading<bits<6> func, string instr_asm>:
func,
(outs CPURegs:$dst),
(ins CPURegs:$src),
!strconcat(instr_asm, " $dst, $src"),
!strconcat(instr_asm, "\t$dst, $src"),
[], IIAlu>;
class EffectiveAddress<string instr_asm> :
@ -345,7 +346,7 @@ class EffectiveAddress<string instr_asm> :
class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>:
FR< 0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src),
!strconcat(instr_asm, " $dst, $src"),
!strconcat(instr_asm, "\t$dst, $src"),
[(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>;
@ -363,15 +364,19 @@ def ADJCALLSTACKUP : MipsPseudo<(outs), (ins uimm16:$amt1, uimm16:$amt2),
[(callseq_end imm:$amt1, imm:$amt2)]>;
}
// Some assembly macros need to avoid pseudoinstructions and assembler
// automatic reodering, we should reorder ourselves.
def MACRO : MipsPseudo<(outs), (ins), ".set\tmacro", []>;
def REORDER : MipsPseudo<(outs), (ins), ".set\treorder", []>;
def NOMACRO : MipsPseudo<(outs), (ins), ".set\tnomacro", []>;
def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>;
// When handling PIC code the assembler needs .cpload and .cprestore
// directives. If the real instructions corresponding these directives
// are used, we have the same behavior, but get also a bunch of warnings
// from the assembler.
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$reg),
".set noreorder\n\t.cpload $reg\n\t.set reorder\n",
[]>;
def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc),
".cprestore $loc\n", []>;
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>;
def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>;
// The supported Mips ISAs dont have any instruction close to the SELECT_CC
// operation. The solution is to create a Mips pseudo SELECT_CC instruction
@ -488,14 +493,14 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1,
isBarrier=1, hasCtrlDep=1, rs=0, rt=0, shamt=0 in
{
def RET : FR <0x00, 0x02, (outs), (ins CPURegs:$target),
"jr $target", [(MipsRet CPURegs:$target)], IIBranch>;
"jr\t$target", [(MipsRet CPURegs:$target)], IIBranch>;
}
// FrameIndexes are legalized when they are operands from load/store
// instructions. The same not happens for stack address copies, so an
// add op with mem ComplexPattern is used and the stack address copy
// can be matched. It's similar to Sparc LEA_ADDRi
def LEA_ADDiu : EffectiveAddress<"addiu $dst, ${addr:stackloc}">;
def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, ${addr:stackloc}">;
// Count Leading
// CLO/CLZ are part of the newer MIPS32(tm) instruction

View File

@ -14,6 +14,7 @@
#define DEBUG_TYPE "mips-reg-info"
#include "Mips.h"
#include "MipsSubtarget.h"
#include "MipsRegisterInfo.h"
#include "MipsMachineFunction.h"
#include "llvm/Constants.h"
@ -35,9 +36,10 @@
using namespace llvm;
MipsRegisterInfo::MipsRegisterInfo(const TargetInstrInfo &tii)
MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST,
const TargetInstrInfo &tii)
: MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP),
TII(tii) {}
Subtarget(ST), TII(tii) {}
/// getRegisterNumbering - Given the enum value for some register, e.g.
/// Mips::RA, return the number that it corresponds to (e.g. 31).
@ -82,10 +84,10 @@ getRegisterNumbering(unsigned RegEnum)
return 0; // Not reached
}
unsigned MipsRegisterInfo::getPICCallReg(void) { return Mips::T9; }
//===----------------------------------------------------------------------===//
//
// Callee Saved Registers methods
//
//===----------------------------------------------------------------------===//
/// Mips Callee Saved Registers
@ -306,9 +308,12 @@ emitPrologue(MachineFunction &MF) const
// Update frame info
MFI->setStackSize(NumBytes);
// PIC speficic function prologue
if (isPIC)
BuildMI(MBB, MBBI, TII.get(Mips::CPLOAD)).addReg(Mips::T9);
BuildMI(MBB, MBBI, TII.get(Mips::NOREORDER));
// TODO: check need from GP here.
if (isPIC && Subtarget.isABI_O32())
BuildMI(MBB, MBBI, TII.get(Mips::CPLOAD)).addReg(getPICCallReg());
BuildMI(MBB, MBBI, TII.get(Mips::NOMACRO));
// Adjust stack : addi sp, sp, (-imm)
BuildMI(MBB, MBBI, TII.get(Mips::ADDiu), Mips::SP)
@ -334,9 +339,10 @@ emitPrologue(MachineFunction &MF) const
}
// PIC speficic function prologue
if ((isPIC) && (MFI->hasCalls()))
if ((isPIC) && (MFI->hasCalls())) {
BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE))
.addImm(MipsFI->getGPStackOffset());
}
}
void MipsRegisterInfo::

View File

@ -14,23 +14,28 @@
#ifndef MIPSREGISTERINFO_H
#define MIPSREGISTERINFO_H
#include "Mips.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "MipsGenRegisterInfo.h.inc"
namespace llvm {
class MipsSubtarget;
class TargetInstrInfo;
class Type;
struct MipsRegisterInfo : public MipsGenRegisterInfo {
const MipsSubtarget &Subtarget;
const TargetInstrInfo &TII;
MipsRegisterInfo(const TargetInstrInfo &tii);
MipsRegisterInfo(const MipsSubtarget &Subtarget, const TargetInstrInfo &tii);
/// getRegisterNumbering - Given the enum value for some register, e.g.
/// Mips::RA, return the number that it corresponds to (e.g. 31).
static unsigned getRegisterNumbering(unsigned RegEnum);
/// Get PIC indirect call register
static unsigned getPICCallReg(void);
/// Code Generation virtual methods...
const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;

View File

@ -15,23 +15,34 @@
#include "Mips.h"
#include "MipsGenSubtarget.inc"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
cl::opt<bool> NotABICall("disable-mips-abicall", cl::Hidden,
cl::desc("Disable code for SVR4-style dynamic objects"));
cl::opt<bool> AbsoluteCall("enable-mips-absolute-call", cl::Hidden,
cl::desc("Enable absolute call within abicall"));
MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
const std::string &FS, bool little) :
MipsArchVersion(Mips1), MipsABI(O32), IsLittle(little), IsSingleFloat(false),
IsFP64bit(false), IsGP64bit(false), HasVFPU(false), HasSEInReg(false)
IsFP64bit(false), IsGP64bit(false), HasVFPU(false), HasSEInReg(false),
HasABICall(true), HasAbsoluteCall(false), IsLinux(true)
{
std::string CPU = "mips1";
// Parse features string.
ParseSubtargetFeatures(FS, CPU);
const std::string& TT = M.getTargetTriple();
// Is the target system Linux ?
if (TT.find("linux") == std::string::npos)
IsLinux = false;
// When only the target triple is specified and is
// a allegrex target, set the features. We also match
// big and little endian allegrex cores (dont really
// know if a big one exists)
const std::string& TT = M.getTargetTriple();
if (TT.find("mipsallegrex") != std::string::npos) {
MipsABI = EABI;
IsSingleFloat = true;
@ -39,4 +50,13 @@ MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
HasVFPU = true; // Enables Allegrex Vector FPU (not supported yet)
HasSEInReg = true;
}
// Abicall is the default for O32 ABI and is ignored
// for EABI.
if (NotABICall || isABI_EABI())
HasABICall = false;
// TODO: disable when handling 64 bit symbols in the future.
if (HasABICall && AbsoluteCall)
HasAbsoluteCall = true;
}

View File

@ -24,16 +24,17 @@ class Module;
class MipsSubtarget : public TargetSubtarget {
public:
enum MipsABIEnum {
O32, O64, N32, N64, EABI
};
protected:
enum MipsArchEnum {
Mips1, Mips2, Mips3, Mips4, Mips32, Mips32r2, Mips64, Mips64r2
};
enum MipsABIEnum {
O32, EABI
};
// Mips architecture version
MipsArchEnum MipsArchVersion;
@ -60,6 +61,16 @@ protected:
// HasSEInReg - Target has SEB and SEH (signext in register) instructions.
bool HasSEInReg;
// IsABICall - Enable SRV4 code for SVR4-style dynamic objects
bool HasABICall;
// HasAbsoluteCall - Enable code that is not fully position-independent.
// Only works with HasABICall enabled.
bool HasAbsoluteCall;
// isLinux - Target system is Linux. Is false we consider ELFOS for now.
bool IsLinux;
InstrItineraryData InstrItins;
public:
@ -67,6 +78,7 @@ public:
/// Only O32 and EABI supported right now.
bool isABI_EABI() const { return MipsABI == EABI; }
bool isABI_O32() const { return MipsABI == O32; }
unsigned getTargetABI() const { return MipsABI; }
/// This constructor initializes the data members to match that
/// of the specified module.
@ -87,6 +99,9 @@ public:
bool isNotSingleFloat() const { return !IsSingleFloat; };
bool hasVFPU() const { return HasVFPU; };
bool hasSEInReg() const { return HasSEInReg; };
bool hasABICall() const { return HasABICall; };
bool hasAbsoluteCall() const { return HasAbsoluteCall; };
bool isLinux() const { return IsLinux; };
};
} // End llvm namespace

View File

@ -17,21 +17,23 @@
using namespace llvm;
MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM) {
AlignmentIsInBytes = false;
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
PrivateGlobalPrefix = "$";
JumpTableDataSection = "\t.rdata";
CommentString = "#";
ReadOnlySection = "\t.rdata";
ZeroDirective = "\t.space\t";
BSSSection = "\t.section\t.bss";
LCOMMDirective = "\t.lcomm\t";
AlignmentIsInBytes = false;
COMMDirectiveTakesAlignment = true;
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
Data64bitsDirective = NULL;
PrivateGlobalPrefix = "$";
JumpTableDataSection = "\t.rdata";
CommentString = "#";
ReadOnlySection = "\t.rdata";
ZeroDirective = "\t.space\t";
BSSSection = "\t.section\t.bss";
LCOMMDirective = "\t.lcomm\t";
if (TM.getRelocationModel() == Reloc::Static)
JumpTableDirective = "\t.word\t";
else
JumpTableDirective = "\t.gpword\t";
COMMDirectiveTakesAlignment = true;
}

View File

@ -44,8 +44,12 @@ MipsTargetMachine(const Module &M, const std::string &FS, bool isLittle=false):
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0),
TLInfo(*this)
{
if (getRelocationModel() != Reloc::Static)
// Abicall enables PIC by default
if (Subtarget.hasABICall() && (getRelocationModel() != Reloc::Static))
setRelocationModel(Reloc::PIC_);
// TODO: create an option to enable long calls, like -mlong-calls,
// that would be our CodeModel::Large. It must not work with Abicall.
if (getCodeModel() == CodeModel::Default)
setCodeModel(CodeModel::Small);
}