1 /* 2 * Copyright 2014, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "clang/Basic/DiagnosticOptions.h" 18 #include "clang/Driver/DriverDiagnostic.h" 19 #include "clang/Driver/Options.h" 20 #include "clang/Frontend/Utils.h" 21 22 #include "llvm/Option/Arg.h" 23 #include "llvm/Option/ArgList.h" 24 #include "llvm/Option/Option.h" 25 #include "llvm/Option/OptTable.h" 26 27 #include "rs_cc_options.h" 28 #include "slang.h" 29 #include "slang_assert.h" 30 31 #include <cstdlib> 32 #include <string> 33 #include <utility> 34 #include <vector> 35 36 enum { 37 OPT_INVALID = 0, // This is not an option ID. 38 #define PREFIX(NAME, VALUE) 39 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 40 HELPTEXT, METAVAR) \ 41 OPT_##ID, 42 #include "RSCCOptions.inc" 43 LastOption 44 #undef OPTION 45 #undef PREFIX 46 }; 47 48 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 49 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 50 HELPTEXT, METAVAR) 51 #include "RSCCOptions.inc" 52 #undef OPTION 53 #undef PREFIX 54 55 static const llvm::opt::OptTable::Info RSCCInfoTable[] = { 56 #define PREFIX(NAME, VALUE) 57 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 58 HELPTEXT, METAVAR) \ 59 { \ 60 PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \ 61 PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS \ 62 } \ 63 , 64 #include "RSCCOptions.inc" 65 #undef OPTION 66 #undef PREFIX 67 }; 68 69 namespace { 70 71 class RSCCOptTable : public llvm::opt::OptTable { 72 public: 73 RSCCOptTable() 74 : OptTable(RSCCInfoTable, 75 sizeof(RSCCInfoTable) / sizeof(RSCCInfoTable[0])) {} 76 }; 77 } 78 79 llvm::opt::OptTable *slang::createRSCCOptTable() { return new RSCCOptTable(); } 80 81 void slang::ParseArguments(llvm::SmallVectorImpl<const char *> &ArgVector, 82 llvm::SmallVectorImpl<const char *> &Inputs, 83 slang::RSCCOptions &Opts, 84 clang::DiagnosticsEngine &DiagEngine) { 85 if (ArgVector.size() > 1) { 86 const char **ArgBegin = ArgVector.data() + 1; 87 const char **ArgEnd = ArgVector.data() + ArgVector.size(); 88 unsigned MissingArgIndex, MissingArgCount; 89 std::unique_ptr<llvm::opt::OptTable> OptParser(slang::createRSCCOptTable()); 90 std::unique_ptr<llvm::opt::InputArgList> Args(OptParser->ParseArgs( 91 ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount)); 92 93 // Check for missing argument error. 94 if (MissingArgCount) 95 DiagEngine.Report(clang::diag::err_drv_missing_argument) 96 << Args->getArgString(MissingArgIndex) << MissingArgCount; 97 98 clang::DiagnosticOptions DiagOpts; 99 DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w); 100 DiagOpts.Warnings = Args->getAllArgValues(OPT_W); 101 clang::ProcessWarningOptions(DiagEngine, DiagOpts); 102 103 // Issue errors on unknown arguments. 104 for (llvm::opt::arg_iterator it = Args->filtered_begin(OPT_UNKNOWN), 105 ie = Args->filtered_end(); 106 it != ie; ++it) 107 DiagEngine.Report(clang::diag::err_drv_unknown_argument) 108 << (*it)->getAsString(*Args); 109 110 for (llvm::opt::ArgList::const_iterator it = Args->begin(), 111 ie = Args->end(); 112 it != ie; ++it) { 113 const llvm::opt::Arg *A = *it; 114 if (A->getOption().getKind() == llvm::opt::Option::InputClass) 115 Inputs.push_back(A->getValue()); 116 } 117 118 Opts.mIncludePaths = Args->getAllArgValues(OPT_I); 119 120 Opts.mBitcodeOutputDir = Args->getLastArgValue(OPT_o); 121 122 if (const llvm::opt::Arg *A = Args->getLastArg(OPT_M_Group)) { 123 switch (A->getOption().getID()) { 124 case OPT_M: { 125 Opts.mEmitDependency = true; 126 Opts.mOutputType = slang::Slang::OT_Dependency; 127 break; 128 } 129 case OPT_MD: { 130 Opts.mEmitDependency = true; 131 Opts.mOutputType = slang::Slang::OT_Bitcode; 132 break; 133 } 134 default: { slangAssert(false && "Invalid option in M group!"); } 135 } 136 } 137 138 if (const llvm::opt::Arg *A = Args->getLastArg(OPT_Output_Type_Group)) { 139 switch (A->getOption().getID()) { 140 case OPT_emit_asm: { 141 Opts.mOutputType = slang::Slang::OT_Assembly; 142 break; 143 } 144 case OPT_emit_llvm: { 145 Opts.mOutputType = slang::Slang::OT_LLVMAssembly; 146 break; 147 } 148 case OPT_emit_bc: { 149 Opts.mOutputType = slang::Slang::OT_Bitcode; 150 break; 151 } 152 case OPT_emit_nothing: { 153 Opts.mOutputType = slang::Slang::OT_Nothing; 154 break; 155 } 156 default: { 157 slangAssert(false && "Invalid option in output type group!"); 158 } 159 } 160 } 161 162 if (Opts.mEmitDependency && 163 ((Opts.mOutputType != slang::Slang::OT_Bitcode) && 164 (Opts.mOutputType != slang::Slang::OT_Dependency))) 165 DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with) 166 << Args->getLastArg(OPT_M_Group)->getAsString(*Args) 167 << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args); 168 169 Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix); 170 171 Opts.mJavaReflectionPathBase = 172 Args->getLastArgValue(OPT_java_reflection_path_base); 173 Opts.mJavaReflectionPackageName = 174 Args->getLastArgValue(OPT_java_reflection_package_name); 175 176 Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name); 177 178 llvm::StringRef BitcodeStorageValue = 179 Args->getLastArgValue(OPT_bitcode_storage); 180 if (BitcodeStorageValue == "ar") 181 Opts.mBitcodeStorage = slang::BCST_APK_RESOURCE; 182 else if (BitcodeStorageValue == "jc") 183 Opts.mBitcodeStorage = slang::BCST_JAVA_CODE; 184 else if (!BitcodeStorageValue.empty()) 185 DiagEngine.Report(clang::diag::err_drv_invalid_value) 186 << OptParser->getOptionName(OPT_bitcode_storage) 187 << BitcodeStorageValue; 188 189 llvm::opt::Arg *lastBitwidthArg = Args->getLastArg(OPT_m32, OPT_m64); 190 if (Args->hasArg(OPT_reflect_cpp)) { 191 Opts.mBitcodeStorage = slang::BCST_CPP_CODE; 192 // mJavaReflectionPathBase can be set for C++ reflected builds. 193 // Set it to the standard mBitcodeOutputDir (via -o) by default. 194 if (Opts.mJavaReflectionPathBase.empty()) { 195 Opts.mJavaReflectionPathBase = Opts.mBitcodeOutputDir; 196 } 197 198 // Check for bitwidth arguments. 199 if (lastBitwidthArg) { 200 if (lastBitwidthArg->getOption().matches(OPT_m32)) { 201 Opts.mBitWidth = 32; 202 } else { 203 Opts.mBitWidth = 64; 204 } 205 } 206 } else if (lastBitwidthArg) { 207 // -m32/-m64 are forbidden for non-C++ reflection paths. 208 DiagEngine.Report(DiagEngine.getCustomDiagID( 209 clang::DiagnosticsEngine::Error, 210 "cannot use -m32/-m64 without specifying C++ reflection (-reflect-c++)")); 211 } 212 213 Opts.mDependencyOutputDir = 214 Args->getLastArgValue(OPT_output_dep_dir, Opts.mBitcodeOutputDir); 215 Opts.mAdditionalDepTargets = 216 Args->getAllArgValues(OPT_additional_dep_target); 217 218 Opts.mShowHelp = Args->hasArg(OPT_help); 219 Opts.mShowVersion = Args->hasArg(OPT_version); 220 Opts.mDebugEmission = Args->hasArg(OPT_emit_g); 221 Opts.mVerbose = Args->hasArg(OPT_verbose); 222 223 // If we are emitting both 32-bit and 64-bit bitcode, we must embed it. 224 225 size_t OptLevel = 226 clang::getLastArgIntValue(*Args, OPT_optimization_level, 3, DiagEngine); 227 228 Opts.mOptimizationLevel = 229 OptLevel == 0 ? llvm::CodeGenOpt::None : llvm::CodeGenOpt::Aggressive; 230 231 Opts.mTargetAPI = clang::getLastArgIntValue(*Args, OPT_target_api, 232 RS_VERSION, DiagEngine); 233 234 if (Opts.mTargetAPI == 0) { 235 Opts.mTargetAPI = UINT_MAX; 236 } 237 238 Opts.mEmit3264 = (Opts.mTargetAPI >= 21) && (Opts.mBitcodeStorage != slang::BCST_CPP_CODE); 239 if (Opts.mEmit3264) { 240 Opts.mBitcodeStorage = slang::BCST_JAVA_CODE; 241 } 242 } 243 } 244