Added JumpTable support

Fixed some AsmPrinter issues
Added GLOBAL_OFFSET_TABLE Node handle.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44024 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bruno Cardoso Lopes 2007-11-12 19:49:57 +00:00
parent 62724da930
commit 753a98740b
6 changed files with 140 additions and 32 deletions

View File

@ -29,6 +29,7 @@
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SetVector.h"
@ -237,9 +238,8 @@ emitFunctionStart(MachineFunction &MF)
const Function *F = MF.getFunction();
SwitchToTextSection(getSectionForFunction(*F).c_str(), F);
// On Mips GAS, if .align #n is present, #n means the number of bits
// to be cleared. So, if we want 4 byte alignment, we must have .align 2
EmitAlignment(1, F);
// 2 bits aligned
EmitAlignment(2, F);
O << "\t.globl\t" << CurrentFnName << "\n";
O << "\t.ent\t" << CurrentFnName << "\n";
@ -280,6 +280,9 @@ runOnMachineFunction(MachineFunction &MF)
// Print out constants referenced by the function
EmitConstantPool(MF.getConstantPool());
// Print out jump tables referenced by the function
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
O << "\n\n";
// What's my mangled name?
@ -388,6 +391,11 @@ printOperand(const MachineInstr *MI, int opNum)
O << MO.getSymbolName();
break;
case MachineOperand::MO_JumpTableIndex:
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << MO.getJumpTableIndex();
break;
// FIXME: Verify correct
case MachineOperand::MO_ConstantPoolIndex:
O << TAI->getPrivateGlobalPrefix() << "CPI"
@ -450,19 +458,30 @@ doFinalization(Module &M)
std::string name = Mang->getValueName(I);
Constant *C = I->getInitializer();
unsigned Size = TD->getABITypeSize(C->getType());
unsigned Align = TD->getPrefTypeAlignment(C->getType());
unsigned Align = TD->getPreferredAlignmentLog(I);
// Is this correct ?
if (C->isNullValue() && (I->hasLinkOnceLinkage() ||
I->hasInternalLinkage() || I->hasWeakLinkage()
/* FIXME: Verify correct */)) {
I->hasInternalLinkage() || I->hasWeakLinkage()))
{
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
SwitchToDataSection(".data", I);
if (I->hasInternalLinkage())
O << "\t.local " << name << "\n";
if (!NoZerosInBSS && TAI->getBSSSection())
SwitchToDataSection(TAI->getBSSSection(), I);
else
SwitchToDataSection(TAI->getDataSection(), I);
O << "\t.comm " << name << ","
<< TD->getABITypeSize(C->getType())
<< "," << Align << "\n";
if (I->hasInternalLinkage()) {
if (TAI->getLCOMMDirective())
O << TAI->getLCOMMDirective() << name << "," << Size;
else
O << "\t.local\t" << name << "\n";
} else {
O << TAI->getCOMMDirective() << name << "," << Size;
// The .comm alignment in bytes.
if (TAI->getCOMMDirectiveTakesAlignment())
O << "," << (1 << Align);
}
} else {
@ -483,24 +502,37 @@ doFinalization(Module &M)
// something. For now, just emit them as external.
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol
O << "\t.globl " << name << "\n";
O << TAI->getGlobalDirective() << name << "\n";
// Fall Through
case GlobalValue::InternalLinkage:
if (C->isNullValue())
SwitchToDataSection(".bss", I);
else
SwitchToDataSection(".data", I);
// FIXME: special handling for ".ctors" & ".dtors" sections
if (I->hasSection() && (I->getSection() == ".ctors" ||
I->getSection() == ".dtors")) {
std::string SectionName = ".section " + I->getSection();
SectionName += ",\"aw\",%progbits";
SwitchToDataSection(SectionName.c_str());
} else {
if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection())
SwitchToDataSection(TAI->getBSSSection(), I);
else if (!I->isConstant())
SwitchToDataSection(TAI->getDataSection(), I);
else {
// Read-only data.
if (TAI->getReadOnlySection())
SwitchToDataSection(TAI->getReadOnlySection(), I);
else
SwitchToDataSection(TAI->getDataSection(), I);
}
}
break;
case GlobalValue::GhostLinkage:
cerr << "Should not have any"
<< "unmaterialized functions!\n";
cerr << "Should not have any unmaterialized functions!\n";
abort();
case GlobalValue::DLLImportLinkage:
cerr << "DLLImport linkage is"
<< "not supported by this target!\n";
cerr << "DLLImport linkage is not supported by this target!\n";
abort();
case GlobalValue::DLLExportLinkage:
cerr << "DLLExport linkage is"
<< "not supported by this target!\n";
cerr << "DLLExport linkage is not supported by this target!\n";
abort();
default:
assert(0 && "Unknown linkage type!");

View File

@ -78,6 +78,7 @@ private:
// Include the pieces autogenerated from the target description.
#include "MipsGenDAGISel.inc"
SDOperand getGlobalBaseReg();
SDNode *Select(SDOperand N);
// Complex Pattern.
@ -124,6 +125,23 @@ InstructionSelectBasicBlock(SelectionDAG &SD)
ScheduleAndEmitDAG(SD);
}
/// getGlobalBaseReg - Output the instructions required to put the
/// GOT address into a register.
SDOperand MipsDAGToDAGISel::getGlobalBaseReg()
{
MachineFunction* MF = BB->getParent();
unsigned GP = 0;
for(MachineFunction::livein_iterator ii = MF->livein_begin(),
ee = MF->livein_end(); ii != ee; ++ii)
if (ii->first == Mips::GP) {
GP = ii->second;
break;
}
assert(GP && "GOT PTR not in liveins");
return CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
GP, MVT::i32);
}
/// ComplexPattern used on MipsInstrInfo
/// Used on Mips Load/Store instructions
bool MipsDAGToDAGISel::
@ -138,7 +156,8 @@ SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base)
// on PIC code Load GA
if (TM.getRelocationModel() == Reloc::PIC_) {
if (Addr.getOpcode() == ISD::TargetGlobalAddress) {
if ((Addr.getOpcode() == ISD::TargetGlobalAddress) ||
(Addr.getOpcode() == ISD::TargetJumpTable)){
Base = CurDAG->getRegister(Mips::GP, MVT::i32);
Offset = Addr;
return true;
@ -253,6 +272,13 @@ Select(SDOperand N)
return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
}
// Get target GOT address.
case ISD::GLOBAL_OFFSET_TABLE: {
SDOperand Result = getGlobalBaseReg();
ReplaceUses(N, Result);
return NULL;
}
/// Handle direct and indirect calls when using PIC. On PIC, when
/// GOT is smaller than about 64k (small code) the GA target is
/// loaded with only one instruction. Otherwise GA's target must

View File

@ -55,6 +55,9 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
setSetCCResultType(MVT::i32);
setSetCCResultContents(ZeroOrOneSetCCResult);
// JumpTable targets must use GOT when using PIC_
setUsesGlobalOffsetTable(true);
// Set up the register classes
addRegisterClass(MVT::i32, Mips::CPURegsRegisterClass);
@ -62,6 +65,7 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::RET, MVT::Other, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
// Load extented operations for i1 types must be promoted
setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote);
@ -119,6 +123,7 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG)
case ISD::RET: return LowerRET(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
}
return SDOperand();
}
@ -175,6 +180,29 @@ LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG)
assert(0 && "TLS not implemented for MIPS.");
}
SDOperand MipsTargetLowering::
LowerJumpTable(SDOperand Op, SelectionDAG &DAG)
{
SDOperand ResNode;
SDOperand HiPart;
MVT::ValueType PtrVT = Op.getValueType();
JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
SDOperand JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
if (getTargetMachine().getRelocationModel() != Reloc::PIC_) {
const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32);
SDOperand Ops[] = { JTI };
HiPart = DAG.getNode(MipsISD::Hi, VTs, 1, Ops, 1);
} else // Emit Load from Global Pointer
HiPart = DAG.getLoad(MVT::i32, DAG.getEntryNode(), JTI, NULL, 0);
SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, JTI);
ResNode = DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo);
return ResNode;
}
//===----------------------------------------------------------------------===//
// Calling Convention Implementation
//
@ -346,13 +374,11 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
// location is used on function prologue to save GP and also after all
// emited CALL's to restore GP.
if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
// Function can have an arbitrary number of calls, so
// hold the LastStackLoc with the biggest offset.
int FI;
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
if (LastStackLoc >= MipsFI->getGPStackOffset()) {
LastStackLoc = (!LastStackLoc) ? (16) : (LastStackLoc+4);
// Create the frame index only once. SPOffset here can be anything
// (this will be fixed on processFunctionBeforeFrameFinalized)
@ -363,7 +389,6 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
MipsFI->setGPStackOffset(LastStackLoc);
}
// Reload GP value.
FI = MipsFI->getGPFI();
SDOperand FIN = DAG.getFrameIndex(FI,getPointerTy());
@ -455,6 +480,10 @@ LowerCCCArguments(SDOperand Op, SelectionDAG &DAG)
unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF);
// GP holds the GOT address on PIC calls.
if (getTargetMachine().getRelocationModel() == Reloc::PIC_)
AddLiveIn(MF, Mips::GP, Mips::CPURegsRegisterClass);
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);

View File

@ -76,6 +76,7 @@ namespace llvm {
SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG);
// Inline asm support
ConstraintType getConstraintType(const std::string &Constraint) const;

View File

@ -274,13 +274,13 @@ class JumpFR<bits<6> op, bits<6> func, string instr_asm>:
(outs),
(ins CPURegs:$target),
!strconcat(instr_asm, " $target"),
[], IIBranch>;
[(brind CPURegs:$target)], IIBranch>;
// Jump and Link (Call)
let isCall=1, hasDelaySlot=1,
// All calls clobber the non-callee saved registers...
Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2,
T3, T4, T5, T6, T7, T8, T9, K0, K1] in {
T3, T4, T5, T6, T7, T8, T9, K0, K1], Uses = [GP] in {
class JumpLink<bits<6> op, string instr_asm>:
FJ< op,
(outs),
@ -518,6 +518,10 @@ def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
(ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
def : Pat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>;
def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>;
def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)),
(ADDiu CPURegs:$hi, tjumptable:$lo)>;
// Mips does not have not, so we increase the operation
def : Pat<(not CPURegs:$in),

View File

@ -12,11 +12,27 @@
//===----------------------------------------------------------------------===//
#include "MipsTargetAsmInfo.h"
#include "MipsTargetMachine.h"
using namespace llvm;
MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM) {
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
CommentString = "#";
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";
GlobalDirective = "\t.globl\t";
LCOMMDirective = "\t.lcomm\t";
if (TM.getRelocationModel() == Reloc::Static)
JumpTableDirective = "\t.word\t";
else
JumpTableDirective = "\t.gpword\t";
COMMDirectiveTakesAlignment = true;
}