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