[llvm-commits] [123562] Initial support for nested functions ( but not non-local gotos or trampolines).

clattner at apple.com clattner at apple.com
Wed Feb 7 15:28:05 PST 2007


Revision: 123562
Author:   clattner
Date:     2007-02-07 15:28:05 -0800 (Wed, 07 Feb 2007)

Log Message:
-----------
Initial support for nested functions (but not non-local gotos or trampolines).
Patch by Duncan Sands!

This implements llvm/test/CFrontend/2007-02-05-nested.c

Modified Paths:
--------------
    apple-local/branches/llvm/gcc/llvm-backend.cpp
    apple-local/branches/llvm/gcc/llvm-convert.cpp
    apple-local/branches/llvm/gcc/llvm-internal.h
    apple-local/branches/llvm/gcc/llvm-types.cpp

Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-backend.cpp	2007-02-07 23:12:06 UTC (rev 123561)
+++ apple-local/branches/llvm/gcc/llvm-backend.cpp	2007-02-07 23:28:05 UTC (rev 123562)
@@ -433,9 +433,9 @@
 // llvm_emit_code_for_current_function - Top level interface for emitting a
 // function to the .s file.
 void llvm_emit_code_for_current_function(tree fndecl) {
-  if (cfun->static_chain_decl || cfun->nonlocal_goto_save_area)
-    sorry("%Jnested functions not supported by LLVM", fndecl);
-  
+  if (cfun->nonlocal_goto_save_area)
+    sorry("%Jnon-local gotos not supported by LLVM", fndecl);
+
   if (errorcount || sorrycount) {
     TREE_ASM_WRITTEN(fndecl) = 1;
     return;  // Do not process broken code.
@@ -709,7 +709,7 @@
     if (FnEntry == 0) {
       unsigned CC;
       const FunctionType *Ty = 
-        TheTypeConverter->ConvertFunctionType(TREE_TYPE(decl), CC);
+        TheTypeConverter->ConvertFunctionType(TREE_TYPE(decl), NULL, CC);
       FnEntry = new Function(Ty, Function::ExternalLinkage, Name, TheModule);
       FnEntry->setCallingConv(CC);
 

Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-convert.cpp	2007-02-07 23:12:06 UTC (rev 123561)
+++ apple-local/branches/llvm/gcc/llvm-convert.cpp	2007-02-07 23:28:05 UTC (rev 123562)
@@ -260,6 +260,7 @@
     Name = IDENTIFIER_POINTER(ID);
   
   // Determine the FunctionType and calling convention for this function.
+  tree static_chain = cfun->static_chain_decl;
   const FunctionType *FTy;
   unsigned CallingConv;
   
@@ -271,16 +272,19 @@
   if (TYPE_ARG_TYPES(TREE_TYPE(FnDecl)) == 0) {
     FTy = TheTypeConverter->ConvertArgListToFnType(TREE_TYPE(TREE_TYPE(FnDecl)),
                                                    DECL_ARGUMENTS(FnDecl),
+                                                   static_chain,
                                                    CallingConv);
 #ifdef TARGET_ADJUST_LLVM_CC
     TARGET_ADJUST_LLVM_CC(CallingConv, TREE_TYPE(FnDecl));
 #endif
   } else {
     // Otherwise, just get the type from the function itself.
-    FTy = TheTypeConverter->ConvertFunctionType(TREE_TYPE(FnDecl), CallingConv);
+    FTy = TheTypeConverter->ConvertFunctionType(TREE_TYPE(FnDecl),
+						static_chain,
+						CallingConv);
   }
   
-  // If we've already see this function and created a prototype, and if the
+  // If we've already seen this function and created a prototype, and if the
   // proto has the right LLVM type, just use it.
   if (DECL_LLVM_SET_P(FnDecl) &&
       cast<PointerType>(DECL_LLVM(FnDecl)->getType())->getElementType() == FTy){
@@ -371,8 +375,11 @@
 
   // Handle the DECL_RESULT.
   ABIConverter.HandleReturnType(TREE_TYPE(TREE_TYPE(FnDecl)));
-  
-  for (tree Args = DECL_ARGUMENTS(FnDecl); Args; Args = TREE_CHAIN(Args)) {
+
+  // Prepend the static chain (if any) to the list of arguments.
+  tree Args = static_chain ? static_chain : DECL_ARGUMENTS(FnDecl);
+
+  while (Args) {
     const char *Name = "unnamed_arg";
     if (DECL_NAME(Args)) Name = IDENTIFIER_POINTER(DECL_NAME(Args));
 
@@ -400,6 +407,8 @@
       ABIConverter.HandleArgument(TREE_TYPE(Args));
       Client.clear();
     }
+
+    Args = Args == static_chain ? DECL_ARGUMENTS(FnDecl) : TREE_CHAIN(Args);
   }
 
   // If this is not a void-returning function, initialize the RESULT_DECL.
@@ -407,9 +416,9 @@
       !DECL_LLVM_SET_P(DECL_RESULT(FnDecl)))
     EmitAutomaticVariableDecl(DECL_RESULT(FnDecl));
 
-  // If this function has nested functions, we should handle the static chain,
-  // and handle a potential nonlocal_goto_save_area.
-  if (cfun->static_chain_decl || cfun->nonlocal_goto_save_area) {
+  // If this function has nested functions, we should handle a potential
+  // nonlocal_goto_save_area.
+  if (cfun->nonlocal_goto_save_area) {
     // Not supported yet.
   }
   
@@ -1869,9 +1878,23 @@
     if (EmitBuiltinCall(exp, fndecl, DestLoc, Res))
       return Res;
   }
-  
+
   Value *Callee = Emit(TREE_OPERAND(exp, 0), 0);
 
+  if (TREE_OPERAND(exp, 2)) {
+    // This is a direct call to a function using a static chain.  We need to
+    // change the function type to one with an extra parameter for the chain.
+    assert(fndecl && "Indirect static chain call!");
+    tree function_type = TYPE_MAIN_VARIANT(TREE_TYPE(fndecl));
+    tree static_chain = TREE_OPERAND(exp, 2);
+
+    unsigned CallingConv;
+    const Type *Ty = TheTypeConverter->ConvertFunctionType(function_type,
+                                                           static_chain,
+                                                           CallingConv);
+    Callee = CastToType(Instruction::BitCast, Callee, PointerType::get(Ty));
+  }
+
   //EmitCall(exp, DestLoc);
   Value *Result = EmitCallOf(Callee, exp, DestLoc);
 
@@ -2032,7 +2055,11 @@
 
   // Handle the result, including struct returns.
   ABIConverter.HandleReturnType(TREE_TYPE(exp));
-  
+
+  // Pass the static chain, if any, as the first parameter.
+  if (TREE_OPERAND(exp, 2))
+    CallOperands.push_back (Emit(TREE_OPERAND(exp, 2), 0));
+
   // Loop over the arguments, expanding them and adding them to the op list.
   const PointerType *PFTy = cast<PointerType>(Callee->getType());
   const FunctionType *FTy = cast<FunctionType>(PFTy->getElementType());

Modified: apple-local/branches/llvm/gcc/llvm-internal.h
===================================================================
--- apple-local/branches/llvm/gcc/llvm-internal.h	2007-02-07 23:12:06 UTC (rev 123561)
+++ apple-local/branches/llvm/gcc/llvm-internal.h	2007-02-07 23:28:05 UTC (rev 123562)
@@ -117,7 +117,8 @@
   /// ConvertFunctionType - Convert the specified FUNCTION_TYPE or METHOD_TYPE
   /// tree to an LLVM type.  This does the same thing that ConvertType does, but
   /// it also returns the function's LLVM calling convention.
-  const FunctionType *ConvertFunctionType(tree_node *type, 
+  const FunctionType *ConvertFunctionType(tree_node *type,
+                                          tree_node *static_chain,
                                           unsigned &CallingConv);
   
   /// ConvertArgListToFnType - Given a DECL_ARGUMENTS list on an GCC tree,
@@ -125,6 +126,7 @@
   /// turning "T foo(...)" functions into "T foo(void)" functions.
   const FunctionType *ConvertArgListToFnType(tree_node *retty,
                                              tree_node *arglist,
+                                             tree_node *static_chain,
                                              unsigned &CallingConv);
   
 private:

Modified: apple-local/branches/llvm/gcc/llvm-types.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-types.cpp	2007-02-07 23:12:06 UTC (rev 123561)
+++ apple-local/branches/llvm/gcc/llvm-types.cpp	2007-02-07 23:28:05 UTC (rev 123562)
@@ -416,7 +416,7 @@
       return Ty;
     
     unsigned CallingConv;
-    return TypeDB.setType(type, ConvertFunctionType(type, CallingConv));
+    return TypeDB.setType(type, ConvertFunctionType(type, NULL, CallingConv));
   }
   case ARRAY_TYPE: {
     if (const Type *Ty = GET_TYPE_LLVM(type))
@@ -530,7 +530,8 @@
 /// fills in Result with the argument types for the function.  It returns the
 /// specified result type for the function.
 const FunctionType *TypeConverter::
-ConvertArgListToFnType(tree ReturnType, tree Args, unsigned &CallingConv) {
+ConvertArgListToFnType(tree ReturnType, tree Args, tree static_chain,
+                       unsigned &CallingConv) {
   std::vector<const Type*> ArgTys;
   const Type *RetTy;
   
@@ -538,12 +539,28 @@
   TheLLVMABI<FunctionTypeConversion> ABIConverter(Client);
   
   ABIConverter.HandleReturnType(ReturnType);
+
+  if (static_chain)
+    // Pass the static chain as the first parameter.
+    ABIConverter.HandleArgument(TREE_TYPE(static_chain));
+
   for (; Args && TREE_TYPE(Args) != void_type_node; Args = TREE_CHAIN(Args))
     ABIConverter.HandleArgument(TREE_TYPE(Args));
-  return FunctionType::get(RetTy, ArgTys, false);
+
+  FunctionType::ParamAttrsList ParamAttrs;
+
+  if (static_chain) {
+    // Something for the return type.
+    ParamAttrs.push_back(FunctionType::NoAttributeSet);
+    // Pass the static chain in a register.
+    ParamAttrs.push_back(FunctionType::InRegAttribute);
+  }
+
+  return FunctionType::get(RetTy, ArgTys, false, ParamAttrs);
 }
 
-const FunctionType *TypeConverter::ConvertFunctionType(tree type, 
+const FunctionType *TypeConverter::ConvertFunctionType(tree type,
+                                                       tree static_chain,
                                                        unsigned &CallingConv) {
   const Type *RetTy = 0;
   std::vector<const Type*> ArgTypes;
@@ -557,7 +574,11 @@
 #ifdef TARGET_ADJUST_LLVM_CC
   TARGET_ADJUST_LLVM_CC(CallingConv, type);
 #endif
-    
+
+  if (static_chain)
+    // Pass the static chain as the first parameter.
+    ABIConverter.HandleArgument(TREE_TYPE(static_chain));
+
   // Loop over all of the arguments, adding them as we go.
   tree Args = TYPE_ARG_TYPES(type);
   for (; Args && TREE_VALUE(Args) != void_type_node; Args = TREE_CHAIN(Args)){
@@ -613,6 +634,10 @@
   LLVM_TARGET_INIT_REGPARM(lparam, type);
 #endif // LLVM_TARGET_ENABLE_REGPARM
 
+  if (static_chain)
+    // Pass the static chain in a register.
+    ParamAttrs.push_back(FunctionType::InRegAttribute);
+
   for (tree Args = TYPE_ARG_TYPES(type);
        Args && TREE_VALUE(Args) != void_type_node;
        Args = TREE_CHAIN(Args)) {





More information about the llvm-commits mailing list