xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/BuiltinTargetFeatures.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric //===-- CodeGenFunction.h - Target features for builtin ---------*- C++ -*-===//
2*81ad6265SDimitry Andric //
3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*81ad6265SDimitry Andric //
7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
8*81ad6265SDimitry Andric //
9*81ad6265SDimitry Andric // This is the internal required target features for builtin.
10*81ad6265SDimitry Andric //
11*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
12*81ad6265SDimitry Andric 
13*81ad6265SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_BUILTINTARGETFEATURES_H
14*81ad6265SDimitry Andric #define LLVM_CLANG_LIB_BASIC_BUILTINTARGETFEATURES_H
15*81ad6265SDimitry Andric #include "llvm/ADT/StringMap.h"
16*81ad6265SDimitry Andric #include "llvm/ADT/StringRef.h"
17*81ad6265SDimitry Andric 
18*81ad6265SDimitry Andric using llvm::StringRef;
19*81ad6265SDimitry Andric 
20*81ad6265SDimitry Andric namespace clang {
21*81ad6265SDimitry Andric namespace Builtin {
22*81ad6265SDimitry Andric /// TargetFeatures - This class is used to check whether the builtin function
23*81ad6265SDimitry Andric /// has the required tagert specific features. It is able to support the
24*81ad6265SDimitry Andric /// combination of ','(and), '|'(or), and '()'. By default, the priority of
25*81ad6265SDimitry Andric /// ',' is higher than that of '|' .
26*81ad6265SDimitry Andric /// E.g:
27*81ad6265SDimitry Andric /// A,B|C means the builtin function requires both A and B, or C.
28*81ad6265SDimitry Andric /// If we want the builtin function requires both A and B, or both A and C,
29*81ad6265SDimitry Andric /// there are two ways: A,B|A,C or A,(B|C).
30*81ad6265SDimitry Andric /// The FeaturesList should not contain spaces, and brackets must appear in
31*81ad6265SDimitry Andric /// pairs.
32*81ad6265SDimitry Andric class TargetFeatures {
33*81ad6265SDimitry Andric   struct FeatureListStatus {
34*81ad6265SDimitry Andric     bool HasFeatures;
35*81ad6265SDimitry Andric     StringRef CurFeaturesList;
36*81ad6265SDimitry Andric   };
37*81ad6265SDimitry Andric 
38*81ad6265SDimitry Andric   const llvm::StringMap<bool> &CallerFeatureMap;
39*81ad6265SDimitry Andric 
40*81ad6265SDimitry Andric   FeatureListStatus getAndFeatures(StringRef FeatureList) {
41*81ad6265SDimitry Andric     int InParentheses = 0;
42*81ad6265SDimitry Andric     bool HasFeatures = true;
43*81ad6265SDimitry Andric     size_t SubexpressionStart = 0;
44*81ad6265SDimitry Andric     for (size_t i = 0, e = FeatureList.size(); i < e; ++i) {
45*81ad6265SDimitry Andric       char CurrentToken = FeatureList[i];
46*81ad6265SDimitry Andric       switch (CurrentToken) {
47*81ad6265SDimitry Andric       default:
48*81ad6265SDimitry Andric         break;
49*81ad6265SDimitry Andric       case '(':
50*81ad6265SDimitry Andric         if (InParentheses == 0)
51*81ad6265SDimitry Andric           SubexpressionStart = i + 1;
52*81ad6265SDimitry Andric         ++InParentheses;
53*81ad6265SDimitry Andric         break;
54*81ad6265SDimitry Andric       case ')':
55*81ad6265SDimitry Andric         --InParentheses;
56*81ad6265SDimitry Andric         assert(InParentheses >= 0 && "Parentheses are not in pair");
57*81ad6265SDimitry Andric         LLVM_FALLTHROUGH;
58*81ad6265SDimitry Andric       case '|':
59*81ad6265SDimitry Andric       case ',':
60*81ad6265SDimitry Andric         if (InParentheses == 0) {
61*81ad6265SDimitry Andric           if (HasFeatures && i != SubexpressionStart) {
62*81ad6265SDimitry Andric             StringRef F = FeatureList.slice(SubexpressionStart, i);
63*81ad6265SDimitry Andric             HasFeatures = CurrentToken == ')' ? hasRequiredFeatures(F)
64*81ad6265SDimitry Andric                                               : CallerFeatureMap.lookup(F);
65*81ad6265SDimitry Andric           }
66*81ad6265SDimitry Andric           SubexpressionStart = i + 1;
67*81ad6265SDimitry Andric           if (CurrentToken == '|') {
68*81ad6265SDimitry Andric             return {HasFeatures, FeatureList.substr(SubexpressionStart)};
69*81ad6265SDimitry Andric           }
70*81ad6265SDimitry Andric         }
71*81ad6265SDimitry Andric         break;
72*81ad6265SDimitry Andric       }
73*81ad6265SDimitry Andric     }
74*81ad6265SDimitry Andric     assert(InParentheses == 0 && "Parentheses are not in pair");
75*81ad6265SDimitry Andric     if (HasFeatures && SubexpressionStart != FeatureList.size())
76*81ad6265SDimitry Andric       HasFeatures =
77*81ad6265SDimitry Andric           CallerFeatureMap.lookup(FeatureList.substr(SubexpressionStart));
78*81ad6265SDimitry Andric     return {HasFeatures, StringRef()};
79*81ad6265SDimitry Andric   }
80*81ad6265SDimitry Andric 
81*81ad6265SDimitry Andric public:
82*81ad6265SDimitry Andric   bool hasRequiredFeatures(StringRef FeatureList) {
83*81ad6265SDimitry Andric     FeatureListStatus FS = {false, FeatureList};
84*81ad6265SDimitry Andric     while (!FS.HasFeatures && !FS.CurFeaturesList.empty())
85*81ad6265SDimitry Andric       FS = getAndFeatures(FS.CurFeaturesList);
86*81ad6265SDimitry Andric     return FS.HasFeatures;
87*81ad6265SDimitry Andric   }
88*81ad6265SDimitry Andric 
89*81ad6265SDimitry Andric   TargetFeatures(const llvm::StringMap<bool> &CallerFeatureMap)
90*81ad6265SDimitry Andric       : CallerFeatureMap(CallerFeatureMap) {}
91*81ad6265SDimitry Andric };
92*81ad6265SDimitry Andric 
93*81ad6265SDimitry Andric } // namespace Builtin
94*81ad6265SDimitry Andric } // namespace clang
95*81ad6265SDimitry Andric #endif /* CLANG_LIB_BASIC_BUILTINTARGETFEATURES_H */
96