Skip to content

Commit

Permalink
Error if duplicated mnemonics are found.
Browse files Browse the repository at this point in the history
We currently don't emit an error when a dialect defines two dialect operations
with the same mnemonic. This change emits basic information about duplicate
mnemonics.

Since this requires a `O(n)` loop worst-case, store the mnemonic counts per
dialect in a `StringMap` and iterate over it during finalization of the dialect,
which then also bails out.

Can possibly be extended to all kinds of duplicated symbols.
  • Loading branch information
tsymalla authored and tsymalla-AMD committed Feb 6, 2024
1 parent c82337d commit e6cbcfd
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 3 deletions.
4 changes: 3 additions & 1 deletion include/llvm-dialects/TableGen/Dialects.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringMap.h"

namespace llvm {
class DagInit;
Expand All @@ -47,10 +48,11 @@ class GenDialect {
std::string cppNamespace;
std::vector<DialectType *> types;
std::vector<OpClass *> opClasses;
llvm::StringMap<unsigned> operationCounts;
std::vector<std::unique_ptr<Operation>> operations;

public:
void finalize();
void finalize(llvm::raw_ostream &errs);

llvm::ArrayRef<std::vector<Trait *>> attribute_lists() const {
return m_attributeLists;
Expand Down
16 changes: 14 additions & 2 deletions lib/TableGen/Dialects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
using namespace llvm;
using namespace llvm_dialects;

void GenDialect::finalize() {
void GenDialect::finalize(raw_ostream &errs) {
// Build the list of different attribute lists.
auto traitLess = [](Trait *lhs, Trait *rhs) {
return lhs->getName() < rhs->getName();
Expand All @@ -41,6 +41,18 @@ void GenDialect::finalize() {

std::vector<Operation *> traitOperations;

bool hasDuplicates = false;
for (const auto &[op, count] : operationCounts) {
if (count != 1) {
errs << "Found op with non-unique mnemonic: " << op << '\n';
hasDuplicates = true;
}
}

if (hasDuplicates)
report_fatal_error(
"Aborting dialect generation since non-unique mnemonics were found!");

for (const auto &op : operations) {
if (op->traits.empty())
continue;
Expand Down Expand Up @@ -219,5 +231,5 @@ void GenDialectsContext::init(RecordKeeper &records,
}

for (auto &dialectEntry : m_dialects)
dialectEntry.second->finalize();
dialectEntry.second->finalize(llvm::errs());
}
1 change: 1 addition & 0 deletions lib/TableGen/Operations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ bool Operation::parse(raw_ostream &errs, GenDialectsContext *context,

op->m_builders.push_back(std::move(builder));

++dialect->operationCounts[op->mnemonic];
dialect->operations.push_back(std::move(op));

return true;
Expand Down
45 changes: 45 additions & 0 deletions test/tablegen/duplicate-ops.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// RUN: not --crash llvm-dialects-tblgen -gen-dialect-defs -dialect=dups -I%S/../../include %s 2>&1 | FileCheck --check-prefixes=CHECK %s

// CHECK: Found op with non-unique mnemonic: duplicate.op
// CHECK-NEXT: Found op with non-unique mnemonic: duplicate.op.1
// CHECK-NEXT: LLVM ERROR: Aborting dialect generation since non-unique mnemonics were found!

include "llvm-dialects/Dialect/Dialect.td"

def TestDialect : Dialect {
let name = "dups";
let cppNamespace = "dups";
}

class TestOp<string mnemonic_, list<Trait> traits_>
: Op<TestDialect, mnemonic_, traits_>;

def DuplicateOp : TestOp<"duplicate.op",
[]> {
let results = (outs);
let arguments = (ins);
}

def DuplicateOp1 : TestOp<"duplicate.op",
[]> {
let results = (outs);
let arguments = (ins);
}

def DuplicateOp2 : TestOp<"duplicate.op.1",
[]> {
let results = (outs);
let arguments = (ins);
}

def DuplicateOp3 : TestOp<"duplicate.op.1",
[]> {
let results = (outs);
let arguments = (ins);
}

def UniqueOp : TestOp<"unique.op",
[]> {
let results = (outs);
let arguments = (ins);
}

0 comments on commit e6cbcfd

Please sign in to comment.