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