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