| //===- OptEmitter.cpp - Helper for emitting options.----------- -----------===// | 
 | // | 
 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
 | // See https://llvm.org/LICENSE.txt for license information. | 
 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "OptEmitter.h" | 
 | #include "llvm/ADT/Twine.h" | 
 | #include "llvm/TableGen/Error.h" | 
 | #include "llvm/TableGen/Record.h" | 
 | #include <cctype> | 
 | #include <cstring> | 
 |  | 
 | namespace llvm { | 
 |  | 
 | // Ordering on Info. The logic should match with the consumer-side function in | 
 | // llvm/Option/OptTable.h. | 
 | // FIXME: Make this take StringRefs instead of null terminated strings to | 
 | // simplify callers. | 
 | static int StrCmpOptionName(const char *A, const char *B) { | 
 |   const char *X = A, *Y = B; | 
 |   char a = tolower(*A), b = tolower(*B); | 
 |   while (a == b) { | 
 |     if (a == '\0') | 
 |       return strcmp(A, B); | 
 |  | 
 |     a = tolower(*++X); | 
 |     b = tolower(*++Y); | 
 |   } | 
 |  | 
 |   if (a == '\0') // A is a prefix of B. | 
 |     return 1; | 
 |   if (b == '\0') // B is a prefix of A. | 
 |     return -1; | 
 |  | 
 |   // Otherwise lexicographic. | 
 |   return (a < b) ? -1 : 1; | 
 | } | 
 |  | 
 | int CompareOptionRecords(Record *const *Av, Record *const *Bv) { | 
 |   const Record *A = *Av; | 
 |   const Record *B = *Bv; | 
 |  | 
 |   // Sentinel options precede all others and are only ordered by precedence. | 
 |   bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); | 
 |   bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel"); | 
 |   if (ASent != BSent) | 
 |     return ASent ? -1 : 1; | 
 |  | 
 |   // Compare options by name, unless they are sentinels. | 
 |   if (!ASent) | 
 |     if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").str().c_str(), | 
 |                                    B->getValueAsString("Name").str().c_str())) | 
 |       return Cmp; | 
 |  | 
 |   if (!ASent) { | 
 |     std::vector<StringRef> APrefixes = A->getValueAsListOfStrings("Prefixes"); | 
 |     std::vector<StringRef> BPrefixes = B->getValueAsListOfStrings("Prefixes"); | 
 |  | 
 |     for (std::vector<StringRef>::const_iterator APre = APrefixes.begin(), | 
 |                                                 AEPre = APrefixes.end(), | 
 |                                                 BPre = BPrefixes.begin(), | 
 |                                                 BEPre = BPrefixes.end(); | 
 |          APre != AEPre && BPre != BEPre; ++APre, ++BPre) { | 
 |       if (int Cmp = StrCmpOptionName(APre->str().c_str(), BPre->str().c_str())) | 
 |         return Cmp; | 
 |     } | 
 |   } | 
 |  | 
 |   // Then by the kind precedence; | 
 |   int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence"); | 
 |   int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence"); | 
 |   if (APrec == BPrec && A->getValueAsListOfStrings("Prefixes") == | 
 |                             B->getValueAsListOfStrings("Prefixes")) { | 
 |     PrintError(A->getLoc(), Twine("Option is equivalent to")); | 
 |     PrintError(B->getLoc(), Twine("Other defined here")); | 
 |     PrintFatalError("Equivalent Options found."); | 
 |   } | 
 |   return APrec < BPrec ? -1 : 1; | 
 | } | 
 |  | 
 | } // namespace llvm |