Currently LLVM has two intrinsics for supporting trampolines,
aka pointers to nested functions: init_trampoline and adjust_trampoline.
In essence, init_trampoline fills a block of memory with executable code,
and adjust_trampoline returns a suitable function pointer for calling that
code.  These patches fold adjust_trampoline into init_trampoline, leaving
init_trampoline as the only intrinsic (it now returns the function pointer
adjust_trampoline used to return).  This requires modifying gcc's nested
function lowering pass, which currently stores the executable code in the
"frame" used to pass the variables of a parent function to its children, and
calls adjust_trampoline whenever it needs the function pointer (the call may
occur in a child function, far from the point at which init_trampoline was
called).  After these patches, the function pointer is stored in the frame
instead, with the code being written to a temporary variable on the parent's
stack.  This means that the adjust_trampoline call happens immediately after the
init_trampoline call, so they might as well be combined into one intrinsic.  The
cost of organizing things this way is that space for one extra function pointer
per trampoline is allocated on the stack.

My motive for doing this was not to simplify LLVM (which is a nice benefit),
but to make it easier to do the optimization in the attached patch 
tramp_opt.diff
This teaches instcombine how to turn a call to the function pointer returned by
init_trampoline into a direct call to the nested function.  This matters because
calling a function via a trampoline is amazingly expensive (presumably due to
icache flushing - remember that code on the stack gets executed).  Since 
usually a
pointer to a nested function is taken in order to pass it to some other 
function, this
optimization is only going to happen if that other function is inlined, so that 
the
init_trampoline and the call to the nested function pointer occur in the same 
function.
It is easy to construct testcases for which this works, but sadly I was unable 
to get
the optimization to occur even once in a trampoline heavy real-world program 
without
jacking-up the inlining limit hugely (to 100000; 10000 wasn't enough).  Still, 
I'm
hoping that it may sometimes be useful.

Ciao,

Duncan.
Index: llvm.master/include/llvm/CodeGen/SelectionDAGNodes.h
===================================================================
--- llvm.master.orig/include/llvm/CodeGen/SelectionDAGNodes.h	2007-09-06 19:25:40.000000000 +0200
+++ llvm.master/include/llvm/CodeGen/SelectionDAGNodes.h	2007-09-06 19:26:34.000000000 +0200
@@ -540,16 +540,13 @@
     // produces a token chain as output.
     DEBUG_LOC,
 
-    // ADJUST_TRAMP - This corresponds to the adjust_trampoline intrinsic.
-    // It takes a value as input and returns a value as output.
-    ADJUST_TRAMP,
-
     // TRAMPOLINE - This corresponds to the init_trampoline intrinsic.
     // It takes as input a token chain, the pointer to the trampoline,
     // the pointer to the nested function, the pointer to pass for the
     // 'nest' parameter, a SRCVALUE for the trampoline and another for
     // the nested function (allowing targets to access the original
-    // Function*).  It produces a token chain as output.
+    // Function*).  It produces the result of the intrinsic and a token
+    // chain as output.
     TRAMPOLINE,
 
     // BUILTIN_OP_END - This must be the last enum value in this list.
Index: llvm.master/include/llvm/Intrinsics.td
===================================================================
--- llvm.master.orig/include/llvm/Intrinsics.td	2007-09-06 19:25:40.000000000 +0200
+++ llvm.master/include/llvm/Intrinsics.td	2007-09-06 19:26:34.000000000 +0200
@@ -239,11 +239,9 @@
 
 //===------------------------ Trampoline Intrinsics -----------------------===//
 //
-def int_init_trampoline   : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty,
-                                       llvm_ptr_ty], []>,
-                            GCCBuiltin<"__builtin_init_trampoline">;
-def int_adjust_trampoline : Intrinsic<[llvm_ptr_ty, llvm_ptr_ty], [IntrNoMem]>,
-                            GCCBuiltin<"__builtin_adjust_trampoline">;
+def int_init_trampoline : Intrinsic<[llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty,
+                                     llvm_ptr_ty], []>,
+                          GCCBuiltin<"__builtin_init_trampoline">;
 
 //===----------------------------------------------------------------------===//
 // Target-specific intrinsics
Index: llvm.master/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
===================================================================
--- llvm.master.orig/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp	2007-09-06 19:25:40.000000000 +0200
+++ llvm.master/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp	2007-09-06 19:26:34.000000000 +0200
@@ -3347,21 +3347,6 @@
     }
     break;
   }
-  case ISD::ADJUST_TRAMP: {
-    Tmp1 = LegalizeOp(Node->getOperand(0));
-    switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
-    default: assert(0 && "This action is not supported yet!");
-    case TargetLowering::Custom:
-      Result = DAG.UpdateNodeOperands(Result, Tmp1);
-      Result = TLI.LowerOperation(Result, DAG);
-      if (Result.Val) break;
-      // FALL THROUGH
-    case TargetLowering::Expand:
-      Result = Tmp1;
-      break;
-    }
-    break;
-  }
   case ISD::TRAMPOLINE: {
     SDOperand Ops[6];
     for (unsigned i = 0; i != 6; ++i)
@@ -3370,7 +3355,14 @@
     // The only option for this node is to custom lower it.
     Result = TLI.LowerOperation(Result, DAG);
     assert(Result.Val && "Should always custom lower!");
-    break;
+
+    // Since trampoline produces two values, make sure to remember that we
+    // legalized both of them.
+    Tmp1 = LegalizeOp(Result.getValue(1));
+    Result = LegalizeOp(Result);
+    AddLegalizedOperand(SDOperand(Node, 0), Result);
+    AddLegalizedOperand(SDOperand(Node, 1), Tmp1);
+    return Op.ResNo ? Tmp1 : Result;
   }
   }
   
Index: llvm.master/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
===================================================================
--- llvm.master.orig/lib/CodeGen/SelectionDAG/SelectionDAG.cpp	2007-09-06 19:25:40.000000000 +0200
+++ llvm.master/lib/CodeGen/SelectionDAG/SelectionDAG.cpp	2007-09-06 19:26:34.000000000 +0200
@@ -3643,8 +3643,7 @@
   case ISD::DEBUG_LOC: return "debug_loc";
 
   // Trampolines
-  case ISD::ADJUST_TRAMP: return "adjust_tramp";
-  case ISD::TRAMPOLINE:   return "trampoline";
+  case ISD::TRAMPOLINE: return "trampoline";
 
   case ISD::CONDCODE:
     switch (cast<CondCodeSDNode>(this)->get()) {
Index: llvm.master/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
===================================================================
--- llvm.master.orig/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	2007-09-06 19:25:40.000000000 +0200
+++ llvm.master/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	2007-09-06 19:26:34.000000000 +0200
@@ -2873,12 +2873,6 @@
     // Discard annotate attributes
     return 0;
 
-  case Intrinsic::adjust_trampoline: {
-    SDOperand Arg = getValue(I.getOperand(1));
-    setValue(&I, DAG.getNode(ISD::ADJUST_TRAMP, TLI.getPointerTy(), Arg));
-    return 0;
-  }
-
   case Intrinsic::init_trampoline: {
     const Function *F =
       cast<Function>(IntrinsicInst::StripPointerCasts(I.getOperand(2)));
@@ -2891,7 +2885,13 @@
     Ops[4] = DAG.getSrcValue(I.getOperand(1));
     Ops[5] = DAG.getSrcValue(F);
 
-    DAG.setRoot(DAG.getNode(ISD::TRAMPOLINE, MVT::Other, Ops, 6));
+    SDOperand Tmp = DAG.getNode(ISD::TRAMPOLINE,
+                                DAG.getNodeValueTypes(TLI.getPointerTy(),
+                                                      MVT::Other), 2,
+                                Ops, 6);
+
+    setValue(&I, Tmp);
+    DAG.setRoot(Tmp.getValue(1));
     return 0;
   }
   }
Index: llvm.master/lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- llvm.master.orig/lib/Target/ARM/ARMISelLowering.cpp	2007-09-06 19:25:39.000000000 +0200
+++ llvm.master/lib/Target/ARM/ARMISelLowering.cpp	2007-09-06 19:26:35.000000000 +0200
@@ -191,11 +191,6 @@
   setOperationAction(ISD::MEMCPY          , MVT::Other, Custom);
   setOperationAction(ISD::MEMMOVE         , MVT::Other, Expand);
 
-  if (Subtarget->isThumb())
-    setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Custom);
-  else
-    setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand);
-
   // Use the default implementation.
   setOperationAction(ISD::VASTART           , MVT::Other, Expand);
   setOperationAction(ISD::VAARG             , MVT::Other, Expand);
@@ -1418,14 +1413,6 @@
   return Chain;
 }
 
-SDOperand ARMTargetLowering::LowerADJUST_TRAMP(SDOperand Op,
-                                                    SelectionDAG &DAG) {
-  // Thumb trampolines should be entered in thumb mode, so set the bottom bit
-  // of the address.
-  return DAG.getNode(ISD::OR, MVT::i32, Op.getOperand(0),
-                     DAG.getConstant(1, MVT::i32));
-}
-
 SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   switch (Op.getOpcode()) {
   default: assert(0 && "Don't know how to custom lower this!"); abort();
@@ -1457,7 +1444,6 @@
   case ISD::FRAMEADDR:     break;
   case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
   case ISD::MEMCPY:        return LowerMEMCPY(Op, DAG);
-  case ISD::ADJUST_TRAMP:  return LowerADJUST_TRAMP(Op, DAG);
   }
   return SDOperand();
 }
Index: llvm.master/lib/Target/ARM/ARMISelLowering.h
===================================================================
--- llvm.master.orig/lib/Target/ARM/ARMISelLowering.h	2007-09-06 19:25:39.000000000 +0200
+++ llvm.master/lib/Target/ARM/ARMISelLowering.h	2007-09-06 19:26:35.000000000 +0200
@@ -138,7 +138,6 @@
     SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerBR_JT(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG);
-    SDOperand LowerADJUST_TRAMP(SDOperand Op, SelectionDAG &DAG);
   };
 }
 
Index: llvm.master/lib/Target/Alpha/AlphaISelLowering.cpp
===================================================================
--- llvm.master.orig/lib/Target/Alpha/AlphaISelLowering.cpp	2007-09-06 19:25:40.000000000 +0200
+++ llvm.master/lib/Target/Alpha/AlphaISelLowering.cpp	2007-09-06 19:26:35.000000000 +0200
@@ -124,9 +124,6 @@
   setOperationAction(ISD::ExternalSymbol, MVT::i64, Custom);
   setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
 
-  setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand);
-  setOperationAction(ISD::ADJUST_TRAMP, MVT::i64, Expand);
-
   setOperationAction(ISD::VASTART, MVT::Other, Custom);
   setOperationAction(ISD::VAEND,   MVT::Other, Expand);
   setOperationAction(ISD::VACOPY,  MVT::Other, Custom);
Index: llvm.master/lib/Target/IA64/IA64ISelLowering.cpp
===================================================================
--- llvm.master.orig/lib/Target/IA64/IA64ISelLowering.cpp	2007-09-06 19:25:39.000000000 +0200
+++ llvm.master/lib/Target/IA64/IA64ISelLowering.cpp	2007-09-06 19:26:35.000000000 +0200
@@ -97,8 +97,6 @@
       setOperationAction(ISD::ROTR , MVT::i64  , Expand);
       setOperationAction(ISD::BSWAP, MVT::i64  , Expand);  // mux @rev
 
-      setOperationAction(ISD::ADJUST_TRAMP, MVT::i64, Expand);
-
       // VASTART needs to be custom lowered to use the VarArgsFrameIndex
       setOperationAction(ISD::VAARG             , MVT::Other, Custom);
       setOperationAction(ISD::VASTART           , MVT::Other, Custom);
Index: llvm.master/lib/Target/Mips/MipsISelLowering.cpp
===================================================================
--- llvm.master.orig/lib/Target/Mips/MipsISelLowering.cpp	2007-09-06 19:25:39.000000000 +0200
+++ llvm.master/lib/Target/Mips/MipsISelLowering.cpp	2007-09-06 19:26:35.000000000 +0200
@@ -105,8 +105,6 @@
   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
 
-  setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand);
-
   setStackPointerRegisterToSaveRestore(Mips::SP);
   computeRegisterProperties();
 }
Index: llvm.master/lib/Target/PowerPC/PPCISelLowering.cpp
===================================================================
--- llvm.master.orig/lib/Target/PowerPC/PPCISelLowering.cpp	2007-09-06 19:25:40.000000000 +0200
+++ llvm.master/lib/Target/PowerPC/PPCISelLowering.cpp	2007-09-06 19:26:35.000000000 +0200
@@ -170,9 +170,6 @@
   // RET must be custom lowered, to meet ABI requirements
   setOperationAction(ISD::RET               , MVT::Other, Custom);
 
-  setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand);
-  setOperationAction(ISD::ADJUST_TRAMP, MVT::i64, Expand);
-
   // VASTART needs to be custom lowered to use the VarArgsFrameIndex
   setOperationAction(ISD::VASTART           , MVT::Other, Custom);
   
Index: llvm.master/lib/Target/Sparc/SparcISelDAGToDAG.cpp
===================================================================
--- llvm.master.orig/lib/Target/Sparc/SparcISelDAGToDAG.cpp	2007-09-06 19:25:39.000000000 +0200
+++ llvm.master/lib/Target/Sparc/SparcISelDAGToDAG.cpp	2007-09-06 19:26:35.000000000 +0200
@@ -216,8 +216,6 @@
   // RET must be custom lowered, to meet ABI requirements
   setOperationAction(ISD::RET               , MVT::Other, Custom);
 
-  setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand);
-
   // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
   setOperationAction(ISD::VASTART           , MVT::Other, Custom);
   // VAARG needs to be lowered to not do unaligned accesses for doubles.
Index: llvm.master/lib/Target/X86/X86ISelLowering.cpp
===================================================================
--- llvm.master.orig/lib/Target/X86/X86ISelLowering.cpp	2007-09-06 19:25:40.000000000 +0200
+++ llvm.master/lib/Target/X86/X86ISelLowering.cpp	2007-09-06 19:26:35.000000000 +0200
@@ -246,9 +246,7 @@
   }
   setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
   
-  setOperationAction(ISD::ADJUST_TRAMP, MVT::i32,   Expand);
-  setOperationAction(ISD::ADJUST_TRAMP, MVT::i64,   Expand);
-  setOperationAction(ISD::TRAMPOLINE,   MVT::Other, Custom);
+  setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom);
 
   // VASTART needs to be custom lowered to use the VarArgsFrameIndex
   setOperationAction(ISD::VASTART           , MVT::Other, Custom);
@@ -4405,7 +4403,9 @@
     OutChains[3] = DAG.getStore(Root, Disp, Addr, TrmpSV->getValue(),
                                 TrmpSV->getOffset() + 6, false, 1);
 
-    return DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains, 4);
+    SDOperand Ops[] =
+      { Trmp, DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains, 4) };
+    return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(), Ops, 2);
   }
 }
 
Index: llvm.master/docs/LangRef.html
===================================================================
--- llvm.master.orig/docs/LangRef.html	2007-09-06 19:25:39.000000000 +0200
+++ llvm.master/docs/LangRef.html	2007-09-06 19:26:35.000000000 +0200
@@ -200,10 +200,9 @@
           <li><a href="#int_memory_barrier">'<tt>llvm.memory.barrier</tt>' Intrinsic</a></li>
         </ol>
       </li>
-      <li><a href="#int_trampoline">Trampoline Intrinsics</a>
+      <li><a href="#int_trampoline">Trampoline Intrinsic</a>
         <ol>
           <li><a href="#int_it">'<tt>llvm.init.trampoline</tt>' Intrinsic</a></li>
-          <li><a href="#int_at">'<tt>llvm.adjust.trampoline</tt>' Intrinsic</a></li>
         </ol>
       </li>
       <li><a href="#int_general">General intrinsics</a>
@@ -5143,12 +5142,12 @@
 
 <!-- ======================================================================= -->
 <div class="doc_subsection">
-  <a name="int_trampoline">Trampoline Intrinsics</a>
+  <a name="int_trampoline">Trampoline Intrinsic</a>
 </div>
 
 <div class="doc_text">
 <p>
-  These intrinsics make it possible to excise one parameter, marked with
+  This intrinsic makes it possible to excise one parameter, marked with
   the <tt>nest</tt> attribute, from a function.  The result is a callable
   function pointer lacking the nest parameter - the caller does not need
   to provide a value for it.  Instead, the value to use is stored in
@@ -5162,11 +5161,10 @@
   <tt>i32 f(i8* nest  %c, i32 %x, i32 %y)</tt> then the resulting function
   pointer has signature <tt>i32 (i32, i32)*</tt>.  It can be created as follows:
 <pre>
-  %tramp1 = alloca [10 x i8], align 4 ; size and alignment only correct for X86
-  %tramp = getelementptr [10 x i8]* %tramp1, i32 0, i32 0
-  call void @llvm.init.trampoline( i8* %tramp, i8* bitcast (i32 (i8* nest , i32, i32)* @f to i8*), i8* %nval )
-  %adj = call i8* @llvm.adjust.trampoline( i8* %tramp )
-  %fp = bitcast i8* %adj to i32 (i32, i32)*
+  %tramp = alloca [10 x i8], align 4 ; size and alignment only correct for X86
+  %tramp1 = getelementptr [10 x i8]* %tramp, i32 0, i32 0
+  %p = call i8* @llvm.init.trampoline( i8* %tramp1, i8* bitcast (i32 (i8* nest , i32, i32)* @f to i8*), i8* %nval )
+  %fp = bitcast i8* %p to i32 (i32, i32)*
 </pre>
   The call <tt>%val = call i32 %fp( i32 %x, i32 %y )</tt> is then equivalent to
   <tt>%val = call i32 %f( i8* %nval, i32 %x, i32 %y )</tt>.
@@ -5180,11 +5178,12 @@
 <div class="doc_text">
 <h5>Syntax:</h5>
 <pre>
-declare void @llvm.init.trampoline(i8* &lt;tramp&gt;, i8* &lt;func&gt;, i8* &lt;nval&gt;)
+declare i8* @llvm.init.trampoline(i8* &lt;tramp&gt;, i8* &lt;func&gt;, i8* &lt;nval&gt;)
 </pre>
 <h5>Overview:</h5>
 <p>
-  This initializes the memory pointed to by <tt>tramp</tt> as a trampoline.
+  This fills the memory pointed to by <tt>tramp</tt> with code
+  and returns a function pointer suitable for executing it.
 </p>
 <h5>Arguments:</h5>
 <p>
@@ -5199,42 +5198,18 @@
 <h5>Semantics:</h5>
 <p>
   The block of memory pointed to by <tt>tramp</tt> is filled with target
-  dependent code, turning it into a function.
-  The new function's signature is the same as that of <tt>func</tt> with
-  any arguments marked with the <tt>nest</tt> attribute removed.  At most
-  one such <tt>nest</tt> argument is allowed, and it must be of pointer
-  type.  Calling the new function is equivalent to calling <tt>func</tt>
-  with the same argument list, but with <tt>nval</tt> used for the missing
-  <tt>nest</tt> argument.
-</p>
-</div>
-
-<!-- _______________________________________________________________________ -->
-<div class="doc_subsubsection">
-  <a name="int_at">'<tt>llvm.adjust.trampoline</tt>' Intrinsic</a>
-</div>
-<div class="doc_text">
-<h5>Syntax:</h5>
-<pre>
-declare i8* @llvm.adjust.trampoline(i8* &lt;tramp&gt;)
-</pre>
-<h5>Overview:</h5>
-<p>
-  This intrinsic returns a function pointer suitable for executing
-  the trampoline code pointed to by <tt>tramp</tt>.
-</p>
-<h5>Arguments:</h5>
-<p>
-  The <tt>llvm.adjust.trampoline</tt> takes one argument, a pointer to a
-  trampoline initialized by the
-  <a href="#int_it">'<tt>llvm.init.trampoline</tt>' intrinsic</a>.
-</p>
-<h5>Semantics:</h5>
-<p>
-  A function pointer that can be used to execute the trampoline code in
-  <tt>tramp</tt> is returned.  The returned value should be bitcast to an
+  dependent code, turning it into a function.  A pointer to this function is
+  returned, but needs to be bitcast to an
   <a href="#int_trampoline">appropriate function pointer type</a>
-  before being called.
+  before being called.  The new function's signature is the same as that of
+  <tt>func</tt> with any arguments marked with the <tt>nest</tt> attribute
+  removed.  At most one such <tt>nest</tt> argument is allowed, and it must be
+  of pointer type.  Calling the new function is equivalent to calling
+  <tt>func</tt> with the same argument list, but with <tt>nval</tt> used for the
+  missing <tt>nest</tt> argument.  If, after calling
+  <tt>llvm.init.trampoline</tt>, the memory pointed to by <tt>tramp</tt> is
+  modified, then the effect of any later call to the returned function pointer is
+  undefined.
 </p>
 </div>
 
Index: gcc.llvm.master/gcc/builtins.c
===================================================================
--- gcc.llvm.master.orig/gcc/builtins.c	2007-09-06 11:16:22.000000000 +0200
+++ gcc.llvm.master/gcc/builtins.c	2007-09-06 11:23:08.000000000 +0200
@@ -4986,25 +4986,13 @@
   trampolines_created = 1;
   INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
 
-  return const0_rtx;
-}
-
-static rtx
-expand_builtin_adjust_trampoline (tree arglist)
-{
-  rtx tramp;
-
-  if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
-    return NULL_RTX;
-
-  tramp = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
-  tramp = round_trampoline_addr (tramp);
 #ifdef TRAMPOLINE_ADJUST_ADDRESS
-  TRAMPOLINE_ADJUST_ADDRESS (tramp);
+  TRAMPOLINE_ADJUST_ADDRESS (r_tramp);
 #endif
 
-  return tramp;
+  return r_tramp;
 }
+/* LLVM local end */
 
 /* Expand a call to the built-in signbit, signbitf or signbitl function.
    Return NULL_RTX if a normal call should be emitted rather than expanding
@@ -5784,8 +5772,7 @@
 
     case BUILT_IN_INIT_TRAMPOLINE:
       return expand_builtin_init_trampoline (arglist);
-    case BUILT_IN_ADJUST_TRAMPOLINE:
-      return expand_builtin_adjust_trampoline (arglist);
+    /* LLVM local deleted 2 lines */
 
     case BUILT_IN_FORK:
     case BUILT_IN_EXECL:
Index: gcc.llvm.master/gcc/builtins.def
===================================================================
--- gcc.llvm.master.orig/gcc/builtins.def	2007-09-06 11:16:22.000000000 +0200
+++ gcc.llvm.master/gcc/builtins.def	2007-09-06 11:23:08.000000000 +0200
@@ -635,7 +635,7 @@
 
 /* Implementing nested functions.  */
 DEF_BUILTIN_STUB (BUILT_IN_INIT_TRAMPOLINE, "__builtin_init_trampoline")
-DEF_BUILTIN_STUB (BUILT_IN_ADJUST_TRAMPOLINE, "__builtin_adjust_trampoline")
+/* LLVM local deleted 1 line */
 DEF_BUILTIN_STUB (BUILT_IN_NONLOCAL_GOTO, "__builtin_nonlocal_goto")
 
 /* Implementing variable sized local variables.  */
Index: gcc.llvm.master/gcc/llvm-convert.cpp
===================================================================
--- gcc.llvm.master.orig/gcc/llvm-convert.cpp	2007-09-06 11:23:08.000000000 +0200
+++ gcc.llvm.master/gcc/llvm-convert.cpp	2007-09-06 11:28:05.000000000 +0200
@@ -4342,9 +4342,7 @@
   case BUILT_IN_FROB_RETURN_ADDR:
    return EmitBuiltinFrobReturnAddr(exp, Result);
   case BUILT_IN_INIT_TRAMPOLINE:
-    return EmitBuiltinInitTrampoline(exp);
-  case BUILT_IN_ADJUST_TRAMPOLINE:
-    return EmitBuiltinAdjustTrampoline(exp, Result);
+    return EmitBuiltinInitTrampoline(exp, Result);
 
   // Builtins used by the exception handling runtime.
   case BUILT_IN_DWARF_CFA:
@@ -5004,7 +5002,7 @@
   return true;
 }
 
-bool TreeToLLVM::EmitBuiltinInitTrampoline(tree exp) {
+bool TreeToLLVM::EmitBuiltinInitTrampoline(tree exp, Value *&Result) {
   tree arglist = TREE_OPERAND(exp, 1);
   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
                          VOID_TYPE))
@@ -5025,22 +5023,7 @@
 
   Function *Intr = Intrinsic::getDeclaration(TheModule,
                                              Intrinsic::init_trampoline);
-  Builder.CreateCall(Intr, Ops, Ops+3);
-  return true;
-}
-
-bool TreeToLLVM::EmitBuiltinAdjustTrampoline(tree exp, Value *&Result) {
-  tree arglist = TREE_OPERAND(exp, 1);
-  if (!validate_arglist(arglist, POINTER_TYPE, VOID_TYPE))
-    return false;
-
-  Value *Tramp = Emit(TREE_VALUE(arglist), 0);
-  Tramp = CastToType(Instruction::BitCast, Tramp,
-                     PointerType::get(Type::Int8Ty));
-
-  Function *Intr = Intrinsic::getDeclaration(TheModule,
-                                             Intrinsic::adjust_trampoline);
-  Result = Builder.CreateCall(Intr, Tramp, "adj");
+  Result = Builder.CreateCall(Intr, Ops, Ops+3, "tramp");
   return true;
 }
 
Index: gcc.llvm.master/gcc/llvm-internal.h
===================================================================
--- gcc.llvm.master.orig/gcc/llvm-internal.h	2007-09-06 11:16:22.000000000 +0200
+++ gcc.llvm.master/gcc/llvm-internal.h	2007-09-06 11:23:08.000000000 +0200
@@ -582,8 +582,7 @@
   bool EmitBuiltinEHReturn(tree_node *exp, Value *&Result);
   bool EmitBuiltinInitDwarfRegSizes(tree_node *exp, Value *&Result);
   bool EmitBuiltinUnwindInit(tree_node *exp, Value *&Result);
-  bool EmitBuiltinInitTrampoline(tree_node *exp);
-  bool EmitBuiltinAdjustTrampoline(tree_node *exp, Value *&Result);
+  bool EmitBuiltinInitTrampoline(tree_node *exp, Value *&Result);
 
   // Complex Math Expressions.
   void EmitLoadFromComplex(Value *&Real, Value *&Imag, Value *SrcComplex,
Index: gcc.llvm.master/gcc/tree-nested.c
===================================================================
--- gcc.llvm.master.orig/gcc/tree-nested.c	2007-09-06 11:23:07.000000000 +0200
+++ gcc.llvm.master/gcc/tree-nested.c	2007-09-06 11:23:08.000000000 +0200
@@ -399,16 +399,20 @@
 
 /* Build or return the type used to represent a nested function trampoline.  */
 
-static GTY(()) tree trampoline_type;
+/* LLVM local */
+static GTY(()) tree trampoline_storage_type;
 
 static tree
-get_trampoline_type (void)
+/* LLVM local */
+get_trampoline_storage_type (void)
 {
   tree record, t;
   unsigned align, size;
 
-  if (trampoline_type)
-    return trampoline_type;
+  /* LLVM local begin */
+  if (trampoline_storage_type)
+    return trampoline_storage_type;
+  /* LLVM local end */
 
   align = TRAMPOLINE_ALIGNMENT;
   size = TRAMPOLINE_SIZE;
@@ -464,8 +468,9 @@
     {
       field = make_node (FIELD_DECL);
       DECL_NAME (field) = DECL_NAME (decl);
-      TREE_TYPE (field) = get_trampoline_type ();
-      TREE_ADDRESSABLE (field) = 1;
+      /* LLVM local begin */
+      TREE_TYPE (field) = TYPE_POINTER_TO (TREE_TYPE (decl));
+      /* LLVM local end */
 
       insert_field_into_struct (get_frame_type (info), field);
 
@@ -1286,17 +1291,14 @@
 {
   struct walk_stmt_info *wi = data;
   struct nesting_info *info = wi->info, *i;
-  tree t = *tp, decl, target_context, x, arg;
+  /* LLVM local */
+  tree t = *tp, decl, target_context, x;
 
   *walk_subtrees = 0;
   switch (TREE_CODE (t))
     {
     case ADDR_EXPR:
-      /* Build
-	   T.1 = &CHAIN->tramp;
-	   T.2 = __builtin_adjust_trampoline (T.1);
-	   T.3 = (func_type)T.2;
-      */
+      /* LLVM local deleted 5 lines */
 
       decl = TREE_OPERAND (t, 0);
       if (TREE_CODE (decl) != FUNCTION_DECL)
@@ -1316,22 +1318,12 @@
 	 we need to insert the trampoline.  */
       for (i = info; i->context != target_context; i = i->outer)
 	continue;
-      x = lookup_tramp_for_decl (i, decl, INSERT);
+      /* LLVM local begin */
 
-      /* Compute the address of the field holding the trampoline.  */
+      /* Lookup the trampoline.  */
+      x = lookup_tramp_for_decl (i, decl, INSERT);
       x = get_frame_field (info, target_context, x, &wi->tsi);
-      x = build_addr (x);
-      x = tsi_gimplify_val (info, x, &wi->tsi);
-      arg = tree_cons (NULL, x, NULL);
-
-      /* Do machine-specific ugliness.  Normally this will involve
-	 computing extra alignment, but it can really be anything.  */
-      x = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE];
-      x = build_function_call_expr (x, arg);
-      x = init_tmp_var (info, x, &wi->tsi);
-
-      /* Cast back to the proper function type.  */
-      x = build1 (NOP_EXPR, TREE_TYPE (t), x);
+      /* LLVM local end */
       x = init_tmp_var (info, x, &wi->tsi);
 
       *tp = x;
@@ -1483,7 +1475,8 @@
       struct nesting_info *i;
       for (i = root->inner; i ; i = i->next)
 	{
-	  tree arg, x, field;
+	  /* LLVM local */
+	  tree arg, x, y, field;
 
 	  field = lookup_tramp_for_decl (root, i->context, NO_INSERT);
 	  if (!field)
@@ -1498,13 +1491,27 @@
 	  x = build_addr (i->context);
 	  arg = tree_cons (NULL, x, arg);
 
-	  x = build (COMPONENT_REF, TREE_TYPE (field),
-		     root->frame_decl, field, NULL_TREE);
-	  x = build_addr (x);
+	  /* LLVM local begin */
+	  /* Create a local variable to hold the trampoline code.  */
+	  y = create_tmp_var_for (root, get_trampoline_storage_type(),
+				  "TRAMP");
+	  x = build_addr (y);
 	  arg = tree_cons (NULL, x, arg);
 
 	  x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE];
 	  x = build_function_call_expr (x, arg);
+	  y = create_tmp_var_for (root, TREE_TYPE(x), NULL);
+	  x = build2 (MODIFY_EXPR, TREE_TYPE (x), y, x);
+	  append_to_statement_list (x, &stmt_list);
+
+	  /* Cast back to the proper function type.  */
+	  y = build1 (NOP_EXPR, TREE_TYPE (field), y);
+
+	  /* Initialize the trampoline.  */
+	  x = build3 (COMPONENT_REF, TREE_TYPE (field),
+		      root->frame_decl, field, NULL_TREE);
+	  x = build2 (MODIFY_EXPR, TREE_TYPE (field), x, y);
+	  /* LLVM local end */
 
 	  append_to_statement_list (x, &stmt_list);
 	}
Index: gcc.llvm.master/gcc/tree.c
===================================================================
--- gcc.llvm.master.orig/gcc/tree.c	2007-09-06 11:23:06.000000000 +0200
+++ gcc.llvm.master/gcc/tree.c	2007-09-06 11:23:08.000000000 +0200
@@ -6029,17 +6029,12 @@
   tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
   tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
   tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
-  ftype = build_function_type (void_type_node, tmp);
+  /* LLVM local begin */
+  ftype = build_function_type (ptr_type_node, tmp);
   local_define_builtin ("__builtin_init_trampoline", ftype,
 			BUILT_IN_INIT_TRAMPOLINE,
 			"__builtin_init_trampoline", ECF_NOTHROW);
-
-  tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
-  ftype = build_function_type (ptr_type_node, tmp);
-  local_define_builtin ("__builtin_adjust_trampoline", ftype,
-			BUILT_IN_ADJUST_TRAMPOLINE,
-			"__builtin_adjust_trampoline",
-			ECF_CONST | ECF_NOTHROW);
+  /* LLVM local end */
 
   tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
   tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
Index: gcc-4.2.llvm/gcc/builtins.c
===================================================================
--- gcc-4.2.llvm.orig/gcc/builtins.c	2007-08-12 17:16:59.000000000 +0200
+++ gcc-4.2.llvm/gcc/builtins.c	2007-09-08 23:26:53.000000000 +0200
@@ -5281,25 +5281,14 @@
   trampolines_created = 1;
   INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
 
-  return const0_rtx;
-}
-
-static rtx
-expand_builtin_adjust_trampoline (tree arglist)
-{
-  rtx tramp;
-
-  if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
-    return NULL_RTX;
-
-  tramp = expand_normal (TREE_VALUE (arglist));
-  tramp = round_trampoline_addr (tramp);
+/* LLVM local begin */
 #ifdef TRAMPOLINE_ADJUST_ADDRESS
-  TRAMPOLINE_ADJUST_ADDRESS (tramp);
+  TRAMPOLINE_ADJUST_ADDRESS (r_tramp);
 #endif
 
-  return tramp;
+  return r_tramp;
 }
+/* LLVM local end */
 
 /* Expand a call to the built-in signbit, signbitf or signbitl function.
    Return NULL_RTX if a normal call should be emitted rather than expanding
@@ -6285,8 +6274,7 @@
 
     case BUILT_IN_INIT_TRAMPOLINE:
       return expand_builtin_init_trampoline (arglist);
-    case BUILT_IN_ADJUST_TRAMPOLINE:
-      return expand_builtin_adjust_trampoline (arglist);
+    /* LLVM local deleted 2 lines */
 
     case BUILT_IN_FORK:
     case BUILT_IN_EXECL:
Index: gcc-4.2.llvm/gcc/builtins.def
===================================================================
--- gcc-4.2.llvm.orig/gcc/builtins.def	2007-07-17 16:42:19.000000000 +0200
+++ gcc-4.2.llvm/gcc/builtins.def	2007-09-08 23:26:53.000000000 +0200
@@ -691,7 +691,7 @@
 
 /* Implementing nested functions.  */
 DEF_BUILTIN_STUB (BUILT_IN_INIT_TRAMPOLINE, "__builtin_init_trampoline")
-DEF_BUILTIN_STUB (BUILT_IN_ADJUST_TRAMPOLINE, "__builtin_adjust_trampoline")
+/* LLVM local deleted 1 line */
 DEF_BUILTIN_STUB (BUILT_IN_NONLOCAL_GOTO, "__builtin_nonlocal_goto")
 
 /* Implementing __builtin_setjmp.  */
Index: gcc-4.2.llvm/gcc/llvm-convert.cpp
===================================================================
--- gcc-4.2.llvm.orig/gcc/llvm-convert.cpp	2007-09-08 23:18:10.000000000 +0200
+++ gcc-4.2.llvm/gcc/llvm-convert.cpp	2007-09-08 23:26:53.000000000 +0200
@@ -3845,9 +3845,7 @@
   case BUILT_IN_FROB_RETURN_ADDR:
    return EmitBuiltinFrobReturnAddr(exp, Result);
   case BUILT_IN_INIT_TRAMPOLINE:
-    return EmitBuiltinInitTrampoline(exp);
-  case BUILT_IN_ADJUST_TRAMPOLINE:
-    return EmitBuiltinAdjustTrampoline(exp, Result);
+    return EmitBuiltinInitTrampoline(exp, Result);
 
   // Builtins used by the exception handling runtime.
   case BUILT_IN_DWARF_CFA:
@@ -4513,7 +4511,7 @@
   return true;
 }
 
-bool TreeToLLVM::EmitBuiltinInitTrampoline(tree exp) {
+bool TreeToLLVM::EmitBuiltinInitTrampoline(tree exp, Value *&Result) {
   tree arglist = TREE_OPERAND(exp, 1);
   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
                          VOID_TYPE))
@@ -4534,22 +4532,7 @@
 
   Function *Intr = Intrinsic::getDeclaration(TheModule,
                                              Intrinsic::init_trampoline);
-  Builder.CreateCall(Intr, Ops, Ops+3);
-  return true;
-}
-
-bool TreeToLLVM::EmitBuiltinAdjustTrampoline(tree exp, Value *&Result) {
-  tree arglist = TREE_OPERAND(exp, 1);
-  if (!validate_arglist(arglist, POINTER_TYPE, VOID_TYPE))
-    return false;
-
-  Value *Tramp = Emit(TREE_VALUE(arglist), 0);
-  Tramp = CastToType(Instruction::BitCast, Tramp,
-                     PointerType::get(Type::Int8Ty));
-
-  Function *Intr = Intrinsic::getDeclaration(TheModule,
-                                             Intrinsic::adjust_trampoline);
-  Result = Builder.CreateCall(Intr, Tramp, "adj");
+  Result = Builder.CreateCall(Intr, Ops, Ops+3, "tramp");
   return true;
 }
 
Index: gcc-4.2.llvm/gcc/llvm-internal.h
===================================================================
--- gcc-4.2.llvm.orig/gcc/llvm-internal.h	2007-09-08 23:18:10.000000000 +0200
+++ gcc-4.2.llvm/gcc/llvm-internal.h	2007-09-08 23:26:53.000000000 +0200
@@ -527,8 +527,7 @@
   bool EmitBuiltinEHReturn(tree_node *exp, Value *&Result);
   bool EmitBuiltinInitDwarfRegSizes(tree_node *exp, Value *&Result);
   bool EmitBuiltinUnwindInit(tree_node *exp, Value *&Result);
-  bool EmitBuiltinInitTrampoline(tree_node *exp);
-  bool EmitBuiltinAdjustTrampoline(tree_node *exp, Value *&Result);
+  bool EmitBuiltinInitTrampoline(tree_node *exp, Value *&Result);
 
   // Complex Math Expressions.
   void EmitLoadFromComplex(Value *&Real, Value *&Imag, Value *SrcComplex,
Index: gcc-4.2.llvm/gcc/tree-nested.c
===================================================================
--- gcc-4.2.llvm.orig/gcc/tree-nested.c	2007-07-27 15:27:04.000000000 +0200
+++ gcc-4.2.llvm/gcc/tree-nested.c	2007-09-08 23:26:53.000000000 +0200
@@ -425,16 +425,20 @@
 
 /* Build or return the type used to represent a nested function trampoline.  */
 
-static GTY(()) tree trampoline_type;
+/* LLVM local */
+static GTY(()) tree trampoline_storage_type;
 
 static tree
-get_trampoline_type (void)
+/* LLVM local */
+get_trampoline_storage_type (void)
 {
   tree record, t;
   unsigned align, size;
 
-  if (trampoline_type)
-    return trampoline_type;
+  /* LLVM local begin */
+  if (trampoline_storage_type)
+    return trampoline_storage_type;
+  /* LLVM local end */
 
   align = TRAMPOLINE_ALIGNMENT;
   size = TRAMPOLINE_SIZE;
@@ -490,8 +494,9 @@
     {
       field = make_node (FIELD_DECL);
       DECL_NAME (field) = DECL_NAME (decl);
-      TREE_TYPE (field) = get_trampoline_type ();
-      TREE_ADDRESSABLE (field) = 1;
+      /* LLVM local begin */
+      TREE_TYPE (field) = TYPE_POINTER_TO (TREE_TYPE (decl));
+      /* LLVM local end */
 
       insert_field_into_struct (get_frame_type (info), field);
 
@@ -1618,17 +1623,14 @@
 {
   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *info = wi->info, *i;
-  tree t = *tp, decl, target_context, x, arg;
+  /* LLVM local */
+  tree t = *tp, decl, target_context, x;
 
   *walk_subtrees = 0;
   switch (TREE_CODE (t))
     {
     case ADDR_EXPR:
-      /* Build
-	   T.1 = &CHAIN->tramp;
-	   T.2 = __builtin_adjust_trampoline (T.1);
-	   T.3 = (func_type)T.2;
-      */
+      /* LLVM local deleted 5 lines */
 
       decl = TREE_OPERAND (t, 0);
       if (TREE_CODE (decl) != FUNCTION_DECL)
@@ -1648,22 +1650,12 @@
 	 we need to insert the trampoline.  */
       for (i = info; i->context != target_context; i = i->outer)
 	continue;
-      x = lookup_tramp_for_decl (i, decl, INSERT);
+      /* LLVM local begin */
 
-      /* Compute the address of the field holding the trampoline.  */
+      /* Lookup the trampoline.  */
+      x = lookup_tramp_for_decl (i, decl, INSERT);
       x = get_frame_field (info, target_context, x, &wi->tsi);
-      x = build_addr (x, target_context);
-      x = tsi_gimplify_val (info, x, &wi->tsi);
-      arg = tree_cons (NULL, x, NULL);
-
-      /* Do machine-specific ugliness.  Normally this will involve
-	 computing extra alignment, but it can really be anything.  */
-      x = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE];
-      x = build_function_call_expr (x, arg);
-      x = init_tmp_var (info, x, &wi->tsi);
-
-      /* Cast back to the proper function type.  */
-      x = build1 (NOP_EXPR, TREE_TYPE (t), x);
+      /* LLVM local end */
       x = init_tmp_var (info, x, &wi->tsi);
 
       *tp = x;
@@ -1858,7 +1850,8 @@
       struct nesting_info *i;
       for (i = root->inner; i ; i = i->next)
 	{
-	  tree arg, x, field;
+	  /* LLVM local */
+	  tree arg, x, y, field;
 
 	  field = lookup_tramp_for_decl (root, i->context, NO_INSERT);
 	  if (!field)
@@ -1873,13 +1866,27 @@
 	  x = build_addr (i->context, context);
 	  arg = tree_cons (NULL, x, arg);
 
-	  x = build3 (COMPONENT_REF, TREE_TYPE (field),
-		      root->frame_decl, field, NULL_TREE);
-	  x = build_addr (x, context);
+	  /* LLVM local begin */
+	  /* Create a local variable to hold the trampoline code.  */
+	  y = create_tmp_var_for (root, get_trampoline_storage_type(),
+				  "TRAMP");
+	  x = build_addr (y, context);
 	  arg = tree_cons (NULL, x, arg);
 
 	  x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE];
 	  x = build_function_call_expr (x, arg);
+	  y = create_tmp_var_for (root, TREE_TYPE(x), NULL);
+	  x = build2 (MODIFY_EXPR, TREE_TYPE (x), y, x);
+	  append_to_statement_list (x, &stmt_list);
+
+	  /* Cast back to the proper function type.  */
+	  y = build1 (NOP_EXPR, TREE_TYPE (field), y);
+
+	  /* Initialize the trampoline.  */
+	  x = build3 (COMPONENT_REF, TREE_TYPE (field),
+		      root->frame_decl, field, NULL_TREE);
+	  x = build2 (MODIFY_EXPR, TREE_TYPE (field), x, y);
+	  /* LLVM local end */
 
 	  append_to_statement_list (x, &stmt_list);
 	}
Index: gcc-4.2.llvm/gcc/tree.c
===================================================================
--- gcc-4.2.llvm.orig/gcc/tree.c	2007-08-12 17:16:58.000000000 +0200
+++ gcc-4.2.llvm/gcc/tree.c	2007-09-08 23:26:53.000000000 +0200
@@ -6772,17 +6772,12 @@
   tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
   tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
   tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
-  ftype = build_function_type (void_type_node, tmp);
+  /* LLVM local begin */
+  ftype = build_function_type (ptr_type_node, tmp);
   local_define_builtin ("__builtin_init_trampoline", ftype,
 			BUILT_IN_INIT_TRAMPOLINE,
 			"__builtin_init_trampoline", ECF_NOTHROW);
-
-  tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
-  ftype = build_function_type (ptr_type_node, tmp);
-  local_define_builtin ("__builtin_adjust_trampoline", ftype,
-			BUILT_IN_ADJUST_TRAMPOLINE,
-			"__builtin_adjust_trampoline",
-			ECF_CONST | ECF_NOTHROW);
+  /* LLVM local end */
 
   tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
   tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
Index: llvm.master/lib/Transforms/Scalar/InstructionCombining.cpp
===================================================================
--- llvm.master.orig/lib/Transforms/Scalar/InstructionCombining.cpp	2007-09-06 19:25:38.000000000 +0200
+++ llvm.master/lib/Transforms/Scalar/InstructionCombining.cpp	2007-09-08 22:13:35.000000000 +0200
@@ -39,6 +39,7 @@
 #include "llvm/Pass.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/GlobalVariable.h"
+#include "llvm/ParameterAttributes.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
@@ -7855,6 +7856,142 @@
       }
   }
 
+  if (BitCastInst *BC = dyn_cast<BitCastInst>(Callee)) {
+    IntrinsicInst *In = dyn_cast<IntrinsicInst>(BC->getOperand(0));
+    if (In && In->getIntrinsicID() == Intrinsic::init_trampoline) {
+      Function *NestF =
+        cast<Function>(IntrinsicInst::StripPointerCasts(In->getOperand(2)));
+      const PointerType *NestPTy = cast<PointerType>(NestF->getType());
+      const FunctionType *NestFTy = cast<FunctionType>(NestPTy->getElementType());
+
+      if (const ParamAttrsList *NestAttrs = NestFTy->getParamAttrs()) {
+        unsigned NestIdx = 1;
+        const Type *NestTy = 0;
+        uint16_t NestAttr;
+
+        Instruction *Caller = CS.getInstruction();
+
+        // Look for a parameter marked with the 'nest' attribute.
+        for (FunctionType::param_iterator I = NestFTy->param_begin(),
+             E = NestFTy->param_end(); I != E; ++NestIdx, ++I)
+          if (NestAttrs->paramHasAttr(NestIdx, ParamAttr::Nest)) {
+            // Record the parameter type and any other attributes.
+            NestTy = *I;
+            NestAttr = NestAttrs->getParamAttrs(NestIdx);
+            break;
+          }
+
+        if (NestTy) {
+          std::vector<Value*> NewArgs;
+          NewArgs.reserve(unsigned(CS.arg_end()-CS.arg_begin())+1);
+
+          // Insert the nest argument into the call argument list, which may
+          // mean appending it.
+          {
+            unsigned Idx = 1;
+            CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
+            do {
+              if (Idx == NestIdx) {
+                // Add the chain argument.
+                Value *NestVal = In->getOperand(3);
+                if (NestVal->getType() != NestTy)
+                  NestVal = new BitCastInst(NestVal, NestTy, "nest", Caller);
+                NewArgs.push_back(NestVal);
+              }
+
+              if (I == E)
+                break;
+
+              // Add the original argument.
+              NewArgs.push_back(*I);
+
+              ++Idx, ++I;
+            } while (1);
+          }
+
+          // The trampoline may have been bitcast to a bogus type (FTy).
+          // Handle this by synthesizing a new function type, equal to FTy
+          // with the chain parameter inserted.  Likewise for attributes.
+
+          const ParamAttrsList *Attrs = FTy->getParamAttrs();
+          std::vector<const Type*> NewTypes;
+          ParamAttrsVector NewAttrs;
+          NewTypes.reserve(FTy->getNumParams()+1);
+
+          // Add any function result attributes.
+          uint16_t Attr = Attrs ? Attrs->getParamAttrs(0) : 0;
+          if (Attr)
+            NewAttrs.push_back (ParamAttrsWithIndex::get(0, Attr));
+
+          // Insert the chain's type into the list of parameter types, which may
+          // mean appending it.  Likewise for the chain's attributes.
+          {
+            unsigned Idx = 1;
+            FunctionType::param_iterator I = FTy->param_begin(),
+              E = FTy->param_end();
+
+            do {
+              if (Idx == NestIdx) {
+                // Add the chain's type and attributes.
+                NewTypes.push_back(NestTy);
+                NewAttrs.push_back(ParamAttrsWithIndex::get(NestIdx, NestAttr));
+              }
+
+              if (I == E)
+                break;
+
+              // Add the original type and attributes.
+              NewTypes.push_back(*I);
+              Attr = Attrs ? Attrs->getParamAttrs(Idx) : 0;
+              if (Attr)
+                NewAttrs.push_back
+                  (ParamAttrsWithIndex::get(Idx + (Idx >= NestIdx), Attr));
+
+              ++Idx, ++I;
+            } while (1);
+          }
+
+          // Replace the trampoline call with a direct call.  Let the generic
+          // code sort out any function type mismatches.
+          FunctionType *NewFTy =
+            FunctionType::get(FTy->getReturnType(), NewTypes, FTy->isVarArg(),
+                              ParamAttrsList::get(NewAttrs));
+          Constant *NewCallee = NestF->getType() == PointerType::get(NewFTy) ?
+            NestF : ConstantExpr::getBitCast(NestF, PointerType::get(NewFTy));
+
+          Instruction *NewCaller;
+          if (InvokeInst *II = dyn_cast<InvokeInst>(Caller)) {
+            NewCaller = new InvokeInst(NewCallee, II->getNormalDest(),
+                                       II->getUnwindDest(), NewArgs.begin(),
+                                       NewArgs.end(), Caller->getName(),
+                                       Caller);
+            cast<InvokeInst>(NewCaller)->setCallingConv(II->getCallingConv());
+          } else {
+            NewCaller = new CallInst(NewCallee, NewArgs.begin(), NewArgs.end(),
+                                     Caller->getName(), Caller);
+            if (cast<CallInst>(Caller)->isTailCall())
+              cast<CallInst>(NewCaller)->setTailCall();
+            cast<CallInst>(NewCaller)->
+              setCallingConv(cast<CallInst>(Caller)->getCallingConv());
+          }
+          if (Caller->getType() != Type::VoidTy && !Caller->use_empty())
+            Caller->replaceAllUsesWith(NewCaller);
+          Caller->eraseFromParent();
+          RemoveFromWorkList(Caller);
+          return 0;
+        }
+      }
+
+      // Replace the trampoline call with a direct call.  Since there is no
+      // 'nest' parameter, there is no need to adjust the argument list.  Let
+      // the generic code sort out any function type mismatches.
+      Constant *NewCallee = NestF->getType() == PTy ?
+        NestF : ConstantExpr::getBitCast(NestF, PTy);
+      CS.setCalledFunction(NewCallee);
+      Changed = true;
+    }
+  }
+
   return Changed ? CS.getInstruction() : 0;
 }
 
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Reply via email to