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