mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
skeleton of a lowerCall implementation for ARM
llvm-svn: 29159
This commit is contained in:
parent
ff3dc2868c
commit
40073f5767
@ -156,9 +156,11 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
|
||||
assert(0 && "not implemented");
|
||||
abort();
|
||||
return;
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
assert(0 && "not implemented");
|
||||
abort();
|
||||
case MachineOperand::MO_GlobalAddress: {
|
||||
GlobalValue *GV = MO.getGlobal();
|
||||
std::string Name = Mang->getValueName(GV);
|
||||
O << Name;
|
||||
}
|
||||
break;
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
assert(0 && "not implemented");
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "ARM.h"
|
||||
#include "ARMTargetMachine.h"
|
||||
#include "llvm/CallingConv.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
@ -33,6 +34,7 @@ namespace {
|
||||
public:
|
||||
ARMTargetLowering(TargetMachine &TM);
|
||||
virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
|
||||
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
||||
};
|
||||
|
||||
}
|
||||
@ -42,9 +44,73 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::RET, MVT::Other, Custom);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
namespace ARMISD {
|
||||
enum NodeType {
|
||||
// Start the numbering where the builting ops and target ops leave off.
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END+ARM::INSTRUCTION_LIST_END,
|
||||
/// CALL - A direct function call.
|
||||
CALL
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
switch (Opcode) {
|
||||
default: return 0;
|
||||
case ARMISD::CALL: return "ARMISD::CALL";
|
||||
}
|
||||
}
|
||||
|
||||
// This transforms a ISD::CALL node into a
|
||||
// callseq_star <- ARMISD:CALL <- callseq_end
|
||||
// chain
|
||||
static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
assert(0 && "Not implemented");
|
||||
abort();
|
||||
SDOperand Chain = Op.getOperand(0);
|
||||
unsigned CallConv = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
|
||||
assert(CallConv == CallingConv::C && "unknown calling convention");
|
||||
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
|
||||
assert(isVarArg == false && "VarArg not supported");
|
||||
bool isTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
|
||||
assert(isTailCall == false && "tail call not supported");
|
||||
SDOperand Callee = Op.getOperand(4);
|
||||
unsigned NumOps = (Op.getNumOperands() - 5) / 2;
|
||||
assert(NumOps == 0);
|
||||
|
||||
// Count how many bytes are to be pushed on the stack. Initially
|
||||
// only the link register.
|
||||
unsigned NumBytes = 4;
|
||||
|
||||
// Adjust the stack pointer for the new arguments...
|
||||
// These operations are automatically eliminated by the prolog/epilog pass
|
||||
Chain = DAG.getCALLSEQ_START(Chain,
|
||||
DAG.getConstant(NumBytes, MVT::i32));
|
||||
|
||||
std::vector<MVT::ValueType> NodeTys;
|
||||
NodeTys.push_back(MVT::Other); // Returns a chain
|
||||
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
|
||||
|
||||
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
|
||||
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
|
||||
// node so that legalize doesn't hack it.
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
|
||||
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
|
||||
|
||||
// If this is a direct call, pass the chain and the callee.
|
||||
assert (Callee.Val);
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Chain);
|
||||
Ops.push_back(Callee);
|
||||
|
||||
unsigned CallOpc = ARMISD::CALL;
|
||||
Chain = DAG.getNode(CallOpc, NodeTys, Ops);
|
||||
|
||||
assert(Op.Val->getValueType(0) == MVT::Other);
|
||||
|
||||
Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
|
||||
DAG.getConstant(NumBytes, MVT::i32));
|
||||
|
||||
return Chain;
|
||||
}
|
||||
|
||||
static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
|
||||
|
@ -41,6 +41,10 @@ def SDT_ARMCallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>;
|
||||
def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARMCallSeq, [SDNPHasChain]>;
|
||||
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_ARMCallSeq, [SDNPHasChain]>;
|
||||
|
||||
def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
|
||||
def ARMcall : SDNode<"ARMISD::CALL", SDT_ARMcall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
|
||||
def ADJCALLSTACKUP : InstARM<(ops i32imm:$amt),
|
||||
"!ADJCALLSTACKUP $amt",
|
||||
[(callseq_end imm:$amt)]>;
|
||||
@ -51,6 +55,8 @@ def ADJCALLSTACKDOWN : InstARM<(ops i32imm:$amt),
|
||||
|
||||
def bxr: InstARM<(ops IntRegs:$dst), "bx $dst", [(brind IntRegs:$dst)]>;
|
||||
|
||||
def bl: InstARM<(ops i32imm:$func, variable_ops), "bl $func", [(ARMcall tglobaladdr:$func)]>;
|
||||
|
||||
def ldr : InstARM<(ops IntRegs:$dst, memri:$addr),
|
||||
"ldr $dst, [$addr]",
|
||||
[(set IntRegs:$dst, (load iaddr:$addr))]>;
|
||||
|
Loading…
Reference in New Issue
Block a user