this is a hack, which may or may not hang around. In short:
authorDuraid Madina <duraid@octopus.com.au>
Thu, 22 Dec 2005 13:29:14 +0000 (13:29 +0000)
committerDuraid Madina <duraid@octopus.com.au>
Thu, 22 Dec 2005 13:29:14 +0000 (13:29 +0000)
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

lib/Target/IA64/IA64ISelDAGToDAG.cpp
lib/Target/IA64/IA64ISelLowering.cpp
lib/Target/IA64/IA64ISelLowering.h

index 177365081fd124e27ae672c63ef8bf4d2083327d..8d5561b1cd7107222da1f8d9270983fe36de618c 100644 (file)
@@ -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));
index adda64ec840e3f3ea18208d70b2f6d6657b89f88..54ba3ef0d3c9df0d29bbd2a16f06c462245783ed 100644 (file)
@@ -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) {
index 924691d70c968f6fa8db0c64fd7e3ebe2227812b..0b86954902426b997d74c2c6a1b53d63d7f89c2b 100644 (file)
@@ -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
     };
   }