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