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