xref: /llvm-project/llvm/lib/Support/RISCVISAUtils.cpp (revision 0d93b01c3b1e2e543acec3f36db639b8b7b0b20d)
1733a8778SCraig Topper //===-- RISCVISAUtils.cpp - RISC-V ISA Utilities --------------------------===//
2733a8778SCraig Topper //
3733a8778SCraig Topper // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4733a8778SCraig Topper // See https://llvm.org/LICENSE.txt for license information.
5733a8778SCraig Topper // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6733a8778SCraig Topper //
7733a8778SCraig Topper //===----------------------------------------------------------------------===//
8733a8778SCraig Topper //
9733a8778SCraig Topper // Utilities shared by TableGen and RISCVISAInfo.
10733a8778SCraig Topper //
11733a8778SCraig Topper //===----------------------------------------------------------------------===//
12733a8778SCraig Topper 
13733a8778SCraig Topper #include "llvm/Support/RISCVISAUtils.h"
147a6847e0SCraig Topper #include "llvm/ADT/StringExtras.h"
15733a8778SCraig Topper #include <cassert>
16733a8778SCraig Topper 
17733a8778SCraig Topper using namespace llvm;
18733a8778SCraig Topper 
19733a8778SCraig Topper // We rank extensions in the following order:
20733a8778SCraig Topper // -Single letter extensions in canonical order.
21733a8778SCraig Topper // -Unknown single letter extensions in alphabetical order.
22733a8778SCraig Topper // -Multi-letter extensions starting with 'z' sorted by canonical order of
23733a8778SCraig Topper //  the second letter then sorted alphabetically.
24733a8778SCraig Topper // -Multi-letter extensions starting with 's' in alphabetical order.
25733a8778SCraig Topper // -(TODO) Multi-letter extensions starting with 'zxm' in alphabetical order.
26733a8778SCraig Topper // -X extensions in alphabetical order.
27*0d93b01cSCraig Topper // -Unknown multi-letter extensions in alphabetical order.
28733a8778SCraig Topper // These flags are used to indicate the category. The first 6 bits store the
29733a8778SCraig Topper // single letter extension rank for single letter and multi-letter extensions
30733a8778SCraig Topper // starting with 'z'.
31733a8778SCraig Topper enum RankFlags {
32733a8778SCraig Topper   RF_Z_EXTENSION = 1 << 6,
33*0d93b01cSCraig Topper   RF_S_EXTENSION = 2 << 6,
34*0d93b01cSCraig Topper   RF_X_EXTENSION = 3 << 6,
35*0d93b01cSCraig Topper   RF_UNKNOWN_MULTILETTER_EXTENSION = 4 << 6,
36733a8778SCraig Topper };
37733a8778SCraig Topper 
38733a8778SCraig Topper // Get the rank for single-letter extension, lower value meaning higher
39733a8778SCraig Topper // priority.
singleLetterExtensionRank(char Ext)40733a8778SCraig Topper static unsigned singleLetterExtensionRank(char Ext) {
417a6847e0SCraig Topper   assert(isLower(Ext));
42733a8778SCraig Topper   switch (Ext) {
43733a8778SCraig Topper   case 'i':
44733a8778SCraig Topper     return 0;
45733a8778SCraig Topper   case 'e':
46733a8778SCraig Topper     return 1;
47733a8778SCraig Topper   }
48733a8778SCraig Topper 
49733a8778SCraig Topper   size_t Pos = RISCVISAUtils::AllStdExts.find(Ext);
50733a8778SCraig Topper   if (Pos != StringRef::npos)
51733a8778SCraig Topper     return Pos + 2; // Skip 'e' and 'i' from above.
52733a8778SCraig Topper 
53733a8778SCraig Topper   // If we got an unknown extension letter, then give it an alphabetical
54733a8778SCraig Topper   // order, but after all known standard extensions.
55733a8778SCraig Topper   return 2 + RISCVISAUtils::AllStdExts.size() + (Ext - 'a');
56733a8778SCraig Topper }
57733a8778SCraig Topper 
58733a8778SCraig Topper // Get the rank for multi-letter extension, lower value meaning higher
59733a8778SCraig Topper // priority/order in canonical order.
getExtensionRank(const std::string & ExtName)60733a8778SCraig Topper static unsigned getExtensionRank(const std::string &ExtName) {
61733a8778SCraig Topper   assert(ExtName.size() >= 1);
62733a8778SCraig Topper   switch (ExtName[0]) {
63733a8778SCraig Topper   case 's':
64733a8778SCraig Topper     return RF_S_EXTENSION;
65733a8778SCraig Topper   case 'z':
66733a8778SCraig Topper     assert(ExtName.size() >= 2);
67733a8778SCraig Topper     // `z` extension must be sorted by canonical order of second letter.
68733a8778SCraig Topper     // e.g. zmx has higher rank than zax.
69733a8778SCraig Topper     return RF_Z_EXTENSION | singleLetterExtensionRank(ExtName[1]);
70733a8778SCraig Topper   case 'x':
71733a8778SCraig Topper     return RF_X_EXTENSION;
72733a8778SCraig Topper   default:
73*0d93b01cSCraig Topper     if (ExtName.size() == 1)
74733a8778SCraig Topper       return singleLetterExtensionRank(ExtName[0]);
75*0d93b01cSCraig Topper     return RF_UNKNOWN_MULTILETTER_EXTENSION;
76733a8778SCraig Topper   }
77733a8778SCraig Topper }
78733a8778SCraig Topper 
79733a8778SCraig Topper // Compare function for extension.
80733a8778SCraig Topper // Only compare the extension name, ignore version comparison.
compareExtension(const std::string & LHS,const std::string & RHS)81733a8778SCraig Topper bool llvm::RISCVISAUtils::compareExtension(const std::string &LHS,
82733a8778SCraig Topper                                            const std::string &RHS) {
83733a8778SCraig Topper   unsigned LHSRank = getExtensionRank(LHS);
84733a8778SCraig Topper   unsigned RHSRank = getExtensionRank(RHS);
85733a8778SCraig Topper 
86733a8778SCraig Topper   // If the ranks differ, pick the lower rank.
87733a8778SCraig Topper   if (LHSRank != RHSRank)
88733a8778SCraig Topper     return LHSRank < RHSRank;
89733a8778SCraig Topper 
90733a8778SCraig Topper   // If the rank is same, it must be sorted by lexicographic order.
91733a8778SCraig Topper   return LHS < RHS;
92733a8778SCraig Topper }
93