1356843Sdim//===- OptEmitter.cpp - Helper for emitting options.----------- -----------===// 2356843Sdim// 3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4356843Sdim// See https://llvm.org/LICENSE.txt for license information. 5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6356843Sdim// 7356843Sdim//===----------------------------------------------------------------------===// 8356843Sdim 9356843Sdim#include "OptEmitter.h" 10356843Sdim#include "llvm/ADT/Twine.h" 11356843Sdim#include "llvm/TableGen/Error.h" 12356843Sdim#include "llvm/TableGen/Record.h" 13356843Sdim#include <cctype> 14356843Sdim#include <cstring> 15356843Sdim 16356843Sdimnamespace llvm { 17356843Sdim 18356843Sdim// Ordering on Info. The logic should match with the consumer-side function in 19356843Sdim// llvm/Option/OptTable.h. 20356843Sdim// FIXME: Make this take StringRefs instead of null terminated strings to 21356843Sdim// simplify callers. 22356843Sdimstatic int StrCmpOptionName(const char *A, const char *B) { 23356843Sdim const char *X = A, *Y = B; 24356843Sdim char a = tolower(*A), b = tolower(*B); 25356843Sdim while (a == b) { 26356843Sdim if (a == '\0') 27356843Sdim return strcmp(A, B); 28356843Sdim 29356843Sdim a = tolower(*++X); 30356843Sdim b = tolower(*++Y); 31356843Sdim } 32356843Sdim 33356843Sdim if (a == '\0') // A is a prefix of B. 34356843Sdim return 1; 35356843Sdim if (b == '\0') // B is a prefix of A. 36356843Sdim return -1; 37356843Sdim 38356843Sdim // Otherwise lexicographic. 39356843Sdim return (a < b) ? -1 : 1; 40356843Sdim} 41356843Sdim 42356843Sdimint CompareOptionRecords(Record *const *Av, Record *const *Bv) { 43356843Sdim const Record *A = *Av; 44356843Sdim const Record *B = *Bv; 45356843Sdim 46356843Sdim // Sentinel options precede all others and are only ordered by precedence. 47356843Sdim bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 48356843Sdim bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 49356843Sdim if (ASent != BSent) 50356843Sdim return ASent ? -1 : 1; 51356843Sdim 52356843Sdim // Compare options by name, unless they are sentinels. 53356843Sdim if (!ASent) 54356843Sdim if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").str().c_str(), 55356843Sdim B->getValueAsString("Name").str().c_str())) 56356843Sdim return Cmp; 57356843Sdim 58356843Sdim if (!ASent) { 59356843Sdim std::vector<StringRef> APrefixes = A->getValueAsListOfStrings("Prefixes"); 60356843Sdim std::vector<StringRef> BPrefixes = B->getValueAsListOfStrings("Prefixes"); 61356843Sdim 62356843Sdim for (std::vector<StringRef>::const_iterator APre = APrefixes.begin(), 63356843Sdim AEPre = APrefixes.end(), 64356843Sdim BPre = BPrefixes.begin(), 65356843Sdim BEPre = BPrefixes.end(); 66356843Sdim APre != AEPre && BPre != BEPre; ++APre, ++BPre) { 67356843Sdim if (int Cmp = StrCmpOptionName(APre->str().c_str(), BPre->str().c_str())) 68356843Sdim return Cmp; 69356843Sdim } 70356843Sdim } 71356843Sdim 72356843Sdim // Then by the kind precedence; 73356843Sdim int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence"); 74356843Sdim int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence"); 75356843Sdim if (APrec == BPrec && A->getValueAsListOfStrings("Prefixes") == 76356843Sdim B->getValueAsListOfStrings("Prefixes")) { 77356843Sdim PrintError(A->getLoc(), Twine("Option is equivalent to")); 78356843Sdim PrintError(B->getLoc(), Twine("Other defined here")); 79356843Sdim PrintFatalError("Equivalent Options found."); 80356843Sdim } 81356843Sdim return APrec < BPrec ? -1 : 1; 82356843Sdim} 83356843Sdim 84356843Sdim} // namespace llvm 85