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)) { _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits