OptEmitter.cpp 2.9 KB

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