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