[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