1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #pragma once
9 
10 #include "shared/source/compiler_interface/compiler_options/compiler_options_base.h"
11 #include "shared/source/utilities/const_stringref.h"
12 
13 #include <cstdint>
14 #include <cstring>
15 #include <memory>
16 #include <string>
17 #include <type_traits>
18 
19 namespace NEO {
20 
21 namespace KernelArgMetadata {
22 
23 enum AccessQualifier : uint8_t {
24     AccessUnknown,
25     AccessNone,
26     AccessReadOnly,
27     AccessWriteOnly,
28     AccessReadWrite,
29 };
30 
31 namespace AccessQualifierStrings {
32 constexpr ConstStringRef none = "NONE";
33 constexpr ConstStringRef readOnly = "read_only";
34 constexpr ConstStringRef writeOnly = "write_only";
35 constexpr ConstStringRef readWrite = "read_write";
36 constexpr ConstStringRef underscoreReadOnly = "__read_only";
37 constexpr ConstStringRef underscoreWriteOnly = "__write_only";
38 constexpr ConstStringRef underscoreReadWrite = "__read_write";
39 } // namespace AccessQualifierStrings
40 
41 enum AddressSpaceQualifier : uint8_t {
42     AddrUnknown,
43     AddrGlobal,
44     AddrLocal,
45     AddrPrivate,
46     AddrConstant
47 };
48 
49 namespace AddressSpaceQualifierStrings {
50 constexpr ConstStringRef addrGlobal = "__global";
51 constexpr ConstStringRef addrLocal = "__local";
52 constexpr ConstStringRef addrPrivate = "__private";
53 constexpr ConstStringRef addrConstant = "__constant";
54 constexpr ConstStringRef addrNotSpecified = "not_specified";
55 } // namespace AddressSpaceQualifierStrings
56 
parseAccessQualifier(ConstStringRef str)57 constexpr AccessQualifier parseAccessQualifier(ConstStringRef str) {
58     using namespace AccessQualifierStrings;
59     if (str.empty() || (none == str)) {
60         return AccessNone;
61     }
62 
63     if (str.length() < 3) {
64         return AccessUnknown;
65     }
66 
67     ConstStringRef strNoUnderscore = ('_' == str[0]) ? ConstStringRef(str.data() + 2, str.length() - 2) : str;
68     static_assert(writeOnly[0] != readOnly[0], "");
69     static_assert(writeOnly[0] != readWrite[0], "");
70     if (strNoUnderscore[0] == writeOnly[0]) {
71         return (writeOnly == strNoUnderscore) ? AccessWriteOnly : AccessUnknown;
72     }
73 
74     if (readOnly == strNoUnderscore) {
75         return AccessReadOnly;
76     }
77 
78     return (readWrite == strNoUnderscore) ? AccessReadWrite : AccessUnknown;
79 }
80 
parseAddressSpace(ConstStringRef str)81 constexpr AddressSpaceQualifier parseAddressSpace(ConstStringRef str) {
82     using namespace AddressSpaceQualifierStrings;
83     if (str.empty()) {
84         return AddrGlobal;
85     }
86 
87     if (str.length() < 3) {
88         return AddrUnknown;
89     }
90 
91     switch (str[2]) {
92     default:
93         return AddrUnknown;
94     case addrNotSpecified[2]:
95         return (str == addrNotSpecified) ? AddrPrivate : AddrUnknown;
96     case addrGlobal[2]:
97         return (str == addrGlobal) ? AddrGlobal : AddrUnknown;
98     case addrLocal[2]:
99         return (str == addrLocal) ? AddrLocal : AddrUnknown;
100     case addrPrivate[2]:
101         return (str == addrPrivate) ? AddrPrivate : AddrUnknown;
102     case addrConstant[2]:
103         return (str == addrConstant) ? AddrConstant : AddrUnknown;
104     }
105 }
106 
107 union TypeQualifiers {
108     uint8_t packed = 0U;
109     struct {
110         bool constQual : 1;
111         bool volatileQual : 1;
112         bool restrictQual : 1;
113         bool pipeQual : 1;
114         bool unknownQual : 1;
115     };
empty()116     bool empty() const {
117         return 0U == packed;
118     }
119 };
120 
121 namespace TypeQualifierStrings {
122 constexpr ConstStringRef qualConst = "const";
123 constexpr ConstStringRef qualVolatile = "volatile";
124 constexpr ConstStringRef qualRestrict = "restrict";
125 constexpr ConstStringRef qualPipe = "pipe";
126 } // namespace TypeQualifierStrings
127 
parseTypeQualifiers(ConstStringRef str)128 inline TypeQualifiers parseTypeQualifiers(ConstStringRef str) {
129     using namespace TypeQualifierStrings;
130     TypeQualifiers ret = {};
131     auto tokenized = CompilerOptions::tokenize(str);
132     for (const auto &tok : tokenized) {
133         bool knownQualifier = true;
134         switch (tok[0]) {
135         default:
136             knownQualifier = false;
137             break;
138         case qualConst[0]:
139             knownQualifier = (qualConst == tok);
140             ret.constQual |= knownQualifier;
141             break;
142         case qualVolatile[0]:
143             knownQualifier = (qualVolatile == tok);
144             ret.volatileQual |= knownQualifier;
145             break;
146         case qualRestrict[0]:
147             knownQualifier = (qualRestrict == tok);
148             ret.restrictQual |= knownQualifier;
149             break;
150         case qualPipe[0]:
151             knownQualifier = (qualPipe == tok);
152             ret.pipeQual |= knownQualifier;
153             break;
154         }
155         ret.unknownQual |= !knownQualifier;
156     }
157     return ret;
158 }
159 
160 } // namespace KernelArgMetadata
161 
parseLimitedString(const char * str,size_t maxSize)162 inline std::string parseLimitedString(const char *str, size_t maxSize) {
163     std::string ret{str, str + maxSize};
164     size_t minSize = strlen(ret.c_str());
165     ret.assign(str, minSize);
166     return ret;
167 }
168 
169 struct ArgTypeTraits {
ArgTypeTraitsArgTypeTraits170     ArgTypeTraits() {
171         accessQualifier = KernelArgMetadata::AccessUnknown;
172         addressQualifier = KernelArgMetadata::AddrGlobal;
173     }
174     uint16_t argByValSize = 0U;
175     struct {
176         std::underlying_type_t<KernelArgMetadata::AccessQualifier> accessQualifier : 4;
177         std::underlying_type_t<KernelArgMetadata::AddressSpaceQualifier> addressQualifier : 4;
178     };
179     KernelArgMetadata::TypeQualifiers typeQualifiers;
180 
getAccessQualifierArgTypeTraits181     KernelArgMetadata::AccessQualifier getAccessQualifier() const {
182         return static_cast<KernelArgMetadata::AccessQualifier>(accessQualifier);
183     }
184 
getAddressQualifierArgTypeTraits185     KernelArgMetadata::AddressSpaceQualifier getAddressQualifier() const {
186         return static_cast<KernelArgMetadata::AddressSpaceQualifier>(addressQualifier);
187     }
188 };
189 
190 namespace {
191 static constexpr auto ArgTypeMetadataSize = sizeof(ArgTypeTraits);
192 static_assert(ArgTypeMetadataSize <= 4, "Keep it small");
193 } // namespace
194 
195 struct ArgTypeMetadataExtended {
196     std::string argName;
197     std::string type;
198     std::string accessQualifier;
199     std::string addressQualifier;
200     std::string typeQualifiers;
201 };
202 
203 } // namespace NEO
204