mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
[NVPTX] Fix handling of indirect calls
Using a special machine node is cleaner than an InlineAsm node, and fixes an assertion failure in InstrEmitter git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@194810 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0dd0d1af2b
commit
4d748eb0e4
@ -18,6 +18,7 @@
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
@ -277,3 +278,12 @@ void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
|
||||
printOperand(MI, OpNum + 1, O);
|
||||
}
|
||||
}
|
||||
|
||||
void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum,
|
||||
raw_ostream &O, const char *Modifier) {
|
||||
const MCOperand &Op = MI->getOperand(OpNum);
|
||||
assert(Op.isExpr() && "Call prototype is not an MCExpr?");
|
||||
const MCExpr *Expr = Op.getExpr();
|
||||
const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
|
||||
O << Sym.getName();
|
||||
}
|
||||
|
@ -44,7 +44,8 @@ public:
|
||||
raw_ostream &O, const char *Modifier = 0);
|
||||
void printMemOperand(const MCInst *MI, int OpNum,
|
||||
raw_ostream &O, const char *Modifier = 0);
|
||||
|
||||
void printProtoIdent(const MCInst *MI, int OpNum,
|
||||
raw_ostream &O, const char *Modifier = 0);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -314,6 +314,14 @@ void NVPTXAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
void NVPTXAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
|
||||
OutMI.setOpcode(MI->getOpcode());
|
||||
|
||||
// Special: Do not mangle symbol operand of CALL_PROTOTYPE
|
||||
if (MI->getOpcode() == NVPTX::CALL_PROTOTYPE) {
|
||||
const MachineOperand &MO = MI->getOperand(0);
|
||||
OutMI.addOperand(GetSymbolRef(MO,
|
||||
OutContext.GetOrCreateSymbol(Twine(MO.getSymbolName()))));
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
const MachineOperand &MO = MI->getOperand(i);
|
||||
|
||||
|
@ -310,6 +310,8 @@ const char *NVPTXTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
return "NVPTXISD::CallSeqBegin";
|
||||
case NVPTXISD::CallSeqEnd:
|
||||
return "NVPTXISD::CallSeqEnd";
|
||||
case NVPTXISD::CallPrototype:
|
||||
return "NVPTXISD::CallPrototype";
|
||||
case NVPTXISD::LoadV2:
|
||||
return "NVPTXISD::LoadV2";
|
||||
case NVPTXISD::LoadV4:
|
||||
@ -885,18 +887,16 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
// proto_0 : .callprototype(.param .b32 _) _ (.param .b32 _);
|
||||
// to be emitted, and the label has to used as the last arg of call
|
||||
// instruction.
|
||||
// The prototype is embedded in a string and put as the operand for an
|
||||
// INLINEASM SDNode.
|
||||
SDVTList InlineAsmVTs = DAG.getVTList(MVT::Other, MVT::Glue);
|
||||
std::string proto_string =
|
||||
getPrototype(retTy, Args, Outs, retAlignment, CS);
|
||||
const char *asmstr = nvTM->getManagedStrPool()
|
||||
->getManagedString(proto_string.c_str())->c_str();
|
||||
SDValue InlineAsmOps[] = {
|
||||
Chain, DAG.getTargetExternalSymbol(asmstr, getPointerTy()),
|
||||
DAG.getMDNode(0), DAG.getTargetConstant(0, MVT::i32), InFlag
|
||||
// The prototype is embedded in a string and put as the operand for a
|
||||
// CallPrototype SDNode which will print out to the value of the string.
|
||||
SDVTList ProtoVTs = DAG.getVTList(MVT::Other, MVT::Glue);
|
||||
std::string Proto = getPrototype(retTy, Args, Outs, retAlignment, CS);
|
||||
const char *ProtoStr =
|
||||
nvTM->getManagedStrPool()->getManagedString(Proto.c_str())->c_str();
|
||||
SDValue ProtoOps[] = {
|
||||
Chain, DAG.getTargetExternalSymbol(ProtoStr, MVT::i32), InFlag,
|
||||
};
|
||||
Chain = DAG.getNode(ISD::INLINEASM, dl, InlineAsmVTs, InlineAsmOps, 5);
|
||||
Chain = DAG.getNode(NVPTXISD::CallPrototype, dl, ProtoVTs, &ProtoOps[0], 3);
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
// Op to just print "call"
|
||||
|
@ -49,6 +49,7 @@ enum NodeType {
|
||||
RETURN,
|
||||
CallSeqBegin,
|
||||
CallSeqEnd,
|
||||
CallPrototype,
|
||||
Dummy,
|
||||
|
||||
LoadV2 = ISD::FIRST_TARGET_MEMORY_OPCODE,
|
||||
|
@ -2607,6 +2607,20 @@ def trapinst : NVPTXInst<(outs), (ins),
|
||||
"trap;",
|
||||
[(trap)]>;
|
||||
|
||||
// Call prototype wrapper
|
||||
def SDTCallPrototype : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
||||
def CallPrototype
|
||||
: SDNode<"NVPTXISD::CallPrototype", SDTCallPrototype,
|
||||
[SDNPHasChain, SDNPOutGlue, SDNPInGlue, SDNPSideEffect]>;
|
||||
def ProtoIdent : Operand<i32> {
|
||||
let PrintMethod = "printProtoIdent";
|
||||
}
|
||||
def CALL_PROTOTYPE
|
||||
: NVPTXInst<(outs), (ins ProtoIdent:$ident),
|
||||
"$ident", [(CallPrototype (i32 texternalsym:$ident))]>;
|
||||
|
||||
|
||||
|
||||
include "NVPTXIntrinsics.td"
|
||||
|
||||
|
||||
|
10
test/CodeGen/NVPTX/callchain.ll
Normal file
10
test/CodeGen/NVPTX/callchain.ll
Normal file
@ -0,0 +1,10 @@
|
||||
; RUN: llc < %s -march=nvptx -mcpu=sm_20 | FileCheck %s
|
||||
|
||||
target triple = "nvptx"
|
||||
|
||||
define void @foo(i8* %ptr) {
|
||||
%fnptr = bitcast i8* %ptr to void ()*
|
||||
; CHECK: prototype_0 : .callprototype ()_ ()
|
||||
tail call void %fnptr()
|
||||
ret void
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user