1 /** 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef COMPILER_COMPILER_OPTIONS_H 17 #define COMPILER_COMPILER_OPTIONS_H 18 19 #include "utils/pandargs.h" 20 #include "libpandabase/utils/arch.h" 21 #include "cpu_features.h" 22 #include "compiler_options_gen.h" 23 24 #include <regex> 25 26 namespace panda::compiler { 27 28 #include "cpu_features.inc" 29 30 enum CpuFeature : uint8_t { 31 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 32 #define DEF(COMPONENT, ...) COMPONENT, 33 CPU_FEATURE(DEF) 34 #undef DEF 35 CPU_FEATURES_NUM 36 }; 37 38 class CompilerOptions; 39 extern CompilerOptions options; 40 41 /** 42 * Extends `compiler::Options`, which may be not sufficient to provide the desired functionality 43 * (e.g. store an option-related variable) 44 */ 45 class CompilerOptions : public Options { 46 public: CompilerOptions(const std::string & exe_path)47 explicit CompilerOptions(const std::string &exe_path) : Options(exe_path) {} 48 NO_MOVE_SEMANTIC(CompilerOptions); 49 NO_COPY_SEMANTIC(CompilerOptions); 50 ~CompilerOptions() = default; 51 52 /** 53 * `--compiler-regex` extension. 54 * The purpose of this extension is to avoid unnecessary construction of std::regex from 55 * `Options::GetCompilerRegex()` on every call to `MatchesRegex()`. 56 * 57 * Static local variable doesn't suit as soon as `Options::SetCompilerRegex()` is used (e.g. in 58 * tests). 59 */ SetCompilerRegex(const std::string & new_regex_pattern)60 void SetCompilerRegex(const std::string &new_regex_pattern) 61 { 62 Options::SetCompilerRegex(new_regex_pattern); 63 regex_ = new_regex_pattern; 64 } 65 template <typename T> MatchesRegex(const T & method_name)66 bool MatchesRegex(const T &method_name) 67 { 68 if (!WasSetCompilerRegex()) { 69 return true; 70 } 71 if (!regex_initialized_) { 72 regex_ = GetCompilerRegex(); 73 regex_initialized_ = true; 74 } 75 return std::regex_match(method_name, regex_); 76 } 77 AdjustCpuFeatures(bool cross_compilation)78 void AdjustCpuFeatures(bool cross_compilation) 79 { 80 ParseEnabledCpuFeatures(); 81 if (cross_compilation || WasSetCompilerCpuFeatures()) { 82 return; 83 } 84 switch (RUNTIME_ARCH) { 85 case Arch::AARCH64: { 86 if (CpuFeaturesHasCrc32()) { 87 EnableCpuFeature(CRC32); 88 } 89 break; 90 } 91 case Arch::AARCH32: 92 break; 93 case Arch::X86: 94 break; 95 case Arch::X86_64: 96 break; 97 case Arch::NONE: 98 break; 99 default: 100 break; 101 } 102 } 103 IsCpuFeatureEnabled(CpuFeature feature)104 bool IsCpuFeatureEnabled(CpuFeature feature) const 105 { 106 return features_.test(feature); 107 } 108 109 private: EnableCpuFeature(CpuFeature feature)110 void EnableCpuFeature(CpuFeature feature) 111 { 112 features_.set(feature); 113 } 114 ParseEnabledCpuFeatures()115 void ParseEnabledCpuFeatures() 116 { 117 for (const auto &arg : GetCompilerCpuFeatures()) { 118 if (arg == "none") { 119 features_.reset(); 120 break; 121 } 122 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 123 #define DEF(FEATURE, NAME) \ 124 if (NAME == arg) { \ 125 EnableCpuFeature(FEATURE); \ 126 continue; \ 127 } 128 CPU_FEATURE(DEF) 129 #undef DEF 130 131 UNREACHABLE(); 132 } 133 } 134 135 // `--compiler-regex`: 136 std::regex regex_; 137 bool regex_initialized_ {false}; 138 std::bitset<CPU_FEATURES_NUM> features_; 139 }; 140 141 } // namespace panda::compiler 142 143 #endif // COMPILER_COMPILER_OPTIONS_H 144