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