diff options
-rw-r--r-- | lib/Target/IA64/IA64ISelDAGToDAG.cpp | 67 | ||||
-rw-r--r-- | lib/Target/IA64/IA64ISelLowering.cpp | 65 | ||||
-rw-r--r-- | lib/Target/IA64/IA64ISelLowering.h | 7 |
3 files changed, 112 insertions, 27 deletions
diff --git a/lib/Target/IA64/IA64ISelDAGToDAG.cpp b/lib/Target/IA64/IA64ISelDAGToDAG.cpp index 177365081f..8d5561b1cd 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<MVT::ValueType> TypeOperands; + + // if we can call directly, do so + if (GlobalAddressSDNode *GASD = + dyn_cast<GlobalAddressSDNode>(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<ExternalSymbolSDNode>(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<SDOperand> 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 adda64ec84..54ba3ef0d3 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<SDOperand> Stores; + std::vector<SDOperand> Converts; std::vector<SDOperand> 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<MVT::ValueType> GETFDRetTypes; - std::vector<SDOperand> 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<MVT::ValueType> 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<GlobalAddressSDNode>(Callee)) +/* + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i64); + } +*/ std::vector<MVT::ValueType> NodeTys; + std::vector<SDOperand> 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<MVT::ValueType> 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 924691d70c..0b86954902 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 }; } |