* Add special entry code main() (to set x87 to 64-bit precision).
* Allow a register node as SelectAddr() base.
* ExternalSymbol -> TargetExternalSymbol as direct function callee.
* Use X86::ESP register rather than CopyFromReg(X86::ESP) as stack ptr for
  call parmater passing.

llvm-svn: 25207
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index c6d4e67..9f5c588 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "X86.h"
+#include "X86InstrBuilder.h"
 #include "X86RegisterInfo.h"
 #include "X86Subtarget.h"
 #include "X86ISelLowering.h"
@@ -95,6 +96,8 @@
     /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
     virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
 
+    virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
+
 // Include the pieces autogenerated from the target description.
 #include "X86GenDAGISel.inc"
 
@@ -208,7 +211,29 @@
   }
 }
 
-/// FIXME: copied from X86ISelPattern.cpp
+/// EmitSpecialCodeForMain - Emit any code that needs to be executed only in
+/// the main function.
+static void EmitSpecialCodeForMain(MachineBasicBlock *BB,
+                                   MachineFrameInfo *MFI) {
+  // Switch the FPU to 64-bit precision mode for better compatibility and speed.
+  int CWFrameIdx = MFI->CreateStackObject(2, 2);
+  addFrameReference(BuildMI(BB, X86::FNSTCW16m, 4), CWFrameIdx);
+
+  // Set the high part to be 64-bit precision.
+  addFrameReference(BuildMI(BB, X86::MOV8mi, 5),
+                    CWFrameIdx, 1).addImm(2);
+
+  // Reload the modified control word now.
+  addFrameReference(BuildMI(BB, X86::FLDCW16m, 4), CWFrameIdx);
+}
+
+void X86DAGToDAGISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {
+  // If this is main, emit special code for main.
+  MachineBasicBlock *BB = MF.begin();
+  if (Fn.hasExternalLinkage() && Fn.getName() == "main")
+    EmitSpecialCodeForMain(BB, MF.getFrameInfo());
+}
+
 /// MatchAddress - Add the specified node to the specified addressing mode,
 /// returning true if it cannot be done.  This just pattern matches for the
 /// addressing mode
@@ -338,22 +363,25 @@
 bool X86DAGToDAGISel::SelectAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
                                  SDOperand &Index, SDOperand &Disp) {
   X86ISelAddressMode AM;
-  if (!MatchAddress(N, AM)) {
-    if (AM.BaseType == X86ISelAddressMode::RegBase) {
-      if (AM.Base.Reg.Val)
-        AM.Base.Reg = Select(AM.Base.Reg);
-      else
-        AM.Base.Reg = CurDAG->getRegister(0, MVT::i32);
-    }
-    if (AM.IndexReg.Val)
-      AM.IndexReg = Select(AM.IndexReg);
-    else
-      AM.IndexReg = CurDAG->getRegister(0, MVT::i32);
+  if (MatchAddress(N, AM))
+    return false;
 
-    getAddressOperands(AM, Base, Scale, Index, Disp);
-    return true;
+  if (AM.BaseType == X86ISelAddressMode::RegBase) {
+    if (AM.Base.Reg.Val) {
+      if (AM.Base.Reg.getOpcode() != ISD::Register)
+        AM.Base.Reg = Select(AM.Base.Reg);
+    } else {
+      AM.Base.Reg = CurDAG->getRegister(0, MVT::i32);
+    }
   }
-  return false;
+
+  if (AM.IndexReg.Val)
+    AM.IndexReg = Select(AM.IndexReg);
+  else
+    AM.IndexReg = CurDAG->getRegister(0, MVT::i32);
+
+  getAddressOperands(AM, Base, Scale, Index, Disp);
+  return true;
 }
 
 bool X86DAGToDAGISel::TryFoldLoad(SDOperand N, SDOperand &Base,