1 //===- OptEmitter.cpp - Helper for emitting options.----------- -----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "OptEmitter.h" 10 #include "llvm/ADT/Twine.h" 11 #include "llvm/TableGen/Error.h" 12 #include "llvm/TableGen/Record.h" 13 #include <cctype> 14 #include <cstring> 15 16 namespace llvm { 17 18 // Ordering on Info. The logic should match with the consumer-side function in 19 // llvm/Option/OptTable.h. 20 // FIXME: Make this take StringRefs instead of null terminated strings to 21 // simplify callers. 22 static int StrCmpOptionName(const char *A, const char *B) { 23 const char *X = A, *Y = B; 24 char a = tolower(*A), b = tolower(*B); 25 while (a == b) { 26 if (a == '\0') 27 return strcmp(A, B); 28 29 a = tolower(*++X); 30 b = tolower(*++Y); 31 } 32 33 if (a == '\0') // A is a prefix of B. 34 return 1; 35 if (b == '\0') // B is a prefix of A. 36 return -1; 37 38 // Otherwise lexicographic. 39 return (a < b) ? -1 : 1; 40 } 41 42 int CompareOptionRecords(Record *const *Av, Record *const *Bv) { 43 const Record *A = *Av; 44 const Record *B = *Bv; 45 46 // Sentinel options precede all others and are only ordered by precedence. 47 bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 48 bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 49 if (ASent != BSent) 50 return ASent ? -1 : 1; 51 52 // Compare options by name, unless they are sentinels. 53 if (!ASent) 54 if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").str().c_str(), 55 B->getValueAsString("Name").str().c_str())) 56 return Cmp; 57 58 if (!ASent) { 59 std::vector<StringRef> APrefixes = A->getValueAsListOfStrings("Prefixes"); 60 std::vector<StringRef> BPrefixes = B->getValueAsListOfStrings("Prefixes"); 61 62 for (std::vector<StringRef>::const_iterator APre = APrefixes.begin(), 63 AEPre = APrefixes.end(), 64 BPre = BPrefixes.begin(), 65 BEPre = BPrefixes.end(); 66 APre != AEPre && BPre != BEPre; ++APre, ++BPre) { 67 if (int Cmp = StrCmpOptionName(APre->str().c_str(), BPre->str().c_str())) 68 return Cmp; 69 } 70 } 71 72 // Then by the kind precedence; 73 int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence"); 74 int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence"); 75 if (APrec == BPrec && A->getValueAsListOfStrings("Prefixes") == 76 B->getValueAsListOfStrings("Prefixes")) { 77 PrintError(A->getLoc(), Twine("Option is equivalent to")); 78 PrintError(B->getLoc(), Twine("Other defined here")); 79 PrintFatalError("Equivalent Options found."); 80 } 81 return APrec < BPrec ? -1 : 1; 82 } 83 84 } // namespace llvm 85