181ad6265SDimitry Andric //===-- CodeGenFunction.h - Target features for builtin ---------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This is the internal required target features for builtin. 1081ad6265SDimitry Andric // 1181ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1281ad6265SDimitry Andric 1381ad6265SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_BUILTINTARGETFEATURES_H 1481ad6265SDimitry Andric #define LLVM_CLANG_LIB_BASIC_BUILTINTARGETFEATURES_H 1581ad6265SDimitry Andric #include "llvm/ADT/StringMap.h" 1681ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 1781ad6265SDimitry Andric 1881ad6265SDimitry Andric using llvm::StringRef; 1981ad6265SDimitry Andric 2081ad6265SDimitry Andric namespace clang { 2181ad6265SDimitry Andric namespace Builtin { 2281ad6265SDimitry Andric /// TargetFeatures - This class is used to check whether the builtin function 2381ad6265SDimitry Andric /// has the required tagert specific features. It is able to support the 2481ad6265SDimitry Andric /// combination of ','(and), '|'(or), and '()'. By default, the priority of 2581ad6265SDimitry Andric /// ',' is higher than that of '|' . 2681ad6265SDimitry Andric /// E.g: 2781ad6265SDimitry Andric /// A,B|C means the builtin function requires both A and B, or C. 2881ad6265SDimitry Andric /// If we want the builtin function requires both A and B, or both A and C, 2981ad6265SDimitry Andric /// there are two ways: A,B|A,C or A,(B|C). 3081ad6265SDimitry Andric /// The FeaturesList should not contain spaces, and brackets must appear in 3181ad6265SDimitry Andric /// pairs. 3281ad6265SDimitry Andric class TargetFeatures { 3381ad6265SDimitry Andric struct FeatureListStatus { 3481ad6265SDimitry Andric bool HasFeatures; 3581ad6265SDimitry Andric StringRef CurFeaturesList; 3681ad6265SDimitry Andric }; 3781ad6265SDimitry Andric 3881ad6265SDimitry Andric const llvm::StringMap<bool> &CallerFeatureMap; 3981ad6265SDimitry Andric getAndFeatures(StringRef FeatureList)4081ad6265SDimitry Andric FeatureListStatus getAndFeatures(StringRef FeatureList) { 4181ad6265SDimitry Andric int InParentheses = 0; 4281ad6265SDimitry Andric bool HasFeatures = true; 4381ad6265SDimitry Andric size_t SubexpressionStart = 0; 4481ad6265SDimitry Andric for (size_t i = 0, e = FeatureList.size(); i < e; ++i) { 4581ad6265SDimitry Andric char CurrentToken = FeatureList[i]; 4681ad6265SDimitry Andric switch (CurrentToken) { 4781ad6265SDimitry Andric default: 4881ad6265SDimitry Andric break; 4981ad6265SDimitry Andric case '(': 5081ad6265SDimitry Andric if (InParentheses == 0) 5181ad6265SDimitry Andric SubexpressionStart = i + 1; 5281ad6265SDimitry Andric ++InParentheses; 5381ad6265SDimitry Andric break; 5481ad6265SDimitry Andric case ')': 5581ad6265SDimitry Andric --InParentheses; 5681ad6265SDimitry Andric assert(InParentheses >= 0 && "Parentheses are not in pair"); 57*bdd1243dSDimitry Andric [[fallthrough]]; 5881ad6265SDimitry Andric case '|': 5981ad6265SDimitry Andric case ',': 6081ad6265SDimitry Andric if (InParentheses == 0) { 6181ad6265SDimitry Andric if (HasFeatures && i != SubexpressionStart) { 6281ad6265SDimitry Andric StringRef F = FeatureList.slice(SubexpressionStart, i); 6381ad6265SDimitry Andric HasFeatures = CurrentToken == ')' ? hasRequiredFeatures(F) 6481ad6265SDimitry Andric : CallerFeatureMap.lookup(F); 6581ad6265SDimitry Andric } 6681ad6265SDimitry Andric SubexpressionStart = i + 1; 6781ad6265SDimitry Andric if (CurrentToken == '|') { 6881ad6265SDimitry Andric return {HasFeatures, FeatureList.substr(SubexpressionStart)}; 6981ad6265SDimitry Andric } 7081ad6265SDimitry Andric } 7181ad6265SDimitry Andric break; 7281ad6265SDimitry Andric } 7381ad6265SDimitry Andric } 7481ad6265SDimitry Andric assert(InParentheses == 0 && "Parentheses are not in pair"); 7581ad6265SDimitry Andric if (HasFeatures && SubexpressionStart != FeatureList.size()) 7681ad6265SDimitry Andric HasFeatures = 7781ad6265SDimitry Andric CallerFeatureMap.lookup(FeatureList.substr(SubexpressionStart)); 7881ad6265SDimitry Andric return {HasFeatures, StringRef()}; 7981ad6265SDimitry Andric } 8081ad6265SDimitry Andric 8181ad6265SDimitry Andric public: hasRequiredFeatures(StringRef FeatureList)8281ad6265SDimitry Andric bool hasRequiredFeatures(StringRef FeatureList) { 8381ad6265SDimitry Andric FeatureListStatus FS = {false, FeatureList}; 8481ad6265SDimitry Andric while (!FS.HasFeatures && !FS.CurFeaturesList.empty()) 8581ad6265SDimitry Andric FS = getAndFeatures(FS.CurFeaturesList); 8681ad6265SDimitry Andric return FS.HasFeatures; 8781ad6265SDimitry Andric } 8881ad6265SDimitry Andric TargetFeatures(const llvm::StringMap<bool> & CallerFeatureMap)8981ad6265SDimitry Andric TargetFeatures(const llvm::StringMap<bool> &CallerFeatureMap) 9081ad6265SDimitry Andric : CallerFeatureMap(CallerFeatureMap) {} 9181ad6265SDimitry Andric }; 9281ad6265SDimitry Andric 9381ad6265SDimitry Andric } // namespace Builtin 9481ad6265SDimitry Andric } // namespace clang 9581ad6265SDimitry Andric #endif /* CLANG_LIB_BASIC_BUILTINTARGETFEATURES_H */ 96