From e81307a78e7395d512cdea0a59ff7937ac8ebe63 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 8 May 2014 02:28:32 +0000 Subject: [PATCH] Driver: parse -mcmodel earlier 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 | 25 +++++++++++-------------- lib/Frontend/CompilerInvocation.cpp | 14 +++++++++++++- test/Driver/code-model.c | 13 +++++++++++++ 3 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 test/Driver/code-model.c diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 8d4f69afc3..85d8b64573 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -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(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(CodeModel); SmallVector BackendArgs; BackendArgs.push_back("clang"); // Fake program name. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 0b6b765dba..a6b1b458e7 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -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 index 0000000000..001ca606cd --- /dev/null +++ b/test/Driver/code-model.c @@ -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' + -- 2.40.0