From: Duraid Madina Date: Thu, 22 Dec 2005 13:29:14 +0000 (+0000) Subject: this is a hack, which may or may not hang around. In short: X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=64aa0ea4e9a9a076e95be8b493b3cbe1cbfde9a7;p=oota-llvm.git this is a hack, which may or may not hang around. In short: whimper out of doing things the Right Way, and hack up a generic 'BRCALL' instruction, that gets generated when calls are lowered. This gets selected by hand in the DAG isel, where it gets turned into real (i.e. in tablegen) br.call instructions. BUG: this dies on void calls, but seems to work otherwise? git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24952 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/IA64/IA64ISelDAGToDAG.cpp b/lib/Target/IA64/IA64ISelDAGToDAG.cpp index 177365081fd..8d5561b1cd7 100644 --- a/lib/Target/IA64/IA64ISelDAGToDAG.cpp +++ b/lib/Target/IA64/IA64ISelDAGToDAG.cpp @@ -342,6 +342,73 @@ SDOperand IA64DAGToDAGISel::Select(SDOperand Op) { default: break; case ISD::Register: return Op; // XXX: this is a hack, tblgen one day? + + case IA64ISD::BRCALL: { // XXX: this is also a hack! + SDOperand Chain = Select(N->getOperand(0)); + SDOperand InFlag; // Null incoming flag value. + + if(N->getNumOperands()==3) // we have an incoming chain, callee and flag + InFlag = Select(N->getOperand(2)); + + unsigned CallOpcode; + SDOperand CallOperand; + std::vector TypeOperands; + + // if we can call directly, do so + if (GlobalAddressSDNode *GASD = + dyn_cast(N->getOperand(1))) { + CallOpcode = IA64::BRCALL_IPREL_GA; + CallOperand = CurDAG->getTargetGlobalAddress(GASD->getGlobal(), MVT::i64); + } else if (ExternalSymbolSDNode *ESSDN = // FIXME: we currently NEED this + // case for correctness, to avoid + // "non-pic code with imm reloc.n + // against dynamic symbol" errors + dyn_cast(N->getOperand(1))) { + CallOpcode = IA64::BRCALL_IPREL_ES; + CallOperand = N->getOperand(1); + } else { + // otherwise we need to load the function descriptor, + // load the branch target (function)'s entry point and GP, + // branch (call) then restore the GP + SDOperand FnDescriptor = Select(N->getOperand(1)); + + // load the branch target's entry point [mem] and + // GP value [mem+8] + SDOperand targetEntryPoint=CurDAG->getTargetNode(IA64::LD8, MVT::i64, + FnDescriptor); + Chain = targetEntryPoint.getValue(1); + SDOperand targetGPAddr=CurDAG->getTargetNode(IA64::ADDS, MVT::i64, + FnDescriptor, CurDAG->getConstant(8, MVT::i64)); + Chain = targetGPAddr.getValue(1); + SDOperand targetGP=CurDAG->getTargetNode(IA64::LD8, MVT::i64, + targetGPAddr); + Chain = targetGP.getValue(1); + + Chain = CurDAG->getCopyToReg(Chain, IA64::r1, targetGP, InFlag); + InFlag = Chain.getValue(1); + Chain = CurDAG->getCopyToReg(Chain, IA64::B6, targetEntryPoint, InFlag); // FLAG these? + InFlag = Chain.getValue(1); + + CallOperand = CurDAG->getRegister(IA64::B6, MVT::i64); + CallOpcode = IA64::BRCALL_INDIRECT; + } + + // Finally, once everything is setup, emit the call itself + if(InFlag.Val) + Chain = CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag, CallOperand, Chain, InFlag); + else // there might be no arguments + Chain = CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag, CallOperand, Chain); + InFlag = Chain.getValue(1); + + std::vector CallResults; + + CallResults.push_back(Chain); + CallResults.push_back(InFlag); + + for (unsigned i = 0, e = CallResults.size(); i != e; ++i) + CodeGenMap[Op.getValue(i)] = CallResults[i]; + return CallResults[Op.ResNo]; + } case IA64ISD::GETFD: { SDOperand Input = Select(N->getOperand(0)); diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp index adda64ec840..54ba3ef0d3c 100644 --- a/lib/Target/IA64/IA64ISelLowering.cpp +++ b/lib/Target/IA64/IA64ISelLowering.cpp @@ -291,6 +291,7 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, SDOperand StackPtr, NullSV; std::vector Stores; + std::vector Converts; std::vector RegValuesToPass; unsigned ArgOffset = 16; @@ -298,7 +299,7 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, { SDOperand Val = Args[i].first; MVT::ValueType ObjectVT = Val.getValueType(); - SDOperand ValToStore; + SDOperand ValToStore, ValToConvert; unsigned ObjSize=8; switch (ObjectVT) { default: assert(0 && "unexpected argument type!"); @@ -330,6 +331,9 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, ValToStore = Val; } else { RegValuesToPass.push_back(Val); + if(1 /* TODO: if(calling external or varadic function)*/ ) { + ValToConvert = Val; // additionally pass this FP value as an int + } } break; } @@ -344,6 +348,10 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, ValToStore, PtrOff, NullSV)); } + + if(ValToConvert.Val) { + Converts.push_back(DAG.getNode(IA64ISD::GETFD, MVT::i64, ValToConvert)); + } ArgOffset += ObjSize; } @@ -379,6 +387,17 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, // mapped 1:1 and the FP args into regs F8-F15 "lazily" // TODO: for performance, we should only copy FP args into int regs when we // know this is required (i.e. for varardic or external (unknown) functions) + + // first to the FP->(integer representation) conversions, these are + // free-floating + unsigned seenConverts = 0; + for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) { + if(MVT::isFloatingPoint(RegValuesToPass[i].getValueType())) { + Chain = DAG.getCopyToReg(Chain, IntArgRegs[i], Converts[seenConverts++]); + } + } + + // next copy args into the usual places unsigned usedFPArgs = 0; for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) { Chain = DAG.getCopyToReg(Chain, @@ -386,42 +405,34 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, IntArgRegs[i] : FPArgRegs[usedFPArgs++], RegValuesToPass[i], InFlag); InFlag = Chain.getValue(1); - - //FIXME: for performance, only do the following when required - - // if we have just copied an FP arg, copy its in-memory representation - // to the appropriate integer register - if(MVT::isFloatingPoint(RegValuesToPass[i].getValueType())) { - std::vector GETFDRetTypes; - std::vector GETFDOperands; - GETFDRetTypes.push_back(MVT::i64); - GETFDRetTypes.push_back(MVT::Flag); - GETFDOperands.push_back(RegValuesToPass[i]); - GETFDOperands.push_back(Chain); - GETFDOperands.push_back(InFlag); - - Chain = DAG.getNode(IA64ISD::GETFD, GETFDRetTypes, GETFDOperands); - Chain = DAG.getCopyToReg(Chain, IntArgRegs[i], Chain.getValue(0), Chain.getValue(1)); // ...thrice! - InFlag = Chain.getValue(1); - } } - std::vector RetVals; - RetVals.push_back(MVT::Other); - RetVals.push_back(MVT::Flag); - // If the callee is a GlobalAddress node (quite common, every direct call is) // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. - if (GlobalAddressSDNode *G = dyn_cast(Callee)) +/* + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i64); + } +*/ std::vector NodeTys; + std::vector CallOperands; NodeTys.push_back(MVT::Other); // Returns a chain NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. + CallOperands.push_back(Chain); + CallOperands.push_back(Callee); + + // emit the call itself if (InFlag.Val) + CallOperands.push_back(InFlag); + +/* out with the old... Chain = SDOperand(DAG.getCall(NodeTys, Chain, Callee, InFlag), 0); else Chain = SDOperand(DAG.getCall(NodeTys, Chain, Callee), 0); +*/ + // to make way for a hack: + Chain = DAG.getNode(IA64ISD::BRCALL, NodeTys, CallOperands); InFlag = Chain.getValue(1); // restore the GP, SP and RP after the call @@ -431,7 +442,11 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, InFlag = Chain.getValue(1); Chain = DAG.getCopyToReg(Chain, IA64::rp, RPBeforeCall, InFlag); InFlag = Chain.getValue(1); - + + std::vector RetVals; + RetVals.push_back(MVT::Other); + RetVals.push_back(MVT::Flag); + MVT::ValueType RetTyVT = getValueType(RetTy); SDOperand RetVal; if (RetTyVT != MVT::isVoid) { diff --git a/lib/Target/IA64/IA64ISelLowering.h b/lib/Target/IA64/IA64ISelLowering.h index 924691d70c9..0b869549024 100644 --- a/lib/Target/IA64/IA64ISelLowering.h +++ b/lib/Target/IA64/IA64ISelLowering.h @@ -38,10 +38,13 @@ namespace llvm { /// operand, producing an f64 value containing the integer representation /// of that FP value. FCTIDZ, FCTIWZ, - + /// GETFD - the getf.d instruction takes a floating point operand and /// returns its 64-bit memory representation as an i64 - GETFD + GETFD, + + // TODO: explain this hack + BRCALL }; }