1//===------------------------------------------------------------*- 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#ifndef LLVM_UTILS_TABLEGEN_COMMON_RUNTIMELIBCALLS_H
10#define LLVM_UTILS_TABLEGEN_COMMON_RUNTIMELIBCALLS_H
11
12#include "llvm/ADT/StringRef.h"
13#include "llvm/Support/raw_ostream.h"
14#include "llvm/TableGen/Record.h"
15#include "llvm/TableGen/SetTheory.h"
16
17namespace llvm {
18
19class AvailabilityPredicate {
20 const Record *TheDef;
21 std::string PredicateString;
22
23public:
24 AvailabilityPredicate(const Record *Def) : TheDef(Def) {
25 if (!TheDef)
26 return;
27 if (const RecordVal *RV = TheDef->getValue(Name: "CondDag")) {
28 if (const auto *Dag = dyn_cast_or_null<DagInit>(Val: RV->getValue())) {
29 PredicateString = lowerCondDag(Owner: TheDef, Val: Dag);
30 return;
31 }
32 }
33 PredicateString = TheDef->getValueAsString(FieldName: "Cond").str();
34 }
35
36 const Record *getDef() const { return TheDef; }
37
38 bool isAlwaysAvailable() const { return PredicateString.empty(); }
39
40 void emitIf(raw_ostream &OS) const {
41 OS << "if (" << PredicateString << ") {\n";
42 }
43
44 void emitEndIf(raw_ostream &OS) const { OS << "}\n"; }
45
46 void emitTableVariableNameSuffix(raw_ostream &OS) const {
47 if (TheDef)
48 OS << '_' << TheDef->getName();
49 }
50
51private:
52 // Lower a (all_of/any_of/not <LibcallPredicate>...) dag to a C++ boolean
53 // expression.
54 static std::string lowerCondDag(const Record *Owner, const Init *Val,
55 bool ParenIfBinOp = false);
56};
57
58class RuntimeLibcalls;
59class RuntimeLibcallImpl;
60
61/// Used to apply predicates to nested sets of libcalls.
62struct LibcallPredicateExpander : SetTheory::Expander {
63 const RuntimeLibcalls &Libcalls;
64 DenseMap<const RuntimeLibcallImpl *,
65 std::pair<std::vector<const Record *>, const Record *>> &Func2Preds;
66
67 LibcallPredicateExpander(
68 const RuntimeLibcalls &Libcalls,
69 DenseMap<const RuntimeLibcallImpl *,
70 std::pair<std::vector<const Record *>, const Record *>>
71 &Func2Preds)
72 : Libcalls(Libcalls), Func2Preds(Func2Preds) {}
73
74 void expand(SetTheory &ST, const Record *Def,
75 SetTheory::RecSet &Elts) override;
76};
77
78class RuntimeLibcall {
79 const Record *TheDef = nullptr;
80 const size_t EnumVal;
81
82public:
83 RuntimeLibcall() = delete;
84 RuntimeLibcall(const Record *Def, size_t EnumVal)
85 : TheDef(Def), EnumVal(EnumVal) {
86 assert(Def);
87 }
88
89 ~RuntimeLibcall() { assert(TheDef); }
90
91 const Record *getDef() const { return TheDef; }
92
93 StringRef getName() const { return TheDef->getName(); }
94
95 size_t getEnumVal() const { return EnumVal; }
96
97 void emitEnumEntry(raw_ostream &OS) const {
98 OS << "RTLIB::" << TheDef->getValueAsString(FieldName: "Name");
99 }
100};
101
102class RuntimeLibcallImpl {
103 const Record *TheDef;
104 const RuntimeLibcall *Provides = nullptr;
105 const size_t EnumVal;
106
107public:
108 RuntimeLibcallImpl(
109 const Record *Def,
110 const DenseMap<const Record *, const RuntimeLibcall *> &ProvideMap,
111 size_t EnumVal)
112 : TheDef(Def), EnumVal(EnumVal) {
113 if (const Record *ProvidesDef = Def->getValueAsDef(FieldName: "Provides"))
114 Provides = ProvideMap.lookup(Val: ProvidesDef);
115 }
116
117 ~RuntimeLibcallImpl() = default;
118
119 const Record *getDef() const { return TheDef; }
120
121 StringRef getName() const { return TheDef->getName(); }
122
123 size_t getEnumVal() const { return EnumVal; }
124
125 const RuntimeLibcall *getProvides() const { return Provides; }
126
127 StringRef getLibcallFuncName() const {
128 return TheDef->getValueAsString(FieldName: "LibCallFuncName");
129 }
130
131 const Record *getCallingConv() const {
132 return TheDef->getValueAsOptionalDef(FieldName: "CallingConv");
133 }
134
135 void emitQuotedLibcallFuncName(raw_ostream &OS) const {
136 OS << '\"' << getLibcallFuncName() << '\"';
137 }
138
139 bool isDefault() const { return TheDef->getValueAsBit(FieldName: "IsDefault"); }
140
141 void emitEnumEntry(raw_ostream &OS) const {
142 OS << "RTLIB::impl_" << this->getName();
143 }
144
145 void emitSetImplCall(raw_ostream &OS) const {
146 OS << "setLibcallImpl(";
147 Provides->emitEnumEntry(OS);
148 OS << ", ";
149 emitEnumEntry(OS);
150 OS << "); // " << getLibcallFuncName() << '\n';
151 }
152
153 void emitTableEntry(raw_ostream &OS) const {
154 OS << '{';
155 Provides->emitEnumEntry(OS);
156 OS << ", ";
157 emitEnumEntry(OS);
158 OS << "}, // " << getLibcallFuncName() << '\n';
159 }
160
161 void emitSetCallingConv(raw_ostream &OS) const {}
162};
163
164struct LibcallsWithCC {
165 std::vector<const RuntimeLibcallImpl *> LibcallImpls;
166 const Record *CallingConv = nullptr;
167};
168
169class RuntimeLibcalls {
170private:
171 DenseMap<const Record *, const RuntimeLibcall *> Def2RuntimeLibcall;
172 DenseMap<const Record *, const RuntimeLibcallImpl *> Def2RuntimeLibcallImpl;
173
174 std::vector<RuntimeLibcall> RuntimeLibcallDefList;
175 std::vector<RuntimeLibcallImpl> RuntimeLibcallImplDefList;
176
177 DenseMap<const RuntimeLibcall *, const RuntimeLibcallImpl *>
178 LibCallToDefaultImpl;
179
180public:
181 RuntimeLibcalls(const RecordKeeper &Records);
182
183 ArrayRef<RuntimeLibcall> getRuntimeLibcallDefList() const {
184 return RuntimeLibcallDefList;
185 }
186
187 ArrayRef<RuntimeLibcallImpl> getRuntimeLibcallImplDefList() const {
188 return RuntimeLibcallImplDefList;
189 }
190
191 const RuntimeLibcall *getRuntimeLibcall(const Record *Def) const {
192 return Def2RuntimeLibcall.lookup(Val: Def);
193 }
194
195 const RuntimeLibcallImpl *getRuntimeLibcallImpl(const Record *Def) const {
196 return Def2RuntimeLibcallImpl.lookup(Val: Def);
197 }
198};
199
200} // namespace llvm
201
202#endif // LLVM_UTILS_TABLEGEN_COMMON_RUNTIMELIBCALLS_H
203