From 43d526d162c69f29a1cc6734014576eade49529b Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Mon, 14 Jul 2008 14:42:54 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53551 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsAsmPrinter.cpp | 132 +++++++++++++++----------- lib/Target/Mips/MipsInstrInfo.cpp | 5 +- lib/Target/Mips/MipsInstrInfo.td | 71 +++++++------- lib/Target/Mips/MipsRegisterInfo.cpp | 22 +++-- lib/Target/Mips/MipsRegisterInfo.h | 9 +- lib/Target/Mips/MipsSubtarget.cpp | 24 ++++- lib/Target/Mips/MipsSubtarget.h | 23 ++++- lib/Target/Mips/MipsTargetAsmInfo.cpp | 24 ++--- lib/Target/Mips/MipsTargetMachine.cpp | 6 +- 9 files changed, 200 insertions(+), 116 deletions(-) diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 178ca141b0a..d2288e61a07 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -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(); + } 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); } diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 687237f9724..3a0e114fdcc 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -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; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 0e0af5d45a1..de5a53617df 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -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 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 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 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 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 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 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 op, bits<6> func, string instr_asm>: @@ -177,7 +178,7 @@ class LogicNOR 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 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 func, string instr_asm, SDNode OpNode>: @@ -195,7 +196,7 @@ class LogicR_shift_reg 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 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 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 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 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 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 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 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 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 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: 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 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 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 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 : @@ -345,7 +346,7 @@ class EffectiveAddress : class SignExtInReg 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 diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 75d9b24d7db..cd42abd3003 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -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:: diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 823461610d7..2d0436b7a61 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -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; diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 96ff30ba4a2..34243880114 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -15,23 +15,34 @@ #include "Mips.h" #include "MipsGenSubtarget.inc" #include "llvm/Module.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; +cl::opt NotABICall("disable-mips-abicall", cl::Hidden, + cl::desc("Disable code for SVR4-style dynamic objects")); +cl::opt 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; } diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 281f3bb1675..5140e1eb22d 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -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 diff --git a/lib/Target/Mips/MipsTargetAsmInfo.cpp b/lib/Target/Mips/MipsTargetAsmInfo.cpp index d69e78fe351..a4e13f5f345 100644 --- a/lib/Target/Mips/MipsTargetAsmInfo.cpp +++ b/lib/Target/Mips/MipsTargetAsmInfo.cpp @@ -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; } diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index a170d6fb36d..bc4a2a1dfc1 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -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); }