1 //===-- AMDGPULibFunc.cpp -------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains utility functions to work with Itanium mangled names 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AMDGPULibFunc.h" 15 #include <llvm/ADT/SmallString.h> 16 #include <llvm/ADT/SmallVector.h> 17 #include <llvm/ADT/StringSwitch.h> 18 #include "llvm/IR/Attributes.h" 19 #include "llvm/IR/DerivedTypes.h" 20 #include "llvm/IR/Function.h" 21 #include "llvm/IR/Module.h" 22 #include "llvm/IR/ValueSymbolTable.h" 23 #include <llvm/Support/raw_ostream.h> 24 #include <string> 25 26 using namespace llvm; 27 28 namespace { 29 30 enum EManglingParam { 31 E_NONE, 32 EX_EVENT, 33 EX_FLOAT4, 34 EX_INTV4, 35 EX_RESERVEDID, 36 EX_SAMPLER, 37 EX_SIZET, 38 EX_UINT, 39 EX_UINTV4, 40 E_ANY, 41 E_CONSTPTR_ANY, 42 E_CONSTPTR_SWAPGL, 43 E_COPY, 44 E_IMAGECOORDS, 45 E_POINTEE, 46 E_SETBASE_I32, 47 E_SETBASE_U32, 48 E_MAKEBASE_UNS, 49 E_V16_OF_POINTEE, 50 E_V2_OF_POINTEE, 51 E_V3_OF_POINTEE, 52 E_V4_OF_POINTEE, 53 E_V8_OF_POINTEE, 54 E_VLTLPTR_ANY, 55 }; 56 57 struct ManglingRule { 58 StringRef const Name; 59 unsigned char Lead[2]; 60 unsigned char Param[5]; 61 62 int maxLeadIndex() const { return (std::max)(Lead[0], Lead[1]); } 63 int getNumLeads() const { return (Lead[0] ? 1 : 0) + (Lead[1] ? 1 : 0); } 64 65 unsigned getNumArgs() const; 66 }; 67 68 unsigned ManglingRule::getNumArgs() const { 69 unsigned I=0; 70 while (I < (sizeof Param/sizeof Param[0]) && Param[I]) ++I; 71 return I; 72 } 73 74 // This table describes function formal argument type rules. The order of rules 75 // corresponds to the EFuncId enum at AMDGPULibFunc.h 76 // 77 // "<func name>", { <leads> }, { <param rules> } 78 // where: 79 // <leads> - list of integers that are one-based indexes of formal argument 80 // used to mangle a function name. Other argument types are derived from types 81 // of these 'leads'. The order of integers in this list correspond to the 82 // order in which these arguments are mangled in the EDG mangling scheme. The 83 // same order should be preserved for arguments in the AMDGPULibFunc structure 84 // when it is used for mangling. For example: 85 // { "vstorea_half", {3,1}, {E_ANY,EX_SIZET,E_ANY}}, 86 // will be mangled in EDG scheme as vstorea_half_<3dparam>_<1stparam> 87 // When mangling from code use: 88 // AMDGPULibFunc insc; 89 // insc.param[0] = ... // describe 3rd parameter 90 // insc.param[1] = ... // describe 1rd parameter 91 // 92 // <param rules> - list of rules used to derive all of the function formal 93 // argument types. EX_ prefixed are simple types, other derived from the 94 // latest 'lead' argument type in the order of encoding from first to last. 95 // E_ANY - use prev lead type, E_CONSTPTR_ANY - make const pointer out of 96 // prev lead type, etc. see ParamIterator::getNextParam() for details. 97 98 static const ManglingRule manglingRules[] = { 99 { StringRef(), {0}, {0} }, 100 { "abs" , {1}, {E_ANY}}, 101 { "abs_diff" , {1}, {E_ANY,E_COPY}}, 102 { "acos" , {1}, {E_ANY}}, 103 { "acosh" , {1}, {E_ANY}}, 104 { "acospi" , {1}, {E_ANY}}, 105 { "add_sat" , {1}, {E_ANY,E_COPY}}, 106 { "all" , {1}, {E_ANY}}, 107 { "any" , {1}, {E_ANY}}, 108 { "asin" , {1}, {E_ANY}}, 109 { "asinh" , {1}, {E_ANY}}, 110 { "asinpi" , {1}, {E_ANY}}, 111 { "async_work_group_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_EVENT}}, 112 { "async_work_group_strided_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_SIZET,EX_EVENT}}, 113 { "atan" , {1}, {E_ANY}}, 114 { "atan2" , {1}, {E_ANY,E_COPY}}, 115 { "atan2pi" , {1}, {E_ANY,E_COPY}}, 116 { "atanh" , {1}, {E_ANY}}, 117 { "atanpi" , {1}, {E_ANY}}, 118 { "atomic_add" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 119 { "atomic_and" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 120 { "atomic_cmpxchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE,E_POINTEE}}, 121 { "atomic_dec" , {1}, {E_VLTLPTR_ANY}}, 122 { "atomic_inc" , {1}, {E_VLTLPTR_ANY}}, 123 { "atomic_max" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 124 { "atomic_min" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 125 { "atomic_or" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 126 { "atomic_sub" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 127 { "atomic_xchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 128 { "atomic_xor" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 129 { "bitselect" , {1}, {E_ANY,E_COPY,E_COPY}}, 130 { "cbrt" , {1}, {E_ANY}}, 131 { "ceil" , {1}, {E_ANY}}, 132 { "clamp" , {1}, {E_ANY,E_COPY,E_COPY}}, 133 { "clz" , {1}, {E_ANY}}, 134 { "commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 135 { "commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 136 { "copysign" , {1}, {E_ANY,E_COPY}}, 137 { "cos" , {1}, {E_ANY}}, 138 { "cosh" , {1}, {E_ANY}}, 139 { "cospi" , {1}, {E_ANY}}, 140 { "cross" , {1}, {E_ANY,E_COPY}}, 141 { "ctz" , {1}, {E_ANY}}, 142 { "degrees" , {1}, {E_ANY}}, 143 { "distance" , {1}, {E_ANY,E_COPY}}, 144 { "divide" , {1}, {E_ANY,E_COPY}}, 145 { "dot" , {1}, {E_ANY,E_COPY}}, 146 { "erf" , {1}, {E_ANY}}, 147 { "erfc" , {1}, {E_ANY}}, 148 { "exp" , {1}, {E_ANY}}, 149 { "exp10" , {1}, {E_ANY}}, 150 { "exp2" , {1}, {E_ANY}}, 151 { "expm1" , {1}, {E_ANY}}, 152 { "fabs" , {1}, {E_ANY}}, 153 { "fast_distance" , {1}, {E_ANY,E_COPY}}, 154 { "fast_length" , {1}, {E_ANY}}, 155 { "fast_normalize" , {1}, {E_ANY}}, 156 { "fdim" , {1}, {E_ANY,E_COPY}}, 157 { "floor" , {1}, {E_ANY}}, 158 { "fma" , {1}, {E_ANY,E_COPY,E_COPY}}, 159 { "fmax" , {1}, {E_ANY,E_COPY}}, 160 { "fmin" , {1}, {E_ANY,E_COPY}}, 161 { "fmod" , {1}, {E_ANY,E_COPY}}, 162 { "fract" , {2}, {E_POINTEE,E_ANY}}, 163 { "frexp" , {1,2}, {E_ANY,E_ANY}}, 164 { "get_image_array_size" , {1}, {E_ANY}}, 165 { "get_image_channel_data_type" , {1}, {E_ANY}}, 166 { "get_image_channel_order" , {1}, {E_ANY}}, 167 { "get_image_dim" , {1}, {E_ANY}}, 168 { "get_image_height" , {1}, {E_ANY}}, 169 { "get_image_width" , {1}, {E_ANY}}, 170 { "get_pipe_max_packets" , {1}, {E_ANY}}, 171 { "get_pipe_num_packets" , {1}, {E_ANY}}, 172 { "hadd" , {1}, {E_ANY,E_COPY}}, 173 { "hypot" , {1}, {E_ANY,E_COPY}}, 174 { "ilogb" , {1}, {E_ANY}}, 175 { "isequal" , {1}, {E_ANY,E_COPY}}, 176 { "isfinite" , {1}, {E_ANY}}, 177 { "isgreater" , {1}, {E_ANY,E_COPY}}, 178 { "isgreaterequal" , {1}, {E_ANY,E_COPY}}, 179 { "isinf" , {1}, {E_ANY}}, 180 { "isless" , {1}, {E_ANY,E_COPY}}, 181 { "islessequal" , {1}, {E_ANY,E_COPY}}, 182 { "islessgreater" , {1}, {E_ANY,E_COPY}}, 183 { "isnan" , {1}, {E_ANY}}, 184 { "isnormal" , {1}, {E_ANY}}, 185 { "isnotequal" , {1}, {E_ANY,E_COPY}}, 186 { "isordered" , {1}, {E_ANY,E_COPY}}, 187 { "isunordered" , {1}, {E_ANY,E_COPY}}, 188 { "ldexp" , {1}, {E_ANY,E_SETBASE_I32}}, 189 { "length" , {1}, {E_ANY}}, 190 { "lgamma" , {1}, {E_ANY}}, 191 { "lgamma_r" , {1,2}, {E_ANY,E_ANY}}, 192 { "log" , {1}, {E_ANY}}, 193 { "log10" , {1}, {E_ANY}}, 194 { "log1p" , {1}, {E_ANY}}, 195 { "log2" , {1}, {E_ANY}}, 196 { "logb" , {1}, {E_ANY}}, 197 { "mad" , {1}, {E_ANY,E_COPY,E_COPY}}, 198 { "mad24" , {1}, {E_ANY,E_COPY,E_COPY}}, 199 { "mad_hi" , {1}, {E_ANY,E_COPY,E_COPY}}, 200 { "mad_sat" , {1}, {E_ANY,E_COPY,E_COPY}}, 201 { "max" , {1}, {E_ANY,E_COPY}}, 202 { "maxmag" , {1}, {E_ANY,E_COPY}}, 203 { "min" , {1}, {E_ANY,E_COPY}}, 204 { "minmag" , {1}, {E_ANY,E_COPY}}, 205 { "mix" , {1}, {E_ANY,E_COPY,E_COPY}}, 206 { "modf" , {2}, {E_POINTEE,E_ANY}}, 207 { "mul24" , {1}, {E_ANY,E_COPY}}, 208 { "mul_hi" , {1}, {E_ANY,E_COPY}}, 209 { "nan" , {1}, {E_ANY}}, 210 { "nextafter" , {1}, {E_ANY,E_COPY}}, 211 { "normalize" , {1}, {E_ANY}}, 212 { "popcount" , {1}, {E_ANY}}, 213 { "pow" , {1}, {E_ANY,E_COPY}}, 214 { "pown" , {1}, {E_ANY,E_SETBASE_I32}}, 215 { "powr" , {1}, {E_ANY,E_COPY}}, 216 { "prefetch" , {1}, {E_CONSTPTR_ANY,EX_SIZET}}, 217 { "radians" , {1}, {E_ANY}}, 218 { "read_pipe" , {4}, {E_COPY,EX_RESERVEDID,EX_UINT,E_ANY}}, 219 { "recip" , {1}, {E_ANY}}, 220 { "remainder" , {1}, {E_ANY,E_COPY}}, 221 { "remquo" , {1,3}, {E_ANY,E_COPY,E_ANY}}, 222 { "reserve_read_pipe" , {1}, {E_ANY,EX_UINT}}, 223 { "reserve_write_pipe" , {1}, {E_ANY,EX_UINT}}, 224 { "rhadd" , {1}, {E_ANY,E_COPY}}, 225 { "rint" , {1}, {E_ANY}}, 226 { "rootn" , {1}, {E_ANY,E_SETBASE_I32}}, 227 { "rotate" , {1}, {E_ANY,E_COPY}}, 228 { "round" , {1}, {E_ANY}}, 229 { "rsqrt" , {1}, {E_ANY}}, 230 { "select" , {1,3}, {E_ANY,E_COPY,E_ANY}}, 231 { "shuffle" , {1,2}, {E_ANY,E_ANY}}, 232 { "shuffle2" , {1,3}, {E_ANY,E_COPY,E_ANY}}, 233 { "sign" , {1}, {E_ANY}}, 234 { "signbit" , {1}, {E_ANY}}, 235 { "sin" , {1}, {E_ANY}}, 236 { "sincos" , {2}, {E_POINTEE,E_ANY}}, 237 { "sinh" , {1}, {E_ANY}}, 238 { "sinpi" , {1}, {E_ANY}}, 239 { "smoothstep" , {1}, {E_ANY,E_COPY,E_COPY}}, 240 { "sqrt" , {1}, {E_ANY}}, 241 { "step" , {1}, {E_ANY,E_COPY}}, 242 { "sub_group_broadcast" , {1}, {E_ANY,EX_UINT}}, 243 { "sub_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 244 { "sub_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 245 { "sub_group_reduce_add" , {1}, {E_ANY}}, 246 { "sub_group_reduce_max" , {1}, {E_ANY}}, 247 { "sub_group_reduce_min" , {1}, {E_ANY}}, 248 { "sub_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}}, 249 { "sub_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}}, 250 { "sub_group_scan_exclusive_add" , {1}, {E_ANY}}, 251 { "sub_group_scan_exclusive_max" , {1}, {E_ANY}}, 252 { "sub_group_scan_exclusive_min" , {1}, {E_ANY}}, 253 { "sub_group_scan_inclusive_add" , {1}, {E_ANY}}, 254 { "sub_group_scan_inclusive_max" , {1}, {E_ANY}}, 255 { "sub_group_scan_inclusive_min" , {1}, {E_ANY}}, 256 { "sub_sat" , {1}, {E_ANY,E_COPY}}, 257 { "tan" , {1}, {E_ANY}}, 258 { "tanh" , {1}, {E_ANY}}, 259 { "tanpi" , {1}, {E_ANY}}, 260 { "tgamma" , {1}, {E_ANY}}, 261 { "trunc" , {1}, {E_ANY}}, 262 { "upsample" , {1}, {E_ANY,E_MAKEBASE_UNS}}, 263 { "vec_step" , {1}, {E_ANY}}, 264 { "vstore" , {3}, {E_POINTEE,EX_SIZET,E_ANY}}, 265 { "vstore16" , {3}, {E_V16_OF_POINTEE,EX_SIZET,E_ANY}}, 266 { "vstore2" , {3}, {E_V2_OF_POINTEE,EX_SIZET,E_ANY}}, 267 { "vstore3" , {3}, {E_V3_OF_POINTEE,EX_SIZET,E_ANY}}, 268 { "vstore4" , {3}, {E_V4_OF_POINTEE,EX_SIZET,E_ANY}}, 269 { "vstore8" , {3}, {E_V8_OF_POINTEE,EX_SIZET,E_ANY}}, 270 { "work_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 271 { "work_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 272 { "work_group_reduce_add" , {1}, {E_ANY}}, 273 { "work_group_reduce_max" , {1}, {E_ANY}}, 274 { "work_group_reduce_min" , {1}, {E_ANY}}, 275 { "work_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}}, 276 { "work_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}}, 277 { "work_group_scan_exclusive_add" , {1}, {E_ANY}}, 278 { "work_group_scan_exclusive_max" , {1}, {E_ANY}}, 279 { "work_group_scan_exclusive_min" , {1}, {E_ANY}}, 280 { "work_group_scan_inclusive_add" , {1}, {E_ANY}}, 281 { "work_group_scan_inclusive_max" , {1}, {E_ANY}}, 282 { "work_group_scan_inclusive_min" , {1}, {E_ANY}}, 283 { "write_imagef" , {1}, {E_ANY,E_IMAGECOORDS,EX_FLOAT4}}, 284 { "write_imagei" , {1}, {E_ANY,E_IMAGECOORDS,EX_INTV4}}, 285 { "write_imageui" , {1}, {E_ANY,E_IMAGECOORDS,EX_UINTV4}}, 286 { "write_pipe" , {4}, {E_COPY,EX_RESERVEDID,EX_UINT,E_ANY}}, 287 { "ncos" , {1}, {E_ANY} }, 288 { "nexp2" , {1}, {E_ANY} }, 289 { "nfma" , {1}, {E_ANY, E_COPY, E_COPY} }, 290 { "nlog2" , {1}, {E_ANY} }, 291 { "nrcp" , {1}, {E_ANY} }, 292 { "nrsqrt" , {1}, {E_ANY} }, 293 { "nsin" , {1}, {E_ANY} }, 294 { "nsqrt" , {1}, {E_ANY} }, 295 { "ftz" , {1}, {E_ANY} }, 296 { "fldexp" , {1}, {E_ANY, EX_UINT} }, 297 { "class" , {1}, {E_ANY, EX_UINT} }, 298 { "rcbrt" , {1}, {E_ANY} }, 299 }; 300 301 static const struct ManglingRulesMap : public StringMap<int> { 302 ManglingRulesMap() 303 : StringMap<int>(sizeof(manglingRules)/sizeof(manglingRules[0])) { 304 int Id = 0; 305 for (auto Rule : manglingRules) 306 insert({ Rule.Name, Id++ }); 307 } 308 } manglingRulesMap; 309 310 static AMDGPULibFunc::Param getRetType(AMDGPULibFunc::EFuncId id, 311 const AMDGPULibFunc::Param (&Leads)[2]) { 312 AMDGPULibFunc::Param Res = Leads[0]; 313 // TBD - This switch may require to be extended for other intriniscs 314 switch (id) { 315 case AMDGPULibFunc::EI_SINCOS: 316 Res.PtrKind = AMDGPULibFunc::BYVALUE; 317 break; 318 default: 319 break; 320 } 321 return Res; 322 } 323 324 class ParamIterator { 325 const AMDGPULibFunc::Param (&Leads)[2]; 326 const ManglingRule& Rule; 327 int Index; 328 public: 329 ParamIterator(const AMDGPULibFunc::Param (&leads)[2], 330 const ManglingRule& rule) 331 : Leads(leads), Rule(rule), Index(0) {} 332 333 AMDGPULibFunc::Param getNextParam(); 334 }; 335 336 AMDGPULibFunc::Param ParamIterator::getNextParam() { 337 AMDGPULibFunc::Param P; 338 if (Index >= int(sizeof Rule.Param/sizeof Rule.Param[0])) return P; 339 340 const char R = Rule.Param[Index]; 341 switch (R) { 342 case E_NONE: break; 343 case EX_UINT: 344 P.ArgType = AMDGPULibFunc::U32; break; 345 case EX_INTV4: 346 P.ArgType = AMDGPULibFunc::I32; P.VectorSize = 4; break; 347 case EX_UINTV4: 348 P.ArgType = AMDGPULibFunc::U32; P.VectorSize = 4; break; 349 case EX_FLOAT4: 350 P.ArgType = AMDGPULibFunc::F32; P.VectorSize = 4; break; 351 case EX_SIZET: 352 P.ArgType = AMDGPULibFunc::U64; break; 353 case EX_EVENT: 354 P.ArgType = AMDGPULibFunc::EVENT; break; 355 case EX_SAMPLER: 356 P.ArgType = AMDGPULibFunc::SAMPLER; break; 357 case EX_RESERVEDID: break; // TBD 358 default: 359 if (Index == (Rule.Lead[1] - 1)) P = Leads[1]; 360 else P = Leads[0]; 361 362 switch (R) { 363 case E_ANY: 364 case E_COPY: break; 365 366 case E_POINTEE: 367 P.PtrKind = AMDGPULibFunc::BYVALUE; break; 368 case E_V2_OF_POINTEE: 369 P.VectorSize = 2; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 370 case E_V3_OF_POINTEE: 371 P.VectorSize = 3; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 372 case E_V4_OF_POINTEE: 373 P.VectorSize = 4; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 374 case E_V8_OF_POINTEE: 375 P.VectorSize = 8; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 376 case E_V16_OF_POINTEE: 377 P.VectorSize = 16; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 378 case E_CONSTPTR_ANY: 379 P.PtrKind |= AMDGPULibFunc::CONST; break; 380 case E_VLTLPTR_ANY: 381 P.PtrKind |= AMDGPULibFunc::VOLATILE; break; 382 case E_SETBASE_I32: 383 P.ArgType = AMDGPULibFunc::I32; break; 384 case E_SETBASE_U32: 385 P.ArgType = AMDGPULibFunc::U32; break; 386 387 case E_MAKEBASE_UNS: 388 P.ArgType &= ~AMDGPULibFunc::BASE_TYPE_MASK; 389 P.ArgType |= AMDGPULibFunc::UINT; 390 break; 391 392 case E_IMAGECOORDS: 393 switch (P.ArgType) { 394 case AMDGPULibFunc::IMG1DA: P.VectorSize = 2; break; 395 case AMDGPULibFunc::IMG1DB: P.VectorSize = 1; break; 396 case AMDGPULibFunc::IMG2DA: P.VectorSize = 4; break; 397 case AMDGPULibFunc::IMG1D: P.VectorSize = 1; break; 398 case AMDGPULibFunc::IMG2D: P.VectorSize = 2; break; 399 case AMDGPULibFunc::IMG3D: P.VectorSize = 4; break; 400 } 401 P.PtrKind = AMDGPULibFunc::BYVALUE; 402 P.ArgType = AMDGPULibFunc::I32; 403 break; 404 405 case E_CONSTPTR_SWAPGL: 406 switch (P.PtrKind & AMDGPULibFunc::ADDR_SPACE) { 407 case AMDGPULibFunc::GLOBAL: P.PtrKind = AMDGPULibFunc::LOCAL; break; 408 case AMDGPULibFunc::LOCAL: P.PtrKind = AMDGPULibFunc::GLOBAL; break; 409 } 410 P.PtrKind |= AMDGPULibFunc::CONST; 411 break; 412 413 default: llvm_unreachable("Unhandeled param rule"); 414 } 415 } 416 ++Index; 417 return P; 418 } 419 420 inline static void drop_front(StringRef& str, size_t n = 1) { 421 str = str.drop_front(n); 422 } 423 424 static bool eatTerm(StringRef& mangledName, const char c) { 425 if (mangledName.front() == c) { 426 drop_front(mangledName); 427 return true; 428 } 429 return false; 430 } 431 432 template <size_t N> 433 static bool eatTerm(StringRef& mangledName, const char (&str)[N]) { 434 if (mangledName.startswith(StringRef(str, N-1))) { 435 drop_front(mangledName, N-1); 436 return true; 437 } 438 return false; 439 } 440 441 static inline bool isDigit(char c) { return c >= '0' && c <= '9'; } 442 443 static int eatNumber(StringRef& s) { 444 size_t const savedSize = s.size(); 445 int n = 0; 446 while (!s.empty() && isDigit(s.front())) { 447 n = n*10 + s.front() - '0'; 448 drop_front(s); 449 } 450 return s.size() < savedSize ? n : -1; 451 } 452 453 static StringRef eatLengthPrefixedName(StringRef& mangledName) { 454 int const Len = eatNumber(mangledName); 455 if (Len <= 0 || static_cast<size_t>(Len) > mangledName.size()) 456 return StringRef(); 457 StringRef Res = mangledName.substr(0, Len); 458 drop_front(mangledName, Len); 459 return Res; 460 } 461 462 } // end anonymous namespace 463 464 AMDGPULibFunc::AMDGPULibFunc() { 465 reset(); 466 } 467 468 AMDGPULibFunc::AMDGPULibFunc(EFuncId id, const AMDGPULibFunc& copyFrom) 469 : FuncId(id) { 470 FKind = copyFrom.FKind; 471 Leads[0] = copyFrom.Leads[0]; 472 Leads[1] = copyFrom.Leads[1]; 473 } 474 475 void AMDGPULibFunc::reset() { 476 FuncId = EI_NONE; 477 FKind = NOPFX; 478 Leads[0].reset(); 479 Leads[1].reset(); 480 Name.clear(); 481 } 482 483 /////////////////////////////////////////////////////////////////////////////// 484 // Demangling 485 486 static int parseVecSize(StringRef& mangledName) { 487 size_t const Len = eatNumber(mangledName); 488 switch (Len) { 489 case 2: case 3: case 4: case 8: case 16: 490 return Len; 491 default: 492 break; 493 } 494 return 1; 495 } 496 497 static AMDGPULibFunc::ENamePrefix parseNamePrefix(StringRef& mangledName) { 498 std::pair<StringRef, StringRef> const P = mangledName.split('_'); 499 AMDGPULibFunc::ENamePrefix Pfx = 500 StringSwitch<AMDGPULibFunc::ENamePrefix>(P.first) 501 .Case("native", AMDGPULibFunc::NATIVE) 502 .Case("half" , AMDGPULibFunc::HALF) 503 .Default(AMDGPULibFunc::NOPFX); 504 505 if (Pfx != AMDGPULibFunc::NOPFX) 506 mangledName = P.second; 507 508 return Pfx; 509 } 510 511 bool AMDGPULibFunc::parseName(const StringRef& fullName) { 512 FuncId = static_cast<EFuncId>(manglingRulesMap.lookup(fullName)); 513 return FuncId != EI_NONE; 514 } 515 516 /////////////////////////////////////////////////////////////////////////////// 517 // Itanium Demangling 518 519 namespace { 520 struct ItaniumParamParser { 521 AMDGPULibFunc::Param Prev; 522 bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res); 523 }; 524 } // namespace 525 526 bool ItaniumParamParser::parseItaniumParam(StringRef& param, 527 AMDGPULibFunc::Param &res) { 528 res.reset(); 529 if (param.empty()) return false; 530 531 // parse pointer prefix 532 if (eatTerm(param, 'P')) { 533 if (eatTerm(param, 'K')) res.PtrKind |= AMDGPULibFunc::CONST; 534 if (eatTerm(param, 'V')) res.PtrKind |= AMDGPULibFunc::VOLATILE; 535 if (!eatTerm(param, "U3AS")) { 536 res.PtrKind |= AMDGPULibFunc::PRIVATE; 537 } else { 538 switch(param.front()) { 539 case '1': res.PtrKind |= AMDGPULibFunc::GLOBAL; break; 540 case '2': res.PtrKind |= AMDGPULibFunc::READONLY;break; 541 case '3': res.PtrKind |= AMDGPULibFunc::LOCAL; break; 542 case '4': res.PtrKind |= AMDGPULibFunc::GENERIC; break; 543 case '5': res.PtrKind |= AMDGPULibFunc::OTHER; break; 544 default: return false; 545 } 546 drop_front(param, 1); 547 } 548 } else { 549 res.PtrKind = AMDGPULibFunc::BYVALUE; 550 } 551 552 // parse vector size 553 if (eatTerm(param,"Dv")) { 554 res.VectorSize = parseVecSize(param); 555 if (res.VectorSize==1 || !eatTerm(param, '_')) return false; 556 } 557 558 // parse type 559 char const TC = param.front(); 560 if (::isDigit(TC)) { 561 res.ArgType = StringSwitch<AMDGPULibFunc::EType> 562 (eatLengthPrefixedName(param)) 563 .Case("ocl_image1darray" , AMDGPULibFunc::IMG1DA) 564 .Case("ocl_image1dbuffer", AMDGPULibFunc::IMG1DB) 565 .Case("ocl_image2darray" , AMDGPULibFunc::IMG2DA) 566 .Case("ocl_image1d" , AMDGPULibFunc::IMG1D) 567 .Case("ocl_image2d" , AMDGPULibFunc::IMG2D) 568 .Case("ocl_image3d" , AMDGPULibFunc::IMG3D) 569 .Case("ocl_event" , AMDGPULibFunc::DUMMY) 570 .Case("ocl_sampler" , AMDGPULibFunc::DUMMY) 571 .Default(AMDGPULibFunc::DUMMY); 572 } else { 573 drop_front(param); 574 switch (TC) { 575 case 'h': res.ArgType = AMDGPULibFunc::U8; break; 576 case 't': res.ArgType = AMDGPULibFunc::U16; break; 577 case 'j': res.ArgType = AMDGPULibFunc::U32; break; 578 case 'm': res.ArgType = AMDGPULibFunc::U64; break; 579 case 'c': res.ArgType = AMDGPULibFunc::I8; break; 580 case 's': res.ArgType = AMDGPULibFunc::I16; break; 581 case 'i': res.ArgType = AMDGPULibFunc::I32; break; 582 case 'l': res.ArgType = AMDGPULibFunc::I64; break; 583 case 'f': res.ArgType = AMDGPULibFunc::F32; break; 584 case 'd': res.ArgType = AMDGPULibFunc::F64; break; 585 case 'D': if (!eatTerm(param, 'h')) return false; 586 res.ArgType = AMDGPULibFunc::F16; break; 587 case 'S': 588 if (!eatTerm(param, '_')) { 589 eatNumber(param); 590 if (!eatTerm(param, '_')) return false; 591 } 592 res.VectorSize = Prev.VectorSize; 593 res.ArgType = Prev.ArgType; 594 break; 595 default:; 596 } 597 } 598 if (res.ArgType == 0) return false; 599 Prev.VectorSize = res.VectorSize; 600 Prev.ArgType = res.ArgType; 601 return true; 602 } 603 604 bool AMDGPULibFunc::parseItanuimName(StringRef& mangledName) { 605 StringRef Name = eatLengthPrefixedName(mangledName); 606 FKind = parseNamePrefix(Name); 607 if (!parseName(Name)) return false; 608 609 const ManglingRule& Rule = manglingRules[FuncId]; 610 ItaniumParamParser Parser; 611 for (int I=0; I < Rule.maxLeadIndex(); ++I) { 612 Param P; 613 if (!Parser.parseItaniumParam(mangledName, P)) 614 return false; 615 616 if ((I + 1) == Rule.Lead[0]) Leads[0] = P; 617 if ((I + 1) == Rule.Lead[1]) Leads[1] = P; 618 } 619 return true; 620 } 621 622 bool AMDGPULibFunc::parse(StringRef mangledName, AMDGPULibFunc& iInfo) { 623 iInfo.reset(); 624 if (mangledName.empty()) 625 return false; 626 627 if (eatTerm(mangledName, "_Z")) { 628 return iInfo.parseItanuimName(mangledName); 629 } 630 return false; 631 } 632 633 StringRef AMDGPULibFunc::getUnmangledName(const StringRef& mangledName) { 634 StringRef S = mangledName; 635 if (eatTerm(S, "_Z")) 636 return eatLengthPrefixedName(S); 637 return StringRef(); 638 } 639 640 641 /////////////////////////////////////////////////////////////////////////////// 642 // Mangling 643 644 template <typename Stream> 645 void AMDGPULibFunc::writeName(Stream& OS) const { 646 const char *Pfx = ""; 647 switch (FKind) { 648 case NATIVE: Pfx = "native_"; break; 649 case HALF: Pfx = "half_"; break; 650 default: break; 651 } 652 if (!Name.empty()) { 653 OS << Pfx << Name; 654 } else if (FuncId != EI_NONE) { 655 OS << Pfx; 656 const StringRef& S = manglingRules[FuncId].Name; 657 OS.write(S.data(), S.size()); 658 } 659 } 660 661 std::string AMDGPULibFunc::mangle() const { 662 return mangleNameItanium(); 663 } 664 665 /////////////////////////////////////////////////////////////////////////////// 666 // Itanium Mangling 667 668 static const char *getItaniumTypeName(AMDGPULibFunc::EType T) { 669 switch (T) { 670 case AMDGPULibFunc::U8: return "h"; 671 case AMDGPULibFunc::U16: return "t"; 672 case AMDGPULibFunc::U32: return "j"; 673 case AMDGPULibFunc::U64: return "m"; 674 case AMDGPULibFunc::I8: return "c"; 675 case AMDGPULibFunc::I16: return "s"; 676 case AMDGPULibFunc::I32: return "i"; 677 case AMDGPULibFunc::I64: return "l"; 678 case AMDGPULibFunc::F16: return "Dh"; 679 case AMDGPULibFunc::F32: return "f"; 680 case AMDGPULibFunc::F64: return "d"; 681 case AMDGPULibFunc::IMG1DA: return "16ocl_image1darray"; 682 case AMDGPULibFunc::IMG1DB: return "17ocl_image1dbuffer"; 683 case AMDGPULibFunc::IMG2DA: return "16ocl_image2darray"; 684 case AMDGPULibFunc::IMG1D: return "11ocl_image1d"; 685 case AMDGPULibFunc::IMG2D: return "11ocl_image2d"; 686 case AMDGPULibFunc::IMG3D: return "11ocl_image3d"; 687 case AMDGPULibFunc::SAMPLER: return "11ocl_sampler"; 688 case AMDGPULibFunc::EVENT: return "9ocl_event"; 689 default: llvm_unreachable("Unhandeled param type"); 690 } 691 return nullptr; 692 } 693 694 namespace { 695 // Itanium mangling ABI says: 696 // "5.1.8. Compression 697 // ... Each non-terminal in the grammar for which <substitution> appears on the 698 // right-hand side is both a source of future substitutions and a candidate 699 // for being substituted. There are two exceptions that appear to be 700 // substitution candidates from the grammar, but are explicitly excluded: 701 // 1. <builtin-type> other than vendor extended types ..." 702 703 // For the purpose of functions the following productions make sence for the 704 // substitution: 705 // <type> ::= <builtin-type> 706 // ::= <class-enum-type> 707 // ::= <array-type> 708 // ::=<CV-qualifiers> <type> 709 // ::= P <type> # pointer-to 710 // ::= <substitution> 711 // 712 // Note that while types like images, samplers and events are by the ABI encoded 713 // using <class-enum-type> production rule they're not used for substitution 714 // because clang consider them as builtin types. 715 // 716 // DvNN_ type is GCC extension for vectors and is a subject for the substitution. 717 718 719 class ItaniumMangler { 720 SmallVector<AMDGPULibFunc::Param, 10> Str; // list of accumulated substituions 721 bool UseAddrSpace; 722 723 int findSubst(const AMDGPULibFunc::Param& P) const { 724 for(unsigned I = 0; I < Str.size(); ++I) { 725 const AMDGPULibFunc::Param& T = Str[I]; 726 if (P.PtrKind == T.PtrKind && 727 P.VectorSize == T.VectorSize && 728 P.ArgType == T.ArgType) { 729 return I; 730 } 731 } 732 return -1; 733 } 734 735 template <typename Stream> 736 bool trySubst(Stream& os, const AMDGPULibFunc::Param& p) { 737 int const subst = findSubst(p); 738 if (subst < 0) return false; 739 // Substitutions are mangled as S(XX)?_ where XX is a hexadecimal number 740 // 0 1 2 741 // S_ S0_ S1_ 742 if (subst == 0) os << "S_"; 743 else os << 'S' << (subst-1) << '_'; 744 return true; 745 } 746 747 public: 748 ItaniumMangler(bool useAddrSpace) 749 : UseAddrSpace(useAddrSpace) {} 750 751 template <typename Stream> 752 void operator()(Stream& os, AMDGPULibFunc::Param p) { 753 754 // Itanium mangling ABI 5.1.8. Compression: 755 // Logically, the substitutable components of a mangled name are considered 756 // left-to-right, components before the composite structure of which they 757 // are a part. If a component has been encountered before, it is substituted 758 // as described below. This decision is independent of whether its components 759 // have been substituted, so an implementation may optimize by considering 760 // large structures for substitution before their components. If a component 761 // has not been encountered before, its mangling is identified, and it is 762 // added to a dictionary of substitution candidates. No entity is added to 763 // the dictionary twice. 764 AMDGPULibFunc::Param Ptr; 765 766 if (p.PtrKind) { 767 if (trySubst(os, p)) return; 768 os << 'P'; 769 if (p.PtrKind & AMDGPULibFunc::CONST) os << 'K'; 770 if (p.PtrKind & AMDGPULibFunc::VOLATILE) os << 'V'; 771 int AS = UseAddrSpace ? (p.PtrKind & AMDGPULibFunc::ADDR_SPACE)-1 : 0; 772 if (AS != 0) os << "U3AS" << AS; 773 Ptr = p; 774 p.PtrKind = 0; 775 } 776 777 if (p.VectorSize > 1) { 778 if (trySubst(os, p)) goto exit; 779 Str.push_back(p); 780 os << "Dv" << static_cast<unsigned>(p.VectorSize) << '_'; 781 } 782 783 os << getItaniumTypeName((AMDGPULibFunc::EType)p.ArgType); 784 785 exit: 786 if (Ptr.ArgType) Str.push_back(Ptr); 787 } 788 }; 789 } // namespace 790 791 std::string AMDGPULibFunc::mangleNameItanium() const { 792 SmallString<128> Buf; 793 raw_svector_ostream S(Buf); 794 SmallString<128> NameBuf; 795 raw_svector_ostream Name(NameBuf); 796 writeName(Name); 797 const StringRef& NameStr = Name.str(); 798 S << "_Z" << static_cast<int>(NameStr.size()) << NameStr; 799 800 ItaniumMangler Mangler(true); 801 ParamIterator I(Leads, manglingRules[FuncId]); 802 Param P; 803 while ((P = I.getNextParam()).ArgType != 0) 804 Mangler(S, P); 805 return S.str(); 806 } 807 808 /////////////////////////////////////////////////////////////////////////////// 809 // Misc 810 811 static Type* getIntrinsicParamType( 812 LLVMContext& C, 813 const AMDGPULibFunc::Param& P, 814 bool useAddrSpace) { 815 Type* T = nullptr; 816 switch (P.ArgType) { 817 case AMDGPULibFunc::U8: 818 case AMDGPULibFunc::I8: T = Type::getInt8Ty(C); break; 819 case AMDGPULibFunc::U16: 820 case AMDGPULibFunc::I16: T = Type::getInt16Ty(C); break; 821 case AMDGPULibFunc::U32: 822 case AMDGPULibFunc::I32: T = Type::getInt32Ty(C); break; 823 case AMDGPULibFunc::U64: 824 case AMDGPULibFunc::I64: T = Type::getInt64Ty(C); break; 825 case AMDGPULibFunc::F16: T = Type::getHalfTy(C); break; 826 case AMDGPULibFunc::F32: T = Type::getFloatTy(C); break; 827 case AMDGPULibFunc::F64: T = Type::getDoubleTy(C); break; 828 829 case AMDGPULibFunc::IMG1DA: 830 case AMDGPULibFunc::IMG1DB: 831 case AMDGPULibFunc::IMG2DA: 832 case AMDGPULibFunc::IMG1D: 833 case AMDGPULibFunc::IMG2D: 834 case AMDGPULibFunc::IMG3D: 835 T = StructType::create(C,"ocl_image")->getPointerTo(); break; 836 case AMDGPULibFunc::SAMPLER: 837 T = StructType::create(C,"ocl_sampler")->getPointerTo(); break; 838 case AMDGPULibFunc::EVENT: 839 T = StructType::create(C,"ocl_event")->getPointerTo(); break; 840 default: 841 llvm_unreachable("Unhandeled param type"); 842 return nullptr; 843 } 844 if (P.VectorSize > 1) 845 T = VectorType::get(T, P.VectorSize); 846 if (P.PtrKind != AMDGPULibFunc::BYVALUE) 847 T = useAddrSpace ? T->getPointerTo((P.PtrKind & AMDGPULibFunc::ADDR_SPACE) 848 - 1) 849 : T->getPointerTo(); 850 return T; 851 } 852 853 FunctionType* AMDGPULibFunc::getFunctionType(Module& M) const { 854 LLVMContext& C = M.getContext(); 855 std::vector<Type*> Args; 856 ParamIterator I(Leads, manglingRules[FuncId]); 857 Param P; 858 while ((P=I.getNextParam()).ArgType != 0) 859 Args.push_back(getIntrinsicParamType(C, P, true)); 860 861 return FunctionType::get( 862 getIntrinsicParamType(C, getRetType(FuncId, Leads), true), 863 Args, false); 864 } 865 866 unsigned AMDGPULibFunc::getNumArgs() const { 867 return manglingRules[FuncId].getNumArgs(); 868 } 869 870 std::string AMDGPULibFunc::getName() const { 871 SmallString<128> Buf; 872 raw_svector_ostream OS(Buf); 873 writeName(OS); 874 return OS.str(); 875 } 876 877 Function *AMDGPULibFunc::getFunction(Module *M, const AMDGPULibFunc& fInfo) { 878 std::string FuncName = fInfo.mangle(); 879 Function *F = dyn_cast_or_null<Function>( 880 M->getValueSymbolTable().lookup(FuncName)); 881 882 // check formal with actual types conformance 883 if (F && !F->isDeclaration() 884 && !F->isVarArg() 885 && F->arg_size() == fInfo.getNumArgs()) { 886 return F; 887 } 888 return nullptr; 889 } 890 891 Function *AMDGPULibFunc::getOrInsertFunction(Module *M, 892 const AMDGPULibFunc& fInfo) { 893 std::string const FuncName = fInfo.mangle(); 894 Function *F = dyn_cast_or_null<Function>( 895 M->getValueSymbolTable().lookup(FuncName)); 896 897 // check formal with actual types conformance 898 if (F && !F->isDeclaration() 899 && !F->isVarArg() 900 && F->arg_size() == fInfo.getNumArgs()) { 901 return F; 902 } 903 904 FunctionType *FuncTy = fInfo.getFunctionType(*M); 905 906 bool hasPtr = false; 907 for (FunctionType::param_iterator 908 PI = FuncTy->param_begin(), 909 PE = FuncTy->param_end(); 910 PI != PE; ++PI) { 911 const Type* argTy = static_cast<const Type*>(*PI); 912 if (argTy->isPointerTy()) { 913 hasPtr = true; 914 break; 915 } 916 } 917 918 Constant *C = nullptr; 919 if (hasPtr) { 920 // Do not set extra attributes for functions with pointer arguments. 921 C = M->getOrInsertFunction(FuncName, FuncTy); 922 } else { 923 AttributeList Attr; 924 LLVMContext &Ctx = M->getContext(); 925 Attr.addAttribute(Ctx, AttributeList::FunctionIndex, Attribute::ReadOnly); 926 Attr.addAttribute(Ctx, AttributeList::FunctionIndex, Attribute::NoUnwind); 927 C = M->getOrInsertFunction(FuncName, FuncTy, Attr); 928 } 929 930 return cast<Function>(C); 931 } 932