Skip to content

Commit c6778cc

Browse files
committed
tablegen: refactor OpClass and Operation with a common base class
Common up the handling of arguments and argument getter generation. This happens to fix a bug where type arguments were handled correctly for Operation but not for OpClass
1 parent b5e9fe7 commit c6778cc

File tree

4 files changed

+186
-183
lines changed

4 files changed

+186
-183
lines changed

include/llvm-dialects/TableGen/Operations.h

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class BuilderMethod;
3535
class FmtContext;
3636
class GenDialectsContext;
3737
class GenDialect;
38+
class OpClass;
3839
class Operation;
3940
class Trait;
4041

@@ -48,38 +49,53 @@ struct OverloadKey {
4849
unsigned index;
4950
};
5051

51-
class OpClass {
52+
// Base class for OpClass and Operation
53+
class OperationBase {
5254
public:
53-
GenDialect *dialect = nullptr;
54-
OpClass *superclass = nullptr;
55-
std::string name;
55+
GenDialect *dialect() const { return m_dialect; }
56+
OpClass *superclass() const { return m_superclass; }
57+
58+
llvm::SmallVector<NamedValue> getFullArguments() const;
59+
unsigned getNumFullArguments() const;
60+
61+
void emitArgumentAccessorDeclarations(llvm::raw_ostream &out,
62+
FmtContext &fmt) const;
63+
void emitArgumentAccessorDefinitions(llvm::raw_ostream &out,
64+
FmtContext &fmt) const;
65+
66+
protected:
67+
bool init(llvm::raw_ostream &errs, GenDialectsContext &context,
68+
llvm::Record *record);
69+
70+
private:
71+
GenDialect *m_dialect = nullptr;
72+
OpClass *m_superclass = nullptr;
5673

5774
/// List of arguments specific to this class; does not contain superclass
5875
/// arguments, if any.
59-
std::vector<NamedValue> arguments;
76+
std::vector<NamedValue> m_arguments;
77+
};
78+
79+
class OpClass : public OperationBase {
80+
public:
81+
std::string name;
82+
6083
std::vector<OpClass *> subclasses;
6184
std::vector<Operation *> operations;
6285

6386
static std::unique_ptr<OpClass> parse(llvm::raw_ostream &errs,
6487
GenDialectsContext &context,
6588
llvm::Record *record);
66-
67-
llvm::SmallVector<NamedValue> getFullArguments() const;
68-
unsigned getNumFullArguments() const;
6989
};
7090

71-
class Operation {
91+
class Operation : public OperationBase {
7292
friend class BuilderMethod;
7393

7494
public:
75-
OpClass *superclass = nullptr;
7695
std::string name;
7796
std::string mnemonic;
7897
std::vector<Trait *> traits;
7998

80-
/// List of arguments specific to this operation; does not contain superclass
81-
/// arguments, if any.
82-
std::vector<NamedValue> arguments;
8399
std::vector<NamedValue> results;
84100

85101
Operation(GenDialectsContext &context) : m_system(context, m_scope) {}
@@ -93,9 +109,6 @@ class Operation {
93109

94110
llvm::ArrayRef<BuilderMethod> builders() const { return m_builders; }
95111

96-
llvm::SmallVector<NamedValue> getFullArguments() const;
97-
unsigned getNumFullArguments() const;
98-
99112
int getAttributeListIdx() const { return m_attributeListIdx; }
100113

101114
void emitVerifierMethod(llvm::raw_ostream &out, FmtContext &fmt) const;

lib/TableGen/GenDialect.cpp

Lines changed: 10 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@ class Builder;
145145
return ::llvm::isa<::llvm::CallInst>(v) &&
146146
classof(::llvm::cast<::llvm::CallInst>(v));
147147
}
148-
)", &fmt, opClass->superclass ? opClass->superclass->name : "::llvm::CallInst");
148+
)",
149+
&fmt,
150+
opClass->superclass() ? opClass->superclass()->name
151+
: "::llvm::CallInst");
149152

150-
for (const auto& arg : opClass->arguments) {
151-
out << tgfmt("$0 get$1();\n", &fmt, arg.type->getBuilderCppType(),
152-
convertToCamelFromSnakeCase(arg.name, true));
153-
}
153+
opClass->emitArgumentAccessorDeclarations(out, fmt);
154154

155155
out << R"(
156156
};
@@ -178,7 +178,8 @@ class Builder;
178178
classof(::llvm::cast<::llvm::CallInst>(v));
179179
}
180180
)",
181-
&fmt, op.superclass ? op.superclass->name : "::llvm::CallInst",
181+
&fmt,
182+
op.superclass() ? op.superclass()->name : "::llvm::CallInst",
182183
!op.haveResultOverloads() ? "isSimpleOperation"
183184
: "isOverloadedOperation");
184185

@@ -188,10 +189,7 @@ class Builder;
188189

189190
out << "bool verifier(::llvm::raw_ostream &errs);\n\n";
190191

191-
for (const auto& arg : op.arguments) {
192-
out << tgfmt("$0 get$1();\n", &fmt, arg.type->getBuilderCppType(),
193-
convertToCamelFromSnakeCase(arg.name, true));
194-
}
192+
op.emitArgumentAccessorDeclarations(out, fmt);
195193

196194
out << '\n';
197195

@@ -359,23 +357,7 @@ void llvm_dialects::genDialectDefs(raw_ostream& out, RecordKeeper& records) {
359357
)", &fmt);
360358

361359
// Emit argument getters.
362-
unsigned numSuperclassArgs = 0;
363-
if (opClass->superclass)
364-
numSuperclassArgs = opClass->superclass->getNumFullArguments();
365-
for (auto indexedArg : llvm::enumerate(opClass->arguments)) {
366-
const NamedValue& arg = indexedArg.value();
367-
std::string value = llvm::formatv("getArgOperand({0})",
368-
numSuperclassArgs + indexedArg.index());
369-
if (auto* attr = dyn_cast<Attr>(arg.type))
370-
value = tgfmt(attr->getFromLlvmValue(), &fmt, value);
371-
out << tgfmt(R"(
372-
$0 $_op::get$1() {
373-
return $2;
374-
}
375-
)",
376-
&fmt, arg.type->getBuilderCppType(),
377-
convertToCamelFromSnakeCase(arg.name, true), value);
378-
}
360+
opClass->emitArgumentAccessorDefinitions(out, fmt);
379361

380362
out << '\n';
381363
}
@@ -399,26 +381,7 @@ void llvm_dialects::genDialectDefs(raw_ostream& out, RecordKeeper& records) {
399381
op.emitVerifierMethod(out, fmt);
400382

401383
// Emit argument getters.
402-
unsigned numSuperclassArgs = 0;
403-
if (op.superclass)
404-
numSuperclassArgs = op.superclass->getNumFullArguments();
405-
for (auto indexedArg : llvm::enumerate(op.arguments)) {
406-
const NamedValue& arg = indexedArg.value();
407-
std::string value = llvm::formatv("getArgOperand({0})",
408-
numSuperclassArgs + indexedArg.index());
409-
if (auto* attr = dyn_cast<Attr>(arg.type))
410-
value = tgfmt(attr->getFromLlvmValue(), &fmt, value);
411-
else if (arg.type->isTypeArg())
412-
value += "->getType()";
413-
414-
out << tgfmt(R"(
415-
$0 $_op::get$1() {
416-
return $2;
417-
}
418-
)",
419-
&fmt, arg.type->getBuilderCppType(),
420-
convertToCamelFromSnakeCase(arg.name, true), value);
421-
}
384+
op.emitArgumentAccessorDefinitions(out, fmt);
422385

423386
out << '\n';
424387

lib/TableGen/Operations.cpp

Lines changed: 75 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@
2525
using namespace llvm;
2626
using namespace llvm_dialects;
2727

28-
// Default destructor instantiated explicitly to avoid having to add more
29-
// includes in the header.
30-
Operation::~Operation() = default;
31-
3228
static std::optional<std::vector<NamedValue>>
3329
parseArguments(raw_ostream &errs, GenDialectsContext &context, Record *rec) {
3430
Record *superClassRec = rec->getValueAsDef("superclass");
@@ -54,38 +50,78 @@ parseArguments(raw_ostream &errs, GenDialectsContext &context, Record *rec) {
5450
NamedValue::Parser::OperationArguments);
5551
}
5652

57-
std::unique_ptr<OpClass>
58-
OpClass::parse(raw_ostream &errs, GenDialectsContext &context, Record *record) {
59-
auto opClass = std::make_unique<OpClass>();
60-
opClass->dialect = context.getDialect(record->getValueAsDef("dialect"));
61-
opClass->name = record->getName();
62-
opClass->superclass = context.getOpClass(record->getValueAsDef("superclass"));
53+
bool OperationBase::init(raw_ostream &errs, GenDialectsContext &context,
54+
Record *record) {
55+
m_dialect = context.getDialect(record->getValueAsDef("dialect"));
56+
m_superclass = context.getOpClass(record->getValueAsDef("superclass"));
6357

6458
auto arguments = parseArguments(errs, context, record);
6559
if (!arguments.has_value())
66-
return {};
67-
opClass->arguments = std::move(*arguments);
68-
69-
OpClass *ptr = opClass.get();
70-
opClass->dialect->opClasses.push_back(opClass.get());
71-
if (opClass->superclass)
72-
opClass->superclass->subclasses.push_back(ptr);
60+
return false;
61+
m_arguments = std::move(*arguments);
7362

74-
return opClass;
63+
return true;
7564
}
7665

77-
SmallVector<NamedValue> OpClass::getFullArguments() const {
66+
SmallVector<NamedValue> OperationBase::getFullArguments() const {
7867
SmallVector<NamedValue> args;
79-
if (superclass)
80-
args = superclass->getFullArguments();
81-
args.insert(args.end(), arguments.begin(), arguments.end());
68+
if (m_superclass)
69+
args = m_superclass->getFullArguments();
70+
args.insert(args.end(), m_arguments.begin(), m_arguments.end());
8271
return args;
8372
}
8473

85-
unsigned OpClass::getNumFullArguments() const {
86-
if (superclass)
87-
return superclass->getNumFullArguments() + arguments.size();
88-
return arguments.size();
74+
unsigned OperationBase::getNumFullArguments() const {
75+
if (m_superclass)
76+
return m_superclass->getNumFullArguments() + m_arguments.size();
77+
return m_arguments.size();
78+
}
79+
80+
void OperationBase::emitArgumentAccessorDeclarations(llvm::raw_ostream &out,
81+
FmtContext &fmt) const {
82+
for (const auto &arg : m_arguments) {
83+
out << tgfmt("$0 get$1();\n", &fmt, arg.type->getBuilderCppType(),
84+
convertToCamelFromSnakeCase(arg.name, true));
85+
}
86+
}
87+
88+
void OperationBase::emitArgumentAccessorDefinitions(llvm::raw_ostream &out,
89+
FmtContext &fmt) const {
90+
unsigned numSuperclassArgs = 0;
91+
if (m_superclass)
92+
numSuperclassArgs = m_superclass->getNumFullArguments();
93+
for (auto indexedArg : llvm::enumerate(m_arguments)) {
94+
const NamedValue &arg = indexedArg.value();
95+
std::string value = llvm::formatv("getArgOperand({0})",
96+
numSuperclassArgs + indexedArg.index());
97+
if (auto *attr = dyn_cast<Attr>(arg.type))
98+
value = tgfmt(attr->getFromLlvmValue(), &fmt, value);
99+
else if (arg.type->isTypeArg())
100+
value += "->getType()";
101+
out << tgfmt(R"(
102+
$0 $_op::get$1() {
103+
return $2;
104+
}
105+
)",
106+
&fmt, arg.type->getBuilderCppType(),
107+
convertToCamelFromSnakeCase(arg.name, true), value);
108+
}
109+
}
110+
111+
std::unique_ptr<OpClass>
112+
OpClass::parse(raw_ostream &errs, GenDialectsContext &context, Record *record) {
113+
auto opClass = std::make_unique<OpClass>();
114+
opClass->name = record->getName();
115+
116+
if (!opClass->init(errs, context, record))
117+
return {};
118+
119+
OpClass *ptr = opClass.get();
120+
opClass->dialect()->opClasses.push_back(opClass.get());
121+
if (opClass->superclass())
122+
opClass->superclass()->subclasses.push_back(ptr);
123+
124+
return opClass;
89125
}
90126

91127
static std::string evaluateAttrLlvmType(raw_ostream &errs, raw_ostream &out,
@@ -113,22 +149,27 @@ static std::string evaluateAttrLlvmType(raw_ostream &errs, raw_ostream &out,
113149
return attrType;
114150
}
115151

152+
// Default destructor instantiated explicitly to avoid having to add more
153+
// includes in the header.
154+
Operation::~Operation() = default;
155+
116156
bool Operation::parse(raw_ostream &errs, GenDialectsContext *context,
117157
GenDialect *dialect, Record *record) {
118158
auto op = std::make_unique<Operation>(*context);
119-
op->superclass = context->getOpClass(record->getValueAsDef("superclass"));
120-
if (op->superclass)
121-
op->superclass->operations.push_back(op.get());
159+
160+
if (!op->init(errs, *context, record))
161+
return false;
162+
163+
assert(op->dialect() == dialect);
164+
165+
if (op->superclass())
166+
op->superclass()->operations.push_back(op.get());
167+
122168
op->name = record->getName();
123169
op->mnemonic = record->getValueAsString("mnemonic");
124170
for (Record *traitRec : record->getValueAsListOfDefs("traits"))
125171
op->traits.push_back(context->getTrait(traitRec));
126172

127-
auto arguments = parseArguments(errs, *context, record);
128-
if (!arguments.has_value())
129-
return false;
130-
op->arguments = std::move(*arguments);
131-
132173
EvaluationPlanner evaluation(op->m_system);
133174

134175
for (const auto &arg : op->getFullArguments()) {
@@ -265,20 +306,6 @@ bool Operation::parse(raw_ostream &errs, GenDialectsContext *context,
265306
return true;
266307
}
267308

268-
SmallVector<NamedValue> Operation::getFullArguments() const {
269-
SmallVector<NamedValue> args;
270-
if (superclass)
271-
args = superclass->getFullArguments();
272-
args.insert(args.end(), arguments.begin(), arguments.end());
273-
return args;
274-
}
275-
276-
unsigned Operation::getNumFullArguments() const {
277-
if (superclass)
278-
return superclass->getNumFullArguments() + arguments.size();
279-
return arguments.size();
280-
}
281-
282309
void Operation::emitVerifierMethod(llvm::raw_ostream &out,
283310
FmtContext &fmt) const {
284311
SymbolTable symbols;

0 commit comments

Comments
 (0)