Hi rnk,

Add the -mmin-libc-version= flag to the driver and encode this into the module
level metadata.  This will permit the backend to make certain code generation
choices with the knowledge that the target code will run on a minimum libc
version.

On Windows, this will enable us to enable a number of C99 math routines that are
available in MSVCRT 12.0+, though this is certainly not limited to Windows.
There have been cases where code generation on the Linux targets could do
something slightly different if it knew what version of libc it was targeting.

The module level metadata is needed to ensure that LTO does not break down.
When combining modules targeting differing minimum version, the selection of the
highest version should prevail (since older versions should work on newer, but
not vice-versa).

REPOSITORY
  rL LLVM

http://reviews.llvm.org/D7642

Files:
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/CodeGenModule.cpp
  lib/Driver/Tools.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/libc-version.c

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1379,6 +1379,9 @@
   Flags<[HelpHidden]>;
 def mglibc : Flag<["-"], "mglibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
 def muclibc : Flag<["-"], "muclibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
+def mmin_libc_version_EQ : Joined<["-"], "mmin-libc-version=">,
+                           Group<m_libc_Group>,
+                           Flags<[ DriverOption, CC1Option ]>;
 def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>;
 def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
 def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>;
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -162,6 +162,9 @@
 /// The default TLS model to use.
 ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel)
 
+/// minimum libc version
+VALUE_CODEGENOPT(MinCLibVer, 32, 0)
+
 #undef CODEGENOPT
 #undef ENUM_CODEGENOPT
 #undef VALUE_CODEGENOPT
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -372,6 +372,10 @@
     getModule().addModuleFlag(llvm::Module::Warning, "Debug Info Version",
                               llvm::DEBUG_METADATA_VERSION);
 
+  if (CodeGenOpts.MinCLibVer)
+    getModule().addModuleFlag(llvm::Module::Warning, "minimum libc version",
+                              CodeGenOpts.MinCLibVer);
+
   // We need to record the widths of enums and wchar_t, so that we can generate
   // the correct build attributes in the ARM backend.
   llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -4121,6 +4121,12 @@
       CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver));
   }
 
+  // -mmin-libc-version
+  if (const Arg *A = Args.getLastArg(options::OPT_mmin_libc_version_EQ)) {
+    std::string Version = A->getValue();
+    CmdArgs.push_back(Args.MakeArgString("-mmin-libc-version=" + Version));
+  }
+
   // -fno-borland-extensions is default.
   if (Args.hasFlag(options::OPT_fborland_extensions,
                    options::OPT_fno_borland_extensions, false))
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -565,6 +565,27 @@
     }
   }
 
+  if (Arg *A = Args.getLastArg(OPT_mmin_libc_version_EQ)) {
+    StringRef Version = A->getValue();
+
+    unsigned VC[3] = {0};
+    SmallVector<StringRef, 3> Components;
+
+    Version.split(Components, ".", llvm::array_lengthof(VC));
+    for (unsigned CI = 0,
+                  CE = std::min(Components.size(), llvm::array_lengthof(VC));
+         CI < CE; ++CI) {
+      if (Components[CI].getAsInteger(10, VC[CI])) {
+        Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
+                                                  << Version;
+        memset(VC, 0, sizeof(VC));
+        break;
+      }
+    }
+
+    Opts.MinCLibVer = VC[0] * 10000 + VC[1] * 100 + VC[2];
+  }
+
   if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
     StringRef Val = A->getValue();
     if (Val == "fast")
Index: test/CodeGen/libc-version.c
===================================================================
--- /dev/null
+++ test/CodeGen/libc-version.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple thumbv7-windows-itanium -mmin-libc-version=12.0 -emit-llvm -o - %s \
+// RUN:    | FileCheck %s -check-prefix CHECK-WINDOWS
+// RUN: %clang_cc1 -triple thumbv7-windows-itanium -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+// RUN: %clang_cc1 -triple i686-linux-gnu -mmin-libc-version=2.21.0 -emit-llvm -o - %s \
+// RUN:    | FileCheck %s -check-prefix CHECK-LINUX
+// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+// CHECK-LINUX: !"minimum libc version", i32 22100}
+// CHECK-WINDOWS: !"minimum libc version", i32 120000}
+// CHECK-NOT: !"minimum libc version"
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to