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