[llvm-commits] [dragonegg] r126079 - in /dragonegg/trunk: llvm-backend.cpp llvm-convert.cpp llvm-internal.h llvm-types.cpp

Duncan Sands baldrick at free.fr
Sun Feb 20 04:15:27 PST 2011


Author: baldrick
Date: Sun Feb 20 06:15:27 2011
New Revision: 126079

URL: http://llvm.org/viewvc/llvm-project?rev=126079&view=rev
Log:
The Fortran frontend likes to declare intrinsics as taking, say, one argument
but calls them with more arguments.  This is the case for _gfortran_shape_4
for example.  In llvm-gcc this was fixed by having the Fortran frontend declare
intrinsics and externals as taking a variable number of arguments.  This patch
obtains the same effect without modifying the Fortran frontend by having all
prototypes be declared varargs (except for builtins, such as malloc and free;
these are different to Fortran intrinsics) when compiling Fortran.

Modified:
    dragonegg/trunk/llvm-backend.cpp
    dragonegg/trunk/llvm-convert.cpp
    dragonegg/trunk/llvm-internal.h
    dragonegg/trunk/llvm-types.cpp

Modified: dragonegg/trunk/llvm-backend.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-backend.cpp?rev=126079&r1=126078&r2=126079&view=diff
==============================================================================
--- dragonegg/trunk/llvm-backend.cpp (original)
+++ dragonegg/trunk/llvm-backend.cpp Sun Feb 20 06:15:27 2011
@@ -509,6 +509,11 @@
 /// "T foo() {}" will be treated like "T foo(void) {}" and not "T foo(...) {}".
 bool flag_vararg_requires_arguments;
 
+/// flag_force_vararg_prototypes - Force prototypes to take a variable number of
+/// arguments (...).  This is helpful if the language front-end sometimes emits
+/// calls where the call arguments do not match the callee function declaration.
+bool flag_force_vararg_prototypes;
+
 /// InstallLanguageSettings - Do any language-specific back-end configuration.
 static void InstallLanguageSettings() {
   // The principal here is that not doing any language-specific configuration
@@ -524,6 +529,7 @@
   } else if (LanguageName == "GNU C++") {
     flag_odr = true; // C++ obeys the one-definition-rule
   } else if (LanguageName == "GNU Fortran") {
+    flag_force_vararg_prototypes = true;
   } else if (LanguageName == "GNU GIMPLE") { // LTO gold plugin
   } else if (LanguageName == "GNU Java") {
   } else if (LanguageName == "GNU Objective-C") {

Modified: dragonegg/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-convert.cpp?rev=126079&r1=126078&r2=126079&view=diff
==============================================================================
--- dragonegg/trunk/llvm-convert.cpp (original)
+++ dragonegg/trunk/llvm-convert.cpp Sun Feb 20 06:15:27 2011
@@ -541,6 +541,8 @@
   CallingConv::ID CallingConv;
   AttrListPtr PAL;
 
+  bool getFunctionTypeFromArgList = false;
+
   // If the function has no arguments and is varargs (...), turn it into a
   // non-varargs function by scanning the param list for the function.  This
   // allows C functions declared as "T foo() {}" to be treated like
@@ -549,18 +551,30 @@
   //
   // Note that we only do this in C/Objective-C.  Doing this in C++ for
   // functions explicitly declared as taking (...) is bad.
-  if (TYPE_ARG_TYPES(TREE_TYPE(FnDecl)) == 0 && flag_vararg_requires_arguments){
+  if (TYPE_ARG_TYPES(TREE_TYPE(FnDecl)) == 0 && flag_vararg_requires_arguments)
+    getFunctionTypeFromArgList = true;
+
+  // When forcing vararg prototypes ensure that the function only gets a varargs
+  // part if it was originally declared varargs.
+  if (flag_force_vararg_prototypes) {
+    tree Args = TYPE_ARG_TYPES(TREE_TYPE(FnDecl));
+    while (Args && TREE_VALUE(Args) != void_type_node)
+      Args = TREE_CHAIN(Args);
+    if (Args != 0)
+      getFunctionTypeFromArgList = true;
+  }
+
+  if (getFunctionTypeFromArgList)
     FTy = TheTypeConverter->ConvertArgListToFnType(TREE_TYPE(FnDecl),
                                                    DECL_ARGUMENTS(FnDecl),
                                                    static_chain,
                                                    CallingConv, PAL);
-  } else {
+  else
     // Otherwise, just get the type from the function itself.
     FTy = TheTypeConverter->ConvertFunctionType(TREE_TYPE(FnDecl),
                                                 FnDecl,
                                                 static_chain,
                                                 CallingConv, PAL);
-  }
 
   // If we've already seen this function and created a prototype, and if the
   // proto has the right LLVM type, just use it.

Modified: dragonegg/trunk/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-internal.h?rev=126079&r1=126078&r2=126079&view=diff
==============================================================================
--- dragonegg/trunk/llvm-internal.h (original)
+++ dragonegg/trunk/llvm-internal.h Sun Feb 20 06:15:27 2011
@@ -93,6 +93,11 @@
 /// "T foo() {}" will be treated like "T foo(void) {}" and not "T foo(...) {}".
 extern bool flag_vararg_requires_arguments;
 
+/// flag_force_vararg_prototypes - Force prototypes to take a variable number of
+/// arguments (...).  This is helpful if the language front-end sometimes emits
+/// calls where the call arguments do not match the callee function declaration.
+extern bool flag_force_vararg_prototypes;
+
 /// AttributeUsedGlobals - The list of globals that are marked attribute(used).
 extern SmallSetVector<Constant *,32> AttributeUsedGlobals;
 

Modified: dragonegg/trunk/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-types.cpp?rev=126079&r1=126078&r2=126079&view=diff
==============================================================================
--- dragonegg/trunk/llvm-types.cpp (original)
+++ dragonegg/trunk/llvm-types.cpp Sun Feb 20 06:15:27 2011
@@ -1249,8 +1249,13 @@
   if (HasByVal)
     FnAttributes &= ~(Attribute::ReadNone | Attribute::ReadOnly);
 
-  // If the argument list ends with a void type node, it isn't vararg.
-  isVarArg = (Args == 0);
+  if (flag_force_vararg_prototypes)
+    // If forcing prototypes to be varargs, make all function types varargs
+    // except those for builtin functions.
+    isVarArg = decl ? !DECL_BUILT_IN(decl) : true;
+  else
+    // If the argument list ends with a void type node, it isn't vararg.
+    isVarArg = (Args == 0);
   assert(RetTy && "Return type not specified!");
 
   if (FnAttributes != Attribute::None)





More information about the llvm-commits mailing list