Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Basic/BuiltinTargetFeatures.h
Line
Count
Source (jump to first uncovered line)
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
40
0
  FeatureListStatus getAndFeatures(StringRef FeatureList) {
41
0
    int InParentheses = 0;
42
0
    bool HasFeatures = true;
43
0
    size_t SubexpressionStart = 0;
44
0
    for (size_t i = 0, e = FeatureList.size(); i < e; ++i) {
45
0
      char CurrentToken = FeatureList[i];
46
0
      switch (CurrentToken) {
47
0
      default:
48
0
        break;
49
0
      case '(':
50
0
        if (InParentheses == 0)
51
0
          SubexpressionStart = i + 1;
52
0
        ++InParentheses;
53
0
        break;
54
0
      case ')':
55
0
        --InParentheses;
56
0
        assert(InParentheses >= 0 && "Parentheses are not in pair");
57
0
        [[fallthrough]];
58
0
      case '|':
59
0
      case ',':
60
0
        if (InParentheses == 0) {
61
0
          if (HasFeatures && i != SubexpressionStart) {
62
0
            StringRef F = FeatureList.slice(SubexpressionStart, i);
63
0
            HasFeatures = CurrentToken == ')' ? hasRequiredFeatures(F)
64
0
                                              : CallerFeatureMap.lookup(F);
65
0
          }
66
0
          SubexpressionStart = i + 1;
67
0
          if (CurrentToken == '|') {
68
0
            return {HasFeatures, FeatureList.substr(SubexpressionStart)};
69
0
          }
70
0
        }
71
0
        break;
72
0
      }
73
0
    }
74
0
    assert(InParentheses == 0 && "Parentheses are not in pair");
75
0
    if (HasFeatures && SubexpressionStart != FeatureList.size())
76
0
      HasFeatures =
77
0
          CallerFeatureMap.lookup(FeatureList.substr(SubexpressionStart));
78
0
    return {HasFeatures, StringRef()};
79
0
  }
80
81
public:
82
0
  bool hasRequiredFeatures(StringRef FeatureList) {
83
0
    FeatureListStatus FS = {false, FeatureList};
84
0
    while (!FS.HasFeatures && !FS.CurFeaturesList.empty())
85
0
      FS = getAndFeatures(FS.CurFeaturesList);
86
0
    return FS.HasFeatures;
87
0
  }
88
89
  TargetFeatures(const llvm::StringMap<bool> &CallerFeatureMap)
90
0
      : CallerFeatureMap(CallerFeatureMap) {}
91
};
92
93
} // namespace Builtin
94
} // namespace clang
95
#endif /* CLANG_LIB_BASIC_BUILTINTARGETFEATURES_H */