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 bool isDefault() const { return TheDef->getValueAsBit(FieldName: "IsDefault"); }
139
140 void emitEnumEntry(raw_ostream &OS) const {
141 OS << "RTLIB::impl_" << this->getName();
142 }
143
144 void emitSetImplCall(raw_ostream &OS) const {
145 OS << "setLibcallImpl(";
146 Provides->emitEnumEntry(OS);
147 OS << ", ";
148 emitEnumEntry(OS);
149 OS << "); // " << getLibcallFuncName() << '\n';
150 }
151
152 void emitTableEntry(raw_ostream &OS) const {
153 OS << '{';
154 Provides->emitEnumEntry(OS);
155 OS << ", ";
156 emitEnumEntry(OS);
157 OS << "}, // " << getLibcallFuncName() << '\n';
158 }
159
160 void emitSetCallingConv(raw_ostream &OS) const {}
161};
162
163struct LibcallsWithCC {
164 std::vector<const RuntimeLibcallImpl *> LibcallImpls;
165 const Record *CallingConv = nullptr;
166};
167
168class RuntimeLibcalls {
169private:
170 DenseMap<const Record *, const RuntimeLibcall *> Def2RuntimeLibcall;
171 DenseMap<const Record *, const RuntimeLibcallImpl *> Def2RuntimeLibcallImpl;
172
173 std::vector<RuntimeLibcall> RuntimeLibcallDefList;
174 std::vector<RuntimeLibcallImpl> RuntimeLibcallImplDefList;
175
176 DenseMap<const RuntimeLibcall *, const RuntimeLibcallImpl *>
177 LibCallToDefaultImpl;
178
179public:
180 RuntimeLibcalls(const RecordKeeper &Records);
181
182 ArrayRef<RuntimeLibcall> getRuntimeLibcallDefList() const {
183 return RuntimeLibcallDefList;
184 }
185
186 ArrayRef<RuntimeLibcallImpl> getRuntimeLibcallImplDefList() const {
187 return RuntimeLibcallImplDefList;
188 }
189
190 const RuntimeLibcall *getRuntimeLibcall(const Record *Def) const {
191 return Def2RuntimeLibcall.lookup(Val: Def);
192 }
193
194 const RuntimeLibcallImpl *getRuntimeLibcallImpl(const Record *Def) const {
195 return Def2RuntimeLibcallImpl.lookup(Val: Def);
196 }
197};
198
199} // namespace llvm
200
201#endif // LLVM_UTILS_TABLEGEN_COMMON_RUNTIMELIBCALLS_H
202