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 18 using llvm::StringRef; 19 20 namespace clang { 21 namespace 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. 32 class TargetFeatures { 33 struct FeatureListStatus { 34 bool HasFeatures; 35 StringRef CurFeaturesList; 36 }; 37 38 const llvm::StringMap<bool> &CallerFeatureMap; 39 getAndFeatures(StringRef FeatureList)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(SubexpressionStart, i); 63 HasFeatures = CurrentToken == ')' ? hasRequiredFeatures(F) 64 : CallerFeatureMap.lookup(F); 65 } 66 SubexpressionStart = i + 1; 67 if (CurrentToken == '|') { 68 return {HasFeatures, FeatureList.substr(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(FeatureList.substr(SubexpressionStart)); 78 return {HasFeatures, StringRef()}; 79 } 80 81 public: hasRequiredFeatures(StringRef FeatureList)82 bool hasRequiredFeatures(StringRef FeatureList) { 83 FeatureListStatus FS = {false, FeatureList}; 84 while (!FS.HasFeatures && !FS.CurFeaturesList.empty()) 85 FS = getAndFeatures(FS.CurFeaturesList); 86 return FS.HasFeatures; 87 } 88 TargetFeatures(const llvm::StringMap<bool> & CallerFeatureMap)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