xref: /llvm-project/llvm/utils/TableGen/Common/Utils.cpp (revision 3ae71d154e5dfb5e5a5d27b3699b27ce2b55f44d)
18ce5a32fSRahul Joshi //===- Utils.cpp - Common Utilities -----------------------------*- C++ -*-===//
28ce5a32fSRahul Joshi //
38ce5a32fSRahul Joshi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48ce5a32fSRahul Joshi // See https://llvm.org/LICENSE.txt for license information.
58ce5a32fSRahul Joshi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68ce5a32fSRahul Joshi //
78ce5a32fSRahul Joshi //===----------------------------------------------------------------------===//
88ce5a32fSRahul Joshi 
98ce5a32fSRahul Joshi #include "Utils.h"
108ce5a32fSRahul Joshi #include "llvm/ADT/STLExtras.h"
118ce5a32fSRahul Joshi #include "llvm/TableGen/Error.h"
128ce5a32fSRahul Joshi #include "llvm/TableGen/Record.h"
138ce5a32fSRahul Joshi #include <algorithm>
148ce5a32fSRahul Joshi 
158ce5a32fSRahul Joshi using namespace llvm;
168ce5a32fSRahul Joshi 
178ce5a32fSRahul Joshi namespace {
188ce5a32fSRahul Joshi /// Sorting predicate to sort record pointers by their Name field, and break
198ce5a32fSRahul Joshi /// ties using record ID (which corresponds to creation/parse order).
208ce5a32fSRahul Joshi struct LessRecordFieldNameAndID {
218ce5a32fSRahul Joshi   bool operator()(const Record *Rec1, const Record *Rec2) const {
228ce5a32fSRahul Joshi     return std::tuple(Rec1->getValueAsString("Name"), Rec1->getID()) <
238ce5a32fSRahul Joshi            std::tuple(Rec2->getValueAsString("Name"), Rec2->getID());
248ce5a32fSRahul Joshi   }
258ce5a32fSRahul Joshi };
268ce5a32fSRahul Joshi } // End anonymous namespace
278ce5a32fSRahul Joshi 
288ce5a32fSRahul Joshi /// Sort an array of Records on the "Name" field, and check for records with
298ce5a32fSRahul Joshi /// duplicate "Name" field. If duplicates are found, report a fatal error.
30*3ae71d15SRahul Joshi void llvm::sortAndReportDuplicates(MutableArrayRef<const Record *> Records,
318ce5a32fSRahul Joshi                                    StringRef ObjectName) {
328ce5a32fSRahul Joshi   llvm::sort(Records, LessRecordFieldNameAndID());
338ce5a32fSRahul Joshi 
348ce5a32fSRahul Joshi   auto I = std::adjacent_find(Records.begin(), Records.end(),
358ce5a32fSRahul Joshi                               [](const Record *Rec1, const Record *Rec2) {
368ce5a32fSRahul Joshi                                 return Rec1->getValueAsString("Name") ==
378ce5a32fSRahul Joshi                                        Rec2->getValueAsString("Name");
388ce5a32fSRahul Joshi                               });
398ce5a32fSRahul Joshi   if (I == Records.end())
408ce5a32fSRahul Joshi     return;
418ce5a32fSRahul Joshi 
428ce5a32fSRahul Joshi   // Found a duplicate name.
438ce5a32fSRahul Joshi   const Record *First = *I;
448ce5a32fSRahul Joshi   const Record *Second = *(I + 1);
458ce5a32fSRahul Joshi   StringRef Name = First->getValueAsString("Name");
468ce5a32fSRahul Joshi   PrintError(Second, ObjectName + " `" + Name + "` is already defined.");
478ce5a32fSRahul Joshi   PrintFatalNote(First, "Previous definition here.");
488ce5a32fSRahul Joshi }
49