* Add support for calling vararg functions (must pass doubles in int regs too)
* Make visitSetCondInst() share condition-generating code with EmitComparison()
* There are 13 FPRs for function-passing arguments, not 8
* Do not rely on registers being sequential, use an array lookup
* In unimplemented switch cases, send an error and abort instead of silent
  fall-through
* Add doInitialization() for adding function prototypes for external math fns
* Minor changes: fix indentation, spacing, code clarity


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14653 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/PowerPC/PowerPCISelSimple.cpp b/lib/Target/PowerPC/PowerPCISelSimple.cpp
index 10a46de..b69f5c6 100644
--- a/lib/Target/PowerPC/PowerPCISelSimple.cpp
+++ b/lib/Target/PowerPC/PowerPCISelSimple.cpp
@@ -87,6 +87,14 @@
 
     ISel(TargetMachine &tm) : TM(tm), F(0), BB(0) {}
 
+		bool doInitialization(Module &M) {
+			Type *d = Type::DoubleTy;
+			// double fmod(double, double);
+			// M.getOrInsertFunction("fmod", d, d, d, 0);
+			// { "__moddi3", "__divdi3", "__umoddi3", "__udivdi3" };
+			return false;
+		}
+
     /// runOnFunction - Top level implementation of instruction selection for
     /// the entire function.
     ///
@@ -169,7 +177,7 @@
       ValueRecord(Value *V) : Val(V), Reg(0), Ty(V->getType()) {}
     };
     void doCall(const ValueRecord &Ret, MachineInstr *CallMI,
-                const std::vector<ValueRecord> &Args);
+                const std::vector<ValueRecord> &Args, bool isVarArg);
     void visitCallInst(CallInst &I);
     void visitIntrinsicCall(Intrinsic::ID ID, CallInst &I);
 
@@ -466,14 +474,14 @@
       }
     }
   } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
-      // We need to spill the constant to memory...
-      MachineConstantPool *CP = F->getConstantPool();
-      unsigned CPI = CP->getConstantPoolIndex(CFP);
-      const Type *Ty = CFP->getType();
+    // We need to spill the constant to memory...
+    MachineConstantPool *CP = F->getConstantPool();
+    unsigned CPI = CP->getConstantPoolIndex(CFP);
+    const Type *Ty = CFP->getType();
 
-      assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
-      unsigned LoadOpcode = Ty == Type::FloatTy ? PPC32::LFS : PPC32::LFD;
-      addConstantPoolReference(BuildMI(*MBB, IP, LoadOpcode, 2, R), CPI);
+    assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
+    unsigned LoadOpcode = (Ty == Type::FloatTy) ? PPC32::LFS : PPC32::LFD;
+    addConstantPoolReference(BuildMI(*MBB, IP, LoadOpcode, 2, R), CPI);
   } else if (isa<ConstantPointerNull>(C)) {
     // Copy zero (null pointer) to the register.
     BuildMI(*MBB, IP, PPC32::ADDI, 2, R).addReg(PPC32::R0).addImm(0);
@@ -497,11 +505,18 @@
   unsigned ArgOffset = 0;   // Frame mechanisms handle retaddr slot
   unsigned GPR_remaining = 8;
   unsigned FPR_remaining = 13;
-  unsigned GPR_idx = 3;
-  unsigned FPR_idx = 1;
+  unsigned GPR_idx = 0, FPR_idx = 0;
+  static const unsigned GPR[] = { 
+    PPC32::R3, PPC32::R4, PPC32::R5, PPC32::R6,
+    PPC32::R7, PPC32::R8, PPC32::R9, PPC32::R10,
+  };
+  static const unsigned FPR[] = {
+    PPC32::F1, PPC32::F2, PPC32::F3, PPC32::F4, PPC32::F5, PPC32::F6, PPC32::F7, 
+		PPC32::F8, PPC32::F9, PPC32::F10, PPC32::F11, PPC32::F12, PPC32::F13
+  };
     
   MachineFrameInfo *MFI = F->getFrameInfo();
-
+ 
   for (Function::aiterator I = Fn.abegin(), E = Fn.aend(); I != E; ++I) {
     bool ArgLive = !I->use_empty();
     unsigned Reg = ArgLive ? getReg(*I) : 0;
@@ -512,8 +527,8 @@
       if (ArgLive) {
         FI = MFI->CreateFixedObject(1, ArgOffset);
         if (GPR_remaining > 0) {
-          BuildMI(BB, PPC32::OR, 2, Reg).addReg(PPC32::R0+GPR_idx)
-            .addReg(PPC32::R0+GPR_idx);
+          BuildMI(BB, PPC32::OR, 2, Reg).addReg(GPR[GPR_idx])
+            .addReg(GPR[GPR_idx]);
         } else {
           addFrameReference(BuildMI(BB, PPC32::LBZ, 2, Reg), FI);
         }
@@ -523,8 +538,8 @@
       if (ArgLive) {
         FI = MFI->CreateFixedObject(2, ArgOffset);
         if (GPR_remaining > 0) {
-          BuildMI(BB, PPC32::OR, 2, Reg).addReg(PPC32::R0+GPR_idx)
-            .addReg(PPC32::R0+GPR_idx);
+          BuildMI(BB, PPC32::OR, 2, Reg).addReg(GPR[GPR_idx])
+            .addReg(GPR[GPR_idx]);
         } else {
           addFrameReference(BuildMI(BB, PPC32::LHZ, 2, Reg), FI);
         }
@@ -534,8 +549,8 @@
       if (ArgLive) {
         FI = MFI->CreateFixedObject(4, ArgOffset);
         if (GPR_remaining > 0) {
-          BuildMI(BB, PPC32::OR, 2, Reg).addReg(PPC32::R0+GPR_idx)
-            .addReg(PPC32::R0+GPR_idx);
+          BuildMI(BB, PPC32::OR, 2, Reg).addReg(GPR[GPR_idx])
+            .addReg(GPR[GPR_idx]);
         } else {
           addFrameReference(BuildMI(BB, PPC32::LWZ, 2, Reg), FI);
         }
@@ -545,10 +560,10 @@
       if (ArgLive) {
         FI = MFI->CreateFixedObject(8, ArgOffset);
         if (GPR_remaining > 1) {
-            BuildMI(BB, PPC32::OR, 2, Reg).addReg(PPC32::R0+GPR_idx)
-              .addReg(PPC32::R0+GPR_idx);
-            BuildMI(BB, PPC32::OR, 2, Reg+1).addReg(PPC32::R0+GPR_idx+1)
-              .addReg(PPC32::R0+GPR_idx+1);
+            BuildMI(BB, PPC32::OR, 2, Reg).addReg(GPR[GPR_idx])
+              .addReg(GPR[GPR_idx]);
+            BuildMI(BB, PPC32::OR, 2, Reg+1).addReg(GPR[GPR_idx+1])
+              .addReg(GPR[GPR_idx+1]);
         } else {
             addFrameReference(BuildMI(BB, PPC32::LWZ, 2, Reg), FI);
             addFrameReference(BuildMI(BB, PPC32::LWZ, 2, Reg+1), FI, 4);
@@ -571,18 +586,18 @@
           FI = MFI->CreateFixedObject(8, ArgOffset);
         }
         if (FPR_remaining > 0) {
-            BuildMI(BB, PPC32::FMR, 1, Reg).addReg(PPC32::F0+FPR_idx);
-            FPR_remaining--;
-            FPR_idx++;
+          BuildMI(BB, PPC32::FMR, 1, Reg).addReg(FPR[FPR_idx]);
+          FPR_remaining--;
+          FPR_idx++;
         } else {
-            addFrameReference(BuildMI(BB, Opcode, 2, Reg), FI);
+          addFrameReference(BuildMI(BB, Opcode, 2, Reg), FI);
         }
       }
       if (I->getType() == Type::DoubleTy) {
         ArgOffset += 4;   // doubles require 4 additional bytes
         if (GPR_remaining > 0) {
-            GPR_remaining--;    // uses up 2 GPRs
-            GPR_idx++;
+          GPR_remaining--;    // uses up 2 GPRs
+          GPR_idx++;
         }
       }
       break;
@@ -591,8 +606,8 @@
     }
     ArgOffset += 4;  // Each argument takes at least 4 bytes on the stack...
     if (GPR_remaining > 0) {
-        GPR_remaining--;    // uses up 2 GPRs
-        GPR_idx++;
+      GPR_remaining--;    // uses up 2 GPRs
+      GPR_idx++;
     }
   }
 
@@ -836,6 +851,7 @@
     BuildMI(*MBB, IP, CompTy->isSigned() ? PPC32::CMP : PPC32::CMPL, 2, 
             PPC32::CR0).addReg(Op0r).addReg(Op1r);
     break;
+
   case cFP:
     emitUCOM(MBB, IP, Op0r, Op1r);
     break;
@@ -860,30 +876,22 @@
   return OpNum;
 }
 
-/// visitSetCondInst - 
+/// visitSetCondInst - emit code to calculate the condition via
+/// EmitComparison(), and possibly store a 0 or 1 to a register as a result
 ///
 void ISel::visitSetCondInst(SetCondInst &I) {
-  // If the only user of this SetCC is a branch or a select, we don't have to
-  // code-gen this instruction, it will be done more compactly for us later.
-  // FIXME: perhaps there could be several branches/selects using this SetCC and
-  // this SetCC could still be a valid candidate for folding?  Then the problem
-  // becomes with live range, whether or not the uses span function calls, other
-  // branches with can overwrite the condition register, etc.
-  User *user = I.hasOneUse() ? I.use_back() : 0;
-  if (canFoldSetCCIntoBranchOrSelect(&I) && 
-      (isa<BranchInst>(user) || isa<SelectInst>(user)))
+  if (canFoldSetCCIntoBranchOrSelect(&I))
     return;
   
   unsigned Op0Reg = getReg(I.getOperand(0));
   unsigned Op1Reg = getReg(I.getOperand(1));
   unsigned DestReg = getReg(I);
+	unsigned OpNum = I.getOpcode();
   const Type *Ty = I.getOperand (0)->getType();
                    
-  assert(getClass(Ty) < cLong && "can't setcc on longs or fp yet");
-  // Compare the two values.
-  BuildMI(BB, PPC32::CMPW, 2, PPC32::CR0).addReg(Op0Reg).addReg(Op1Reg);
-  
-  unsigned Opcode = getPPCOpcodeForSetCCNumber(I.getOpcode());
+  EmitComparison(OpNum, I.getOperand(0), I.getOperand(1), BB, BB->end());
+ 
+  unsigned Opcode = getPPCOpcodeForSetCCNumber(OpNum);
   MachineBasicBlock *thisMBB = BB;
   const BasicBlock *LLVM_BB = BB->getBasicBlock();
   //  thisMBB:
@@ -1169,7 +1177,7 @@
 /// FIXME: See Documentation at the following URL for "correct" behavior
 /// <http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/2rt_powerpc_abi/chapter_9_section_5.html>
 void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
-                  const std::vector<ValueRecord> &Args) {
+                  const std::vector<ValueRecord> &Args, bool isVarArg) {
   // Count how many bytes are to be pushed on the stack...
   unsigned NumBytes = 0;
 
@@ -1191,14 +1199,15 @@
 
     // Arguments go on the stack in reverse order, as specified by the ABI.
     unsigned ArgOffset = 0;
-    int GPR_remaining = 8, FPR_remaining = 8;
-    unsigned GPR[] = { 
+    int GPR_remaining = 8, FPR_remaining = 13;
+    static const unsigned GPR[] = { 
       PPC32::R3, PPC32::R4, PPC32::R5, PPC32::R6,
       PPC32::R7, PPC32::R8, PPC32::R9, PPC32::R10,
     };
-    unsigned FPR[] = {
-      PPC32::F1, PPC32::F2, PPC32::F3, PPC32::F4,
-      PPC32::F5, PPC32::F6, PPC32::F7, PPC32::F8
+    static const unsigned FPR[] = {
+	    PPC32::F1, PPC32::F2, PPC32::F3, PPC32::F4, PPC32::F5, PPC32::F6, 
+			PPC32::F7, PPC32::F8, PPC32::F9, PPC32::F10, PPC32::F11, PPC32::F12, 
+			PPC32::F13
     };
     unsigned GPR_idx = 0, FPR_idx = 0;
     
@@ -1264,6 +1273,7 @@
             BuildMI(BB, PPC32::STFS, 3).addReg(ArgReg).addImm(ArgOffset)
               .addReg(PPC32::R1);
           }
+          assert(!isVarArg && "Cannot pass floats to vararg functions!");
         } else {
           assert(Args[i].Ty == Type::DoubleTy && "Unknown FP type!");
           // Reg or stack?
@@ -1271,6 +1281,17 @@
             BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
             FPR_remaining--;
             FPR_idx++;
+            // For vararg functions, must pass doubles via int regs as well
+            if (isVarArg) {
+              BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
+                .addReg(PPC32::R1);
+              if (GPR_remaining > 1) {
+                BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addImm(ArgOffset)
+                  .addReg(PPC32::R1);
+                BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx + 1])
+                  .addImm(ArgOffset+4).addReg(PPC32::R1);
+              }
+            }
           } else {
             BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
               .addReg(PPC32::R1);
@@ -1293,7 +1314,6 @@
   }
 
   BB->push_back(CallMI);
-
   BuildMI(BB, PPC32::ADJCALLSTACKUP, 1).addImm(NumBytes);
 
   // If there is a return value, scavenge the result from the location the call
@@ -1324,7 +1344,8 @@
 /// visitCallInst - Push args on stack and do a procedure call instruction.
 void ISel::visitCallInst(CallInst &CI) {
   MachineInstr *TheCall;
-  if (Function *F = CI.getCalledFunction()) {
+  Function *F = CI.getCalledFunction();
+  if (F) {
     // Is it an intrinsic function call?
     if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) {
       visitIntrinsicCall(ID, CI);   // Special intrinsics are not handled here
@@ -1344,7 +1365,8 @@
     Args.push_back(ValueRecord(CI.getOperand(i)));
 
   unsigned DestReg = CI.getType() != Type::VoidTy ? getReg(CI) : 0;
-  doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args);
+  bool isVarArg = F ? F->getFunctionType()->isVarArg() : true;
+  doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args, isVarArg);
 }         
 
 
@@ -1505,13 +1527,13 @@
     const Type *Ty = Op1->getType();
 
     static const unsigned OpcodeTab[][4] = {
-      { PPC32::FADDS, PPC32::FSUBS, PPC32::FMULS, PPC32::FDIVS },   // Float
-      { PPC32::FADD, PPC32::FSUB, PPC32::FMUL, PPC32::FDIV },   // Double
+      { PPC32::FADDS, PPC32::FSUBS, PPC32::FMULS, PPC32::FDIVS },  // Float
+      { PPC32::FADD,  PPC32::FSUB,  PPC32::FMUL,  PPC32::FDIV },   // Double
     };
 
     assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
     unsigned TempReg = makeAnotherReg(Ty);
-    unsigned LoadOpcode = Ty == Type::FloatTy ? PPC32::LFS : PPC32::LFD;
+    unsigned LoadOpcode = (Ty == Type::FloatTy) ? PPC32::LFS : PPC32::LFD;
     addConstantPoolReference(BuildMI(*BB, IP, LoadOpcode, 2, TempReg), CPI);
 
     unsigned Opcode = OpcodeTab[Ty != Type::FloatTy][OperatorClass];
@@ -1536,13 +1558,13 @@
       const Type *Ty = CFP->getType();
 
       static const unsigned OpcodeTab[][4] = {
-        { PPC32::FADDS, PPC32::FSUBS, PPC32::FMULS, PPC32::FDIVS },   // Float
-        { PPC32::FADD, PPC32::FSUB, PPC32::FMUL, PPC32::FDIV },   // Double
+        { PPC32::FADDS, PPC32::FSUBS, PPC32::FMULS, PPC32::FDIVS },  // Float
+        { PPC32::FADD,  PPC32::FSUB,  PPC32::FMUL,  PPC32::FDIV },   // Double
       };
 
       assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
       unsigned TempReg = makeAnotherReg(Ty);
-      unsigned LoadOpcode = Ty == Type::FloatTy ? PPC32::LFS : PPC32::LFD;
+      unsigned LoadOpcode = (Ty == Type::FloatTy) ? PPC32::LFS : PPC32::LFD;
       addConstantPoolReference(BuildMI(*BB, IP, LoadOpcode, 2, TempReg), CPI);
 
       unsigned Opcode = OpcodeTab[Ty != Type::FloatTy][OperatorClass];
@@ -1924,14 +1946,12 @@
     } else {               // Floating point remainder...
       unsigned Op0Reg = getReg(Op0, BB, IP);
       unsigned Op1Reg = getReg(Op1, BB, IP);
-      // FIXME: Make sure the module has external function
-      // double fmod(double, double)
       MachineInstr *TheCall =
         BuildMI(PPC32::CALLpcrel, 1).addExternalSymbol("fmod", true);
       std::vector<ValueRecord> Args;
       Args.push_back(ValueRecord(Op0Reg, Type::DoubleTy));
       Args.push_back(ValueRecord(Op1Reg, Type::DoubleTy));
-      doCall(ValueRecord(ResultReg, Type::DoubleTy), TheCall, Args);
+      doCall(ValueRecord(ResultReg, Type::DoubleTy), TheCall, Args, false);
     }
     return;
   case cLong: {
@@ -1947,7 +1967,7 @@
     std::vector<ValueRecord> Args;
     Args.push_back(ValueRecord(Op0Reg, Type::LongTy));
     Args.push_back(ValueRecord(Op1Reg, Type::LongTy));
-    doCall(ValueRecord(ResultReg, Type::LongTy), TheCall, Args);
+    doCall(ValueRecord(ResultReg, Type::LongTy), TheCall, Args, false);
     return;
   }
   case cByte: case cShort: case cInt:
@@ -2315,7 +2335,8 @@
       // MFCR
       // Left-align
       // SRA ?
-      break;
+      std::cerr << "Cast fp-to-bool not implemented!";
+      abort();
     }
     return;
   }
@@ -2407,7 +2428,7 @@
       Args.push_back(ValueRecord(SrcReg, SrcTy));
       MachineInstr *TheCall =
         BuildMI(PPC32::CALLpcrel, 1).addExternalSymbol("__floatdidf", true);
-      doCall(ValueRecord(DestReg, DestTy), TheCall, Args);
+      doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
       return;
     }
 
@@ -2500,7 +2521,7 @@
       Args.push_back(ValueRecord(SrcReg, SrcTy));
       MachineInstr *TheCall =
         BuildMI(PPC32::CALLpcrel, 1).addExternalSymbol("__fixdfdi", true);
-      doCall(ValueRecord(DestReg, DestTy), TheCall, Args);
+      doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
       return;
     }
 
@@ -2733,7 +2754,7 @@
   Args.push_back(ValueRecord(Arg, Type::UIntTy));
   MachineInstr *TheCall = 
     BuildMI(PPC32::CALLpcrel, 1).addExternalSymbol("malloc", true);
-  doCall(ValueRecord(getReg(I), I.getType()), TheCall, Args);
+  doCall(ValueRecord(getReg(I), I.getType()), TheCall, Args, false);
 }
 
 
@@ -2745,7 +2766,7 @@
   Args.push_back(ValueRecord(I.getOperand(0)));
   MachineInstr *TheCall = 
     BuildMI(PPC32::CALLpcrel, 1).addExternalSymbol("free", true);
-  doCall(ValueRecord(0, Type::VoidTy), TheCall, Args);
+  doCall(ValueRecord(0, Type::VoidTy), TheCall, Args, false);
 }
    
 /// createPPC32SimpleInstructionSelector - This pass converts an LLVM function