diff options
Diffstat (limited to 'rs_cc_options.cpp')
-rw-r--r-- | rs_cc_options.cpp | 320 |
1 files changed, 173 insertions, 147 deletions
diff --git a/rs_cc_options.cpp b/rs_cc_options.cpp index ff37dd0..94d1453 100644 --- a/rs_cc_options.cpp +++ b/rs_cc_options.cpp @@ -23,6 +23,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Option/OptTable.h" +#include "llvm/Support/CommandLine.h" #include "rs_cc_options.h" #include "slang.h" @@ -76,168 +77,193 @@ class RSCCOptTable : public llvm::opt::OptTable { }; } -llvm::opt::OptTable *slang::createRSCCOptTable() { return new RSCCOptTable(); } - -void slang::ParseArguments(llvm::SmallVectorImpl<const char *> &ArgVector, - llvm::SmallVectorImpl<const char *> &Inputs, - slang::RSCCOptions &Opts, - clang::DiagnosticsEngine &DiagEngine) { - if (ArgVector.size() > 1) { - const char **ArgBegin = ArgVector.data() + 1; - const char **ArgEnd = ArgVector.data() + ArgVector.size(); - unsigned MissingArgIndex, MissingArgCount; - std::unique_ptr<llvm::opt::OptTable> OptParser(slang::createRSCCOptTable()); - std::unique_ptr<llvm::opt::InputArgList> Args(OptParser->ParseArgs( - ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount)); - - // Check for missing argument error. - if (MissingArgCount) - DiagEngine.Report(clang::diag::err_drv_missing_argument) - << Args->getArgString(MissingArgIndex) << MissingArgCount; - - clang::DiagnosticOptions DiagOpts; - DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w); - DiagOpts.Warnings = Args->getAllArgValues(OPT_W); - clang::ProcessWarningOptions(DiagEngine, DiagOpts); - - // Issue errors on unknown arguments. - for (llvm::opt::arg_iterator it = Args->filtered_begin(OPT_UNKNOWN), - ie = Args->filtered_end(); - it != ie; ++it) - DiagEngine.Report(clang::diag::err_drv_unknown_argument) - << (*it)->getAsString(*Args); - - for (llvm::opt::ArgList::const_iterator it = Args->begin(), - ie = Args->end(); - it != ie; ++it) { - const llvm::opt::Arg *A = *it; - if (A->getOption().getKind() == llvm::opt::Option::InputClass) - Inputs.push_back(A->getValue()); - } +namespace slang { + +llvm::opt::OptTable *createRSCCOptTable() { return new RSCCOptTable(); } + +// This function is similar to +// clang/lib/Frontend/CompilerInvocation::CreateFromArgs. +bool ParseArguments(const llvm::ArrayRef<const char *> &ArgsIn, + llvm::SmallVectorImpl<const char *> &Inputs, + RSCCOptions &Opts, clang::DiagnosticOptions &DiagOpts, + llvm::cl::StringSaver &StringSaver) { + // We use a different diagnostic engine for argument parsing from the rest of + // the work. This mimics what's done in clang. I believe it is so the + // argument parsing errors are well formatted while the full errors can be + // influenced by command line arguments. + llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> ArgumentParseDiagOpts( + new clang::DiagnosticOptions()); + llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs( + new clang::DiagnosticIDs()); + DiagnosticBuffer DiagsBuffer; + clang::DiagnosticsEngine DiagEngine(DiagIDs, &*ArgumentParseDiagOpts, + &DiagsBuffer, false); + + // Populate a vector with the command line arguments, expanding command files + // that have been included via the '@' argument. + llvm::SmallVector<const char *, 256> ArgVector; + ArgVector.append(ArgsIn.begin(), ArgsIn.end()); + llvm::cl::ExpandResponseFiles(StringSaver, llvm::cl::TokenizeGNUCommandLine, + ArgVector, false); + + std::unique_ptr<llvm::opt::OptTable> OptParser(createRSCCOptTable()); + unsigned MissingArgIndex = 0; + unsigned MissingArgCount = 0; + std::unique_ptr<llvm::opt::InputArgList> Args( + OptParser->ParseArgs(ArgVector.begin() + 1, ArgVector.end(), + MissingArgIndex, MissingArgCount)); + + // Check for missing argument error. + if (MissingArgCount) { + DiagEngine.Report(clang::diag::err_drv_missing_argument) + << Args->getArgString(MissingArgIndex) << MissingArgCount; + } - Opts.mIncludePaths = Args->getAllArgValues(OPT_I); - - Opts.mBitcodeOutputDir = Args->getLastArgValue(OPT_o); - - if (const llvm::opt::Arg *A = Args->getLastArg(OPT_M_Group)) { - switch (A->getOption().getID()) { - case OPT_M: { - Opts.mEmitDependency = true; - Opts.mOutputType = slang::Slang::OT_Dependency; - break; - } - case OPT_MD: { - Opts.mEmitDependency = true; - Opts.mOutputType = slang::Slang::OT_Bitcode; - break; - } - default: { slangAssert(false && "Invalid option in M group!"); } - } + // Issue errors on unknown arguments. + for (llvm::opt::arg_iterator it = Args->filtered_begin(OPT_UNKNOWN), + ie = Args->filtered_end(); + it != ie; ++it) { + DiagEngine.Report(clang::diag::err_drv_unknown_argument) + << (*it)->getAsString(*Args); + } + + DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w); + DiagOpts.Warnings = Args->getAllArgValues(OPT_W); + + for (llvm::opt::ArgList::const_iterator it = Args->begin(), ie = Args->end(); + it != ie; ++it) { + const llvm::opt::Arg *A = *it; + if (A->getOption().getKind() == llvm::opt::Option::InputClass) + Inputs.push_back(A->getValue()); + } + + Opts.mIncludePaths = Args->getAllArgValues(OPT_I); + + Opts.mBitcodeOutputDir = Args->getLastArgValue(OPT_o); + + if (const llvm::opt::Arg *A = Args->getLastArg(OPT_M_Group)) { + switch (A->getOption().getID()) { + case OPT_M: { + Opts.mEmitDependency = true; + Opts.mOutputType = Slang::OT_Dependency; + break; + } + case OPT_MD: { + Opts.mEmitDependency = true; + Opts.mOutputType = Slang::OT_Bitcode; + break; + } + default: { slangAssert(false && "Invalid option in M group!"); } } + } - if (const llvm::opt::Arg *A = Args->getLastArg(OPT_Output_Type_Group)) { - switch (A->getOption().getID()) { - case OPT_emit_asm: { - Opts.mOutputType = slang::Slang::OT_Assembly; - break; - } - case OPT_emit_llvm: { - Opts.mOutputType = slang::Slang::OT_LLVMAssembly; - break; - } - case OPT_emit_bc: { - Opts.mOutputType = slang::Slang::OT_Bitcode; - break; - } - case OPT_emit_nothing: { - Opts.mOutputType = slang::Slang::OT_Nothing; - break; - } - default: { - slangAssert(false && "Invalid option in output type group!"); - } - } + if (const llvm::opt::Arg *A = Args->getLastArg(OPT_Output_Type_Group)) { + switch (A->getOption().getID()) { + case OPT_emit_asm: { + Opts.mOutputType = Slang::OT_Assembly; + break; + } + case OPT_emit_llvm: { + Opts.mOutputType = Slang::OT_LLVMAssembly; + break; } + case OPT_emit_bc: { + Opts.mOutputType = Slang::OT_Bitcode; + break; + } + case OPT_emit_nothing: { + Opts.mOutputType = Slang::OT_Nothing; + break; + } + default: { slangAssert(false && "Invalid option in output type group!"); } + } + } - if (Opts.mEmitDependency && - ((Opts.mOutputType != slang::Slang::OT_Bitcode) && - (Opts.mOutputType != slang::Slang::OT_Dependency))) - DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with) - << Args->getLastArg(OPT_M_Group)->getAsString(*Args) - << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args); - - Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix); - - Opts.mJavaReflectionPathBase = - Args->getLastArgValue(OPT_java_reflection_path_base); - Opts.mJavaReflectionPackageName = - Args->getLastArgValue(OPT_java_reflection_package_name); - - Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name); - - llvm::StringRef BitcodeStorageValue = - Args->getLastArgValue(OPT_bitcode_storage); - if (BitcodeStorageValue == "ar") - Opts.mBitcodeStorage = slang::BCST_APK_RESOURCE; - else if (BitcodeStorageValue == "jc") - Opts.mBitcodeStorage = slang::BCST_JAVA_CODE; - else if (!BitcodeStorageValue.empty()) - DiagEngine.Report(clang::diag::err_drv_invalid_value) - << OptParser->getOptionName(OPT_bitcode_storage) - << BitcodeStorageValue; - - llvm::opt::Arg *lastBitwidthArg = Args->getLastArg(OPT_m32, OPT_m64); - if (Args->hasArg(OPT_reflect_cpp)) { - Opts.mBitcodeStorage = slang::BCST_CPP_CODE; - // mJavaReflectionPathBase can be set for C++ reflected builds. - // Set it to the standard mBitcodeOutputDir (via -o) by default. - if (Opts.mJavaReflectionPathBase.empty()) { - Opts.mJavaReflectionPathBase = Opts.mBitcodeOutputDir; - } + if (Opts.mEmitDependency && ((Opts.mOutputType != Slang::OT_Bitcode) && + (Opts.mOutputType != Slang::OT_Dependency))) + DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with) + << Args->getLastArg(OPT_M_Group)->getAsString(*Args) + << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args); + + Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix); + + Opts.mJavaReflectionPathBase = + Args->getLastArgValue(OPT_java_reflection_path_base); + Opts.mJavaReflectionPackageName = + Args->getLastArgValue(OPT_java_reflection_package_name); + + Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name); + + llvm::StringRef BitcodeStorageValue = + Args->getLastArgValue(OPT_bitcode_storage); + if (BitcodeStorageValue == "ar") + Opts.mBitcodeStorage = BCST_APK_RESOURCE; + else if (BitcodeStorageValue == "jc") + Opts.mBitcodeStorage = BCST_JAVA_CODE; + else if (!BitcodeStorageValue.empty()) + DiagEngine.Report(clang::diag::err_drv_invalid_value) + << OptParser->getOptionName(OPT_bitcode_storage) << BitcodeStorageValue; + + llvm::opt::Arg *lastBitwidthArg = Args->getLastArg(OPT_m32, OPT_m64); + if (Args->hasArg(OPT_reflect_cpp)) { + Opts.mBitcodeStorage = BCST_CPP_CODE; + // mJavaReflectionPathBase can be set for C++ reflected builds. + // Set it to the standard mBitcodeOutputDir (via -o) by default. + if (Opts.mJavaReflectionPathBase.empty()) { + Opts.mJavaReflectionPathBase = Opts.mBitcodeOutputDir; + } - // Check for bitwidth arguments. - if (lastBitwidthArg) { - if (lastBitwidthArg->getOption().matches(OPT_m32)) { - Opts.mBitWidth = 32; - } else { - Opts.mBitWidth = 64; - } + // Check for bitwidth arguments. + if (lastBitwidthArg) { + if (lastBitwidthArg->getOption().matches(OPT_m32)) { + Opts.mBitWidth = 32; + } else { + Opts.mBitWidth = 64; } - } else if (lastBitwidthArg) { - // -m32/-m64 are forbidden for non-C++ reflection paths. - DiagEngine.Report(DiagEngine.getCustomDiagID( - clang::DiagnosticsEngine::Error, - "cannot use -m32/-m64 without specifying C++ reflection (-reflect-c++)")); } + } else if (lastBitwidthArg) { + // -m32/-m64 are forbidden for non-C++ reflection paths. + DiagEngine.Report( + DiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error, + "cannot use -m32/-m64 without specifying " + "C++ reflection (-reflect-c++)")); + } - Opts.mDependencyOutputDir = - Args->getLastArgValue(OPT_output_dep_dir, Opts.mBitcodeOutputDir); - Opts.mAdditionalDepTargets = - Args->getAllArgValues(OPT_additional_dep_target); + Opts.mDependencyOutputDir = + Args->getLastArgValue(OPT_output_dep_dir, Opts.mBitcodeOutputDir); + Opts.mAdditionalDepTargets = Args->getAllArgValues(OPT_additional_dep_target); - Opts.mShowHelp = Args->hasArg(OPT_help); - Opts.mShowVersion = Args->hasArg(OPT_version); - Opts.mDebugEmission = Args->hasArg(OPT_emit_g); - Opts.mVerbose = Args->hasArg(OPT_verbose); + Opts.mShowHelp = Args->hasArg(OPT_help); + Opts.mShowVersion = Args->hasArg(OPT_version); + Opts.mDebugEmission = Args->hasArg(OPT_emit_g); + Opts.mVerbose = Args->hasArg(OPT_verbose); - // If we are emitting both 32-bit and 64-bit bitcode, we must embed it. + // If we are emitting both 32-bit and 64-bit bitcode, we must embed it. - size_t OptLevel = - clang::getLastArgIntValue(*Args, OPT_optimization_level, 3, DiagEngine); + size_t OptLevel = + clang::getLastArgIntValue(*Args, OPT_optimization_level, 3, DiagEngine); - Opts.mOptimizationLevel = - OptLevel == 0 ? llvm::CodeGenOpt::None : llvm::CodeGenOpt::Aggressive; + Opts.mOptimizationLevel = + OptLevel == 0 ? llvm::CodeGenOpt::None : llvm::CodeGenOpt::Aggressive; - Opts.mTargetAPI = clang::getLastArgIntValue(*Args, OPT_target_api, - RS_VERSION, DiagEngine); + Opts.mTargetAPI = + clang::getLastArgIntValue(*Args, OPT_target_api, RS_VERSION, DiagEngine); - if (Opts.mTargetAPI == 0) { - Opts.mTargetAPI = UINT_MAX; - } + if (Opts.mTargetAPI == 0) { + Opts.mTargetAPI = UINT_MAX; + } - Opts.mEmit3264 = (Opts.mTargetAPI >= 21) && (Opts.mBitcodeStorage != slang::BCST_CPP_CODE); - if (Opts.mEmit3264) { - Opts.mBitcodeStorage = slang::BCST_JAVA_CODE; - } + Opts.mEmit3264 = + (Opts.mTargetAPI >= 21) && (Opts.mBitcodeStorage != BCST_CPP_CODE); + if (Opts.mEmit3264) { + Opts.mBitcodeStorage = BCST_JAVA_CODE; } + + if (DiagEngine.hasErrorOccurred()) { + llvm::errs() << DiagsBuffer.str(); + return false; + } + + return true; +} } |