Stanislav Mekhanoshin | 7f37794 | 2017-08-11 16:42:09 +0000 | [diff] [blame] | 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 | |
Benjamin Kramer | 49a49fe | 2017-08-20 13:03:48 +0000 | [diff] [blame] | 519 | namespace { |
Stanislav Mekhanoshin | 7f37794 | 2017-08-11 16:42:09 +0000 | [diff] [blame] | 520 | struct ItaniumParamParser { |
| 521 | AMDGPULibFunc::Param Prev; |
| 522 | bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res); |
| 523 | }; |
Benjamin Kramer | 49a49fe | 2017-08-20 13:03:48 +0000 | [diff] [blame] | 524 | } // namespace |
Stanislav Mekhanoshin | 7f37794 | 2017-08-11 16:42:09 +0000 | [diff] [blame] | 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 | |
Benjamin Kramer | 49a49fe | 2017-08-20 13:03:48 +0000 | [diff] [blame] | 694 | namespace { |
Stanislav Mekhanoshin | 7f37794 | 2017-08-11 16:42:09 +0000 | [diff] [blame] | 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 | }; |
Benjamin Kramer | 49a49fe | 2017-08-20 13:03:48 +0000 | [diff] [blame] | 789 | } // namespace |
Stanislav Mekhanoshin | 7f37794 | 2017-08-11 16:42:09 +0000 | [diff] [blame] | 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 | } |