mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-08 06:32:24 +00:00
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:
parent
62724da930
commit
753a98740b
@ -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!");
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user