InstSelectSimple.cpp: (visitReturnInst) Add return instructions with return
 values.
X86InstrInfo.def: add LEAVE instruction.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4691 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp
index af352ae..f2540a5 100644
--- a/lib/Target/X86/InstSelectSimple.cpp
+++ b/lib/Target/X86/InstSelectSimple.cpp
@@ -326,15 +326,70 @@
 ///   ret long, ulong  : Move value into EAX/EDX (?) and return
 ///   ret float/double : ?  Top of FP stack?  XMM0?
 ///
-void ISel::visitReturnInst(ReturnInst &I) {
-  if (I.getNumOperands() != 0) {  // Not 'ret void'?
-    // Move result into a hard register... then emit a ret
-    visitInstruction(I);  // abort
-  }
-
-  // Emit a simple 'ret' instruction... appending it to the end of the basic
-  // block
-  BuildMI(BB, X86::RET, 0);
+void
+ISel::visitReturnInst (ReturnInst & I)
+{
+  if (I.getNumOperands () == 1)
+    {
+      unsigned val = getReg (I.getOperand (0));
+      unsigned operandSize =
+	I.getOperand (0)->getType ()->getPrimitiveSize ();
+      bool isFP = I.getOperand (0)->getType ()->isFloatingPoint ();
+      if (isFP)
+	{
+	  // ret float/double: top of FP stack
+	  // FLD <val>
+	  switch (operandSize)
+	    {
+	    case 4:
+	      BuildMI (BB, X86::FLDr4, 1, X86::NoReg).addReg (val);
+	      break;
+	    case 8:
+	      BuildMI (BB, X86::FLDr8, 1, X86::NoReg).addReg (val);
+	      break;
+	    default:
+	      visitInstruction (I);
+	      break;
+	    }
+	}
+      else
+	{
+	  switch (operandSize)
+	    {
+	    case 1:
+	      // ret sbyte, ubyte: Extend value into EAX and return
+	      // MOV AL, <val>
+	      // CBW
+	      BuildMI (BB, X86::MOVrr8, 1, X86::AL).addReg (val);
+	      BuildMI (BB, X86::CBW, 0);
+	      break;
+	    case 2:
+	      // ret short, ushort: Extend value into EAX and return
+	      // MOV AX, <val>
+	      // CWDE
+	      BuildMI (BB, X86::MOVrr16, 1, X86::AX).addReg (val);
+	      BuildMI (BB, X86::CWDE, 0);
+	      break;
+	    case 4:
+	      // ret int, uint, ptr: Move value into EAX and return
+	      // MOV EAX, <val>
+	      BuildMI (BB, X86::MOVrr32, 1, X86::EAX).addReg (val);
+	      break;
+	    case 8:
+	      // ret long: use EAX(least significant 32 bits)/EDX (most
+	      // significant 32)...uh, I think so Brain, but how do i call
+	      // up the two parts of the value from inside this mouse
+	      // cage? *zort*
+	    default:
+	      // abort
+	      visitInstruction (I);
+	      break;
+	    }
+	}
+    }
+  // Emit a 'leave' and a 'ret'
+  BuildMI (BB, X86::LEAVE, 0);
+  BuildMI (BB, X86::RET, 0);
 }
 
 /// visitBranchInst - Handle conditional and unconditional branches here.  Note
diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp
index af352ae..f2540a5 100644
--- a/lib/Target/X86/X86ISelSimple.cpp
+++ b/lib/Target/X86/X86ISelSimple.cpp
@@ -326,15 +326,70 @@
 ///   ret long, ulong  : Move value into EAX/EDX (?) and return
 ///   ret float/double : ?  Top of FP stack?  XMM0?
 ///
-void ISel::visitReturnInst(ReturnInst &I) {
-  if (I.getNumOperands() != 0) {  // Not 'ret void'?
-    // Move result into a hard register... then emit a ret
-    visitInstruction(I);  // abort
-  }
-
-  // Emit a simple 'ret' instruction... appending it to the end of the basic
-  // block
-  BuildMI(BB, X86::RET, 0);
+void
+ISel::visitReturnInst (ReturnInst & I)
+{
+  if (I.getNumOperands () == 1)
+    {
+      unsigned val = getReg (I.getOperand (0));
+      unsigned operandSize =
+	I.getOperand (0)->getType ()->getPrimitiveSize ();
+      bool isFP = I.getOperand (0)->getType ()->isFloatingPoint ();
+      if (isFP)
+	{
+	  // ret float/double: top of FP stack
+	  // FLD <val>
+	  switch (operandSize)
+	    {
+	    case 4:
+	      BuildMI (BB, X86::FLDr4, 1, X86::NoReg).addReg (val);
+	      break;
+	    case 8:
+	      BuildMI (BB, X86::FLDr8, 1, X86::NoReg).addReg (val);
+	      break;
+	    default:
+	      visitInstruction (I);
+	      break;
+	    }
+	}
+      else
+	{
+	  switch (operandSize)
+	    {
+	    case 1:
+	      // ret sbyte, ubyte: Extend value into EAX and return
+	      // MOV AL, <val>
+	      // CBW
+	      BuildMI (BB, X86::MOVrr8, 1, X86::AL).addReg (val);
+	      BuildMI (BB, X86::CBW, 0);
+	      break;
+	    case 2:
+	      // ret short, ushort: Extend value into EAX and return
+	      // MOV AX, <val>
+	      // CWDE
+	      BuildMI (BB, X86::MOVrr16, 1, X86::AX).addReg (val);
+	      BuildMI (BB, X86::CWDE, 0);
+	      break;
+	    case 4:
+	      // ret int, uint, ptr: Move value into EAX and return
+	      // MOV EAX, <val>
+	      BuildMI (BB, X86::MOVrr32, 1, X86::EAX).addReg (val);
+	      break;
+	    case 8:
+	      // ret long: use EAX(least significant 32 bits)/EDX (most
+	      // significant 32)...uh, I think so Brain, but how do i call
+	      // up the two parts of the value from inside this mouse
+	      // cage? *zort*
+	    default:
+	      // abort
+	      visitInstruction (I);
+	      break;
+	    }
+	}
+    }
+  // Emit a 'leave' and a 'ret'
+  BuildMI (BB, X86::LEAVE, 0);
+  BuildMI (BB, X86::RET, 0);
 }
 
 /// visitBranchInst - Handle conditional and unconditional branches here.  Note
diff --git a/lib/Target/X86/X86InstrInfo.def b/lib/Target/X86/X86InstrInfo.def
index e6c6b07..1a6f2f5 100644
--- a/lib/Target/X86/X86InstrInfo.def
+++ b/lib/Target/X86/X86InstrInfo.def
@@ -44,6 +44,7 @@
 I(MOVir8      , "movb",               0, 0)           // R8  = imm8   B0+ rb
 I(MOVir16     , "movw",               0, 0)           // R16 = imm16  B8+ rw
 I(MOVir32     , "movl",               0, 0)           // R32 = imm32  B8+ rd
+I(LEAVE       , "leave",              0, 0)           // leave        C9
 
 // Arithmetic instructions
 I(ADDrr8      , "addb",               0, 0)           // R8  += R8    00/r