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
26namespace panda::compiler {
27
28#include "cpu_features.inc"
29
30enum 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
38class CompilerOptions;
39extern 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 */
45class CompilerOptions : public Options {
46public:
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     */
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>
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
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
104    bool IsCpuFeatureEnabled(CpuFeature feature) const
105    {
106        return features_.test(feature);
107    }
108
109private:
110    void EnableCpuFeature(CpuFeature feature)
111    {
112        features_.set(feature);
113    }
114
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