]> granicus.if.org Git - clang/commitdiff
Driver: parse -mcmodel earlier
authorSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 8 May 2014 02:28:32 +0000 (02:28 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 8 May 2014 02:28:32 +0000 (02:28 +0000)
This addresses an existing FIXME item in the driver.  The code model flag was
parsed in the actual tool rather than in the driver.  This was problematic since
the value may be invalid.  In that case, we would silently treat it as a default
value in non-assert builds, and abort in assert builds.  Add a check in the
driver to validate that the value being passed is valid, and if not provide a
proper error message.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208275 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/BackendUtil.cpp
lib/Frontend/CompilerInvocation.cpp
test/Driver/code-model.c [new file with mode: 0644]

index 8d4f69afc3546e16d9ccfa68e508d305a39fe667..85d8b6457316323862f9dd9218de8bab3b0aeccf 100644 (file)
@@ -14,6 +14,7 @@
 #include "clang/Frontend/CodeGenOptions.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/Utils.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Bitcode/BitcodeWriterPass.h"
 #include "llvm/CodeGen/RegAllocRegistry.h"
 #include "llvm/CodeGen/SchedulerRegistry.h"
@@ -378,20 +379,16 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
   TargetMachine::setFunctionSections(CodeGenOpts.FunctionSections);
   TargetMachine::setDataSections    (CodeGenOpts.DataSections);
 
-  // FIXME: Parse this earlier.
-  llvm::CodeModel::Model CM;
-  if (CodeGenOpts.CodeModel == "small") {
-    CM = llvm::CodeModel::Small;
-  } else if (CodeGenOpts.CodeModel == "kernel") {
-    CM = llvm::CodeModel::Kernel;
-  } else if (CodeGenOpts.CodeModel == "medium") {
-    CM = llvm::CodeModel::Medium;
-  } else if (CodeGenOpts.CodeModel == "large") {
-    CM = llvm::CodeModel::Large;
-  } else {
-    assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!");
-    CM = llvm::CodeModel::Default;
-  }
+  unsigned CodeModel =
+    llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel)
+      .Case("small", llvm::CodeModel::Small)
+      .Case("kernel", llvm::CodeModel::Kernel)
+      .Case("medium", llvm::CodeModel::Medium)
+      .Case("large", llvm::CodeModel::Medium)
+      .Case("default", llvm::CodeModel::Default)
+      .Default(~0u);
+  assert(CodeModel != ~0u && "invalid code model!");
+  llvm::CodeModel::Model CM = static_cast<llvm::CodeModel::Model>(CodeModel);
 
   SmallVector<const char *, 16> BackendArgs;
   BackendArgs.push_back("clang"); // Fake program name.
index 0b6b765dba725a53e7b26359548e4c0d1408763a..a6b1b458e79546ce926807c562605c5b90c07bbf 100644 (file)
@@ -27,6 +27,7 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"
 #include "llvm/Option/Option.h"
+#include "llvm/Support/CodeGen.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
@@ -295,6 +296,17 @@ static void ParseCommentArgs(CommentOptions &Opts, ArgList &Args) {
   Opts.ParseAllComments = Args.hasArg(OPT_fparse_all_comments);
 }
 
+static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) {
+  if (Arg *A = Args.getLastArg(OPT_mcode_model)) {
+    StringRef Value = A->getValue();
+    if (Value == "small" || Value == "kernel" || Value == "medium" ||
+        Value == "large")
+      return Value;
+    Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value;
+  }
+  return "default";
+}
+
 static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
                              DiagnosticsEngine &Diags,
                              const TargetOptions &TargetOpts) {
@@ -376,7 +388,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
   Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);
   Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
   Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
-  Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model);
+  Opts.CodeModel = getCodeModel(Args, Diags);
   Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
   Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim);
   Opts.DisableFree = Args.hasArg(OPT_disable_free);
diff --git a/test/Driver/code-model.c b/test/Driver/code-model.c
new file mode 100644 (file)
index 0000000..001ca60
--- /dev/null
@@ -0,0 +1,13 @@
+// RUN: %clang -### -c -mcmodel=small %s 2>&1 | FileCheck -check-prefix CHECK-SMALL %s
+// RUN: %clang -### -S -mcmodel=kernel %s 2>&1 | FileCheck -check-prefix CHECK-KERNEL %s
+// RUN: %clang -### -c -mcmodel=medium %s 2>&1 | FileCheck -check-prefix CHECK-MEDIUM %s
+// RUN: %clang -### -S -mcmodel=large %s 2>&1 | FileCheck -check-prefix CHECK-LARGE %s
+// RUN: not %clang -c -mcmodel=lager %s 2>&1 | FileCheck -check-prefix CHECK-INVALID %s
+
+// CHECK-SMALL: "-mcode-model" "small"
+// CHECK-KERNEL: "-mcode-model" "kernel"
+// CHECK-MEDIUM: "-mcode-model" "medium"
+// CHECK-LARGE: "-mcode-model" "large"
+
+// CHECK-INVALID: error: invalid value 'lager' in '-mcode-model lager'
+