• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- SPIRVUtil.cpp - SPIR-V Utilities -------------------------*- C++ -*-===//
2 //
3 //                     The LLVM/SPIRV Translator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal with the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // Redistributions of source code must retain the above copyright notice,
18 // this list of conditions and the following disclaimers.
19 // Redistributions in binary form must reproduce the above copyright notice,
20 // this list of conditions and the following disclaimers in the documentation
21 // and/or other materials provided with the distribution.
22 // Neither the names of Advanced Micro Devices, Inc., nor the names of its
23 // contributors may be used to endorse or promote products derived from this
24 // Software without specific prior written permission.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
31 // THE SOFTWARE.
32 //
33 //===----------------------------------------------------------------------===//
34 /// \file
35 ///
36 /// This file defines utility classes and functions shared by SPIR-V
37 /// reader/writer.
38 ///
39 //===----------------------------------------------------------------------===//
40 
41 #include "SPIRVInternal.h"
42 #include "libSPIRV/SPIRVDecorate.h"
43 #include "libSPIRV/SPIRVValue.h"
44 #include "SPIRVMDWalker.h"
45 #include "OCLUtil.h"
46 
47 #include "llvm/ADT/StringSwitch.h"
48 #include "llvm/Bitcode/ReaderWriter.h"
49 #include "llvm/IR/IRBuilder.h"
50 #include "llvm/Support/CommandLine.h"
51 #include "llvm/Support/Debug.h"
52 #include "llvm/Support/ErrorHandling.h"
53 #include "llvm/Support/FileSystem.h"
54 #include "llvm/Support/ToolOutputFile.h"
55 #include "llvm/Support/raw_ostream.h"
56 
57 #include <functional>
58 #include <sstream>
59 
60 #define DEBUG_TYPE "spirv"
61 
62 namespace SPIRV{
63 
64 #ifdef _SPIRV_SUPPORT_TEXT_FMT
65 cl::opt<bool, true>
66 UseTextFormat("spirv-text",
67     cl::desc("Use text format for SPIR-V for debugging purpose"),
68     cl::location(SPIRVUseTextFormat));
69 #endif
70 
71 #ifdef _SPIRVDBG
72 cl::opt<bool, true>
73 EnableDbgOutput("spirv-debug",
74     cl::desc("Enable SPIR-V debug output"),
75     cl::location(SPIRVDbgEnable));
76 #endif
77 
78 void
addFnAttr(LLVMContext * Context,CallInst * Call,Attribute::AttrKind Attr)79 addFnAttr(LLVMContext *Context, CallInst *Call, Attribute::AttrKind Attr) {
80   Call->addAttribute(AttributeSet::FunctionIndex, Attr);
81 }
82 
83 void
removeFnAttr(LLVMContext * Context,CallInst * Call,Attribute::AttrKind Attr)84 removeFnAttr(LLVMContext *Context, CallInst *Call, Attribute::AttrKind Attr) {
85   Call->removeAttribute(AttributeSet::FunctionIndex,
86       Attribute::get(*Context, Attr));
87 }
88 
89 Value *
removeCast(Value * V)90 removeCast(Value *V) {
91   auto Cast = dyn_cast<ConstantExpr>(V);
92   if (Cast && Cast->isCast()) {
93     return removeCast(Cast->getOperand(0));
94   }
95   if (auto Cast = dyn_cast<CastInst>(V))
96     return removeCast(Cast->getOperand(0));
97   return V;
98 }
99 
100 void
saveLLVMModule(Module * M,const std::string & OutputFile)101 saveLLVMModule(Module *M, const std::string &OutputFile) {
102   std::error_code EC;
103   tool_output_file Out(OutputFile.c_str(), EC, sys::fs::F_None);
104   if (EC) {
105     SPIRVDBG(errs() << "Fails to open output file: " << EC.message();)
106     return;
107   }
108 
109   WriteBitcodeToFile(M, Out.os());
110   Out.keep();
111 }
112 
113 std::string
mapLLVMTypeToOCLType(const Type * Ty,bool Signed)114 mapLLVMTypeToOCLType(const Type* Ty, bool Signed) {
115   if (Ty->isHalfTy())
116     return "half";
117   if (Ty->isFloatTy())
118     return "float";
119   if (Ty->isDoubleTy())
120     return "double";
121   if (auto intTy = dyn_cast<IntegerType>(Ty)) {
122     std::string SignPrefix;
123     std::string Stem;
124     if (!Signed)
125       SignPrefix = "u";
126     switch (intTy->getIntegerBitWidth()) {
127     case 8:
128       Stem = "char";
129       break;
130     case 16:
131       Stem = "short";
132       break;
133     case 32:
134       Stem = "int";
135       break;
136     case 64:
137       Stem = "long";
138       break;
139     default:
140       Stem = "invalid_type";
141       break;
142     }
143     return SignPrefix + Stem;
144   }
145   if (auto vecTy = dyn_cast<VectorType>(Ty)) {
146     Type* eleTy = vecTy->getElementType();
147     unsigned size = vecTy->getVectorNumElements();
148     std::stringstream ss;
149     ss << mapLLVMTypeToOCLType(eleTy, Signed) << size;
150     return ss.str();
151   }
152   return "invalid_type";
153 }
154 
155 std::string
mapSPIRVTypeToOCLType(SPIRVType * Ty,bool Signed)156 mapSPIRVTypeToOCLType(SPIRVType* Ty, bool Signed) {
157   if (Ty->isTypeFloat()) {
158     auto W = Ty->getBitWidth();
159     switch (W) {
160     case 16:
161       return "half";
162     case 32:
163       return "float";
164     case 64:
165       return "double";
166     default:
167       assert (0 && "Invalid floating pointer type");
168       return std::string("float") + W + "_t";
169     }
170   }
171   if (Ty->isTypeInt()) {
172     std::string SignPrefix;
173     std::string Stem;
174     if (!Signed)
175       SignPrefix = "u";
176     auto W = Ty->getBitWidth();
177     switch (W) {
178     case 8:
179       Stem = "char";
180       break;
181     case 16:
182       Stem = "short";
183       break;
184     case 32:
185       Stem = "int";
186       break;
187     case 64:
188       Stem = "long";
189       break;
190     default:
191       llvm_unreachable("Invalid integer type");
192       Stem = std::string("int") + W + "_t";
193       break;
194     }
195     return SignPrefix + Stem;
196   }
197   if (Ty->isTypeVector()) {
198     auto eleTy = Ty->getVectorComponentType();
199     auto size = Ty->getVectorComponentCount();
200     std::stringstream ss;
201     ss << mapSPIRVTypeToOCLType(eleTy, Signed) << size;
202     return ss.str();
203   }
204   llvm_unreachable("Invalid type");
205   return "unknown_type";
206 }
207 
208 PointerType*
getOrCreateOpaquePtrType(Module * M,const std::string & Name,unsigned AddrSpace)209 getOrCreateOpaquePtrType(Module *M, const std::string &Name,
210     unsigned AddrSpace) {
211   auto OpaqueType = M->getTypeByName(Name);
212   if (!OpaqueType)
213     OpaqueType = StructType::create(M->getContext(), Name);
214   return PointerType::get(OpaqueType, AddrSpace);
215 }
216 
217 PointerType*
getSamplerType(Module * M)218 getSamplerType(Module *M) {
219   return getOrCreateOpaquePtrType(M, getSPIRVTypeName(kSPIRVTypeName::Sampler),
220                                   SPIRAS_Constant);
221 }
222 
223 PointerType*
getPipeStorageType(Module * M)224 getPipeStorageType(Module* M) {
225   return getOrCreateOpaquePtrType(M, getSPIRVTypeName(
226                                         kSPIRVTypeName::PipeStorage),
227                                         SPIRAS_Constant);
228 }
229 
230 
231 void
getFunctionTypeParameterTypes(llvm::FunctionType * FT,std::vector<Type * > & ArgTys)232 getFunctionTypeParameterTypes(llvm::FunctionType* FT,
233     std::vector<Type*>& ArgTys) {
234   for (auto I = FT->param_begin(), E = FT->param_end(); I != E; ++I) {
235     ArgTys.push_back(*I);
236   }
237 }
238 
239 bool
isVoidFuncTy(FunctionType * FT)240 isVoidFuncTy(FunctionType *FT) {
241   return FT->getReturnType()->isVoidTy() && FT->getNumParams() == 0;
242 }
243 
244 bool
isPointerToOpaqueStructType(llvm::Type * Ty)245 isPointerToOpaqueStructType(llvm::Type* Ty) {
246   if (auto PT = dyn_cast<PointerType>(Ty))
247     if (auto ST = dyn_cast<StructType>(PT->getElementType()))
248       if (ST->isOpaque())
249         return true;
250   return false;
251 }
252 
253 bool
isPointerToOpaqueStructType(llvm::Type * Ty,const std::string & Name)254 isPointerToOpaqueStructType(llvm::Type* Ty, const std::string &Name) {
255   if (auto PT = dyn_cast<PointerType>(Ty))
256     if (auto ST = dyn_cast<StructType>(PT->getElementType()))
257       if (ST->isOpaque() && ST->getName() == Name)
258         return true;
259   return false;
260 }
261 
262 bool
isOCLImageType(llvm::Type * Ty,StringRef * Name)263 isOCLImageType(llvm::Type* Ty, StringRef *Name) {
264   if (auto PT = dyn_cast<PointerType>(Ty))
265     if (auto ST = dyn_cast<StructType>(PT->getElementType()))
266       if (ST->isOpaque()) {
267         auto FullName = ST->getName();
268         if (FullName.find(kSPR2TypeName::ImagePrefix) == 0) {
269           if (Name)
270             *Name = FullName.drop_front(strlen(kSPR2TypeName::OCLPrefix));
271           return true;
272         }
273       }
274   return false;
275 }
276 
277 /// \param BaseTyName is the type name as in spirv.BaseTyName.Postfixes
278 /// \param Postfix contains postfixes extracted from the SPIR-V image
279 ///   type name as spirv.BaseTyName.Postfixes.
280 bool
isSPIRVType(llvm::Type * Ty,StringRef BaseTyName,StringRef * Postfix)281 isSPIRVType(llvm::Type* Ty, StringRef BaseTyName, StringRef *Postfix) {
282   if (auto PT = dyn_cast<PointerType>(Ty))
283     if (auto ST = dyn_cast<StructType>(PT->getElementType()))
284       if (ST->isOpaque()) {
285         auto FullName = ST->getName();
286         std::string N = std::string(kSPIRVTypeName::PrefixAndDelim) +
287           BaseTyName.str();
288         if (FullName != N)
289           N = N + kSPIRVTypeName::Delimiter;
290         if (FullName.startswith(N)) {
291           if (Postfix)
292             *Postfix = FullName.drop_front(N.size());
293           return true;
294         }
295       }
296   return false;
297 }
298 
299 Function *
getOrCreateFunction(Module * M,Type * RetTy,ArrayRef<Type * > ArgTypes,StringRef Name,BuiltinFuncMangleInfo * Mangle,AttributeSet * Attrs,bool takeName)300 getOrCreateFunction(Module *M, Type *RetTy, ArrayRef<Type *> ArgTypes,
301     StringRef Name, BuiltinFuncMangleInfo *Mangle, AttributeSet *Attrs,
302     bool takeName) {
303   std::string MangledName = Name;
304   bool isVarArg = false;
305   if (Mangle) {
306     MangledName = mangleBuiltin(Name, ArgTypes, Mangle);
307     isVarArg = 0 <= Mangle->getVarArg();
308     if(isVarArg) ArgTypes = ArgTypes.slice(0, Mangle->getVarArg());
309   }
310   FunctionType *FT = FunctionType::get(RetTy, ArgTypes, isVarArg);
311   Function *F = M->getFunction(MangledName);
312   if (!takeName && F && F->getFunctionType() != FT && Mangle != nullptr) {
313     std::string S;
314     raw_string_ostream SS(S);
315     SS << "Error: Attempt to redefine function: " << *F << " => " <<
316         *FT << '\n';
317     report_fatal_error(SS.str(), false);
318   }
319   if (!F || F->getFunctionType() != FT) {
320     auto NewF = Function::Create(FT,
321       GlobalValue::ExternalLinkage,
322       MangledName,
323       M);
324     if (F && takeName) {
325       NewF->takeName(F);
326       DEBUG(dbgs() << "[getOrCreateFunction] Warning: taking function name\n");
327     }
328     if (NewF->getName() != MangledName) {
329       DEBUG(dbgs() << "[getOrCreateFunction] Warning: function name changed\n");
330     }
331     DEBUG(dbgs() << "[getOrCreateFunction] ";
332       if (F)
333         dbgs() << *F << " => ";
334       dbgs() << *NewF << '\n';
335       );
336     F = NewF;
337     F->setCallingConv(CallingConv::SPIR_FUNC);
338     if (Attrs)
339       F->setAttributes(*Attrs);
340   }
341   return F;
342 }
343 
344 std::vector<Value *>
getArguments(CallInst * CI,unsigned Start,unsigned End)345 getArguments(CallInst* CI, unsigned Start, unsigned End) {
346   std::vector<Value*> Args;
347   if (End == 0)
348     End = CI->getNumArgOperands();
349   for (; Start != End; ++Start) {
350     Args.push_back(CI->getArgOperand(Start));
351   }
352   return Args;
353 }
354 
getArgAsInt(CallInst * CI,unsigned I)355 uint64_t getArgAsInt(CallInst *CI, unsigned I){
356   return cast<ConstantInt>(CI->getArgOperand(I))->getZExtValue();
357 }
358 
getArgAsScope(CallInst * CI,unsigned I)359 Scope getArgAsScope(CallInst *CI, unsigned I){
360   return static_cast<Scope>(getArgAsInt(CI, I));
361 }
362 
getArgAsDecoration(CallInst * CI,unsigned I)363 Decoration getArgAsDecoration(CallInst *CI, unsigned I) {
364   return static_cast<Decoration>(getArgAsInt(CI, I));
365 }
366 
367 std::string
decorateSPIRVFunction(const std::string & S)368 decorateSPIRVFunction(const std::string &S) {
369   return std::string(kSPIRVName::Prefix) + S + kSPIRVName::Postfix;
370 }
371 
372 std::string
undecorateSPIRVFunction(const std::string & S)373 undecorateSPIRVFunction(const std::string& S) {
374   assert (S.find(kSPIRVName::Prefix) == 0);
375   const size_t Start = strlen(kSPIRVName::Prefix);
376   auto End = S.rfind(kSPIRVName::Postfix);
377   return S.substr(Start, End - Start);
378 }
379 
380 std::string
prefixSPIRVName(const std::string & S)381 prefixSPIRVName(const std::string &S) {
382   return std::string(kSPIRVName::Prefix) + S;
383 }
384 
385 StringRef
dePrefixSPIRVName(StringRef R,SmallVectorImpl<StringRef> & Postfix)386 dePrefixSPIRVName(StringRef R,
387     SmallVectorImpl<StringRef> &Postfix) {
388   const size_t Start = strlen(kSPIRVName::Prefix);
389   if (!R.startswith(kSPIRVName::Prefix))
390     return R;
391   R = R.drop_front(Start);
392   R.split(Postfix, "_", -1, false);
393   auto Name = Postfix.front();
394   Postfix.erase(Postfix.begin());
395   return Name;
396 }
397 
398 std::string
getSPIRVFuncName(Op OC,StringRef PostFix)399 getSPIRVFuncName(Op OC, StringRef PostFix) {
400   return prefixSPIRVName(getName(OC) + PostFix.str());
401 }
402 
403 std::string
getSPIRVFuncName(Op OC,const Type * pRetTy,bool IsSigned)404 getSPIRVFuncName(Op OC, const Type *pRetTy, bool IsSigned) {
405   return prefixSPIRVName(getName(OC) + kSPIRVPostfix::Divider +
406                          getPostfixForReturnType(pRetTy, false));
407 }
408 
409 std::string
getSPIRVExtFuncName(SPIRVExtInstSetKind Set,unsigned ExtOp,StringRef PostFix)410 getSPIRVExtFuncName(SPIRVExtInstSetKind Set, unsigned ExtOp,
411     StringRef PostFix) {
412   std::string ExtOpName;
413   switch(Set) {
414   default:
415     llvm_unreachable("invalid extended instruction set");
416     ExtOpName = "unknown";
417     break;
418   case SPIRVEIS_OpenCL:
419     ExtOpName = getName(static_cast<OCLExtOpKind>(ExtOp));
420     break;
421   }
422   return prefixSPIRVName(SPIRVExtSetShortNameMap::map(Set)
423       + '_' + ExtOpName + PostFix.str());
424 }
425 
426 SPIRVDecorate *
mapPostfixToDecorate(StringRef Postfix,SPIRVEntry * Target)427 mapPostfixToDecorate(StringRef Postfix, SPIRVEntry *Target) {
428   if (Postfix == kSPIRVPostfix::Sat)
429     return new SPIRVDecorate(spv::DecorationSaturatedConversion, Target);
430 
431   if (Postfix.startswith(kSPIRVPostfix::Rt))
432     return new SPIRVDecorate(spv::DecorationFPRoundingMode, Target,
433       map<SPIRVFPRoundingModeKind>(Postfix.str()));
434 
435   return nullptr;
436 }
437 
438 SPIRVValue *
addDecorations(SPIRVValue * Target,const SmallVectorImpl<std::string> & Decs)439 addDecorations(SPIRVValue *Target, const SmallVectorImpl<std::string>& Decs){
440   for (auto &I:Decs)
441     if (auto Dec = mapPostfixToDecorate(I, Target))
442       Target->addDecorate(Dec);
443   return Target;
444 }
445 
446 std::string
getPostfix(Decoration Dec,unsigned Value)447 getPostfix(Decoration Dec, unsigned Value) {
448   switch(Dec) {
449   default:
450     llvm_unreachable("not implemented");
451     return "unknown";
452   case spv::DecorationSaturatedConversion:
453     return kSPIRVPostfix::Sat;
454   case spv::DecorationFPRoundingMode:
455     return rmap<std::string>(static_cast<SPIRVFPRoundingModeKind>(Value));
456   }
457 }
458 
459 std::string
getPostfixForReturnType(CallInst * CI,bool IsSigned)460 getPostfixForReturnType(CallInst *CI, bool IsSigned) {
461   return getPostfixForReturnType(CI->getType(), IsSigned);
462 }
463 
getPostfixForReturnType(const Type * pRetTy,bool IsSigned)464 std::string getPostfixForReturnType(const Type *pRetTy, bool IsSigned) {
465   return std::string(kSPIRVPostfix::Return) +
466          mapLLVMTypeToOCLType(pRetTy, IsSigned);
467 }
468 
469 Op
getSPIRVFuncOC(const std::string & S,SmallVectorImpl<std::string> * Dec)470 getSPIRVFuncOC(const std::string& S, SmallVectorImpl<std::string> *Dec) {
471   Op OC;
472   SmallVector<StringRef, 2> Postfix;
473   std::string Name;
474   if (!oclIsBuiltin(S, &Name))
475     Name = S;
476   StringRef R(Name);
477   R = dePrefixSPIRVName(R, Postfix);
478   if (!getByName(R.str(), OC))
479     return OpNop;
480   if (Dec)
481     for (auto &I:Postfix)
482       Dec->push_back(I.str());
483   return OC;
484 }
485 
486 bool
getSPIRVBuiltin(const std::string & OrigName,spv::BuiltIn & B)487 getSPIRVBuiltin(const std::string &OrigName, spv::BuiltIn &B) {
488   SmallVector<StringRef, 2> Postfix;
489   StringRef R(OrigName);
490   R = dePrefixSPIRVName(R, Postfix);
491   assert(Postfix.empty() && "Invalid SPIR-V builtin name");
492   return getByName(R.str(), B);
493 }
494 
oclIsBuiltin(const StringRef & Name,std::string * DemangledName,bool isCPP)495 bool oclIsBuiltin(const StringRef &Name, std::string *DemangledName,
496                   bool isCPP) {
497   if (Name == "printf") {
498     if (DemangledName)
499       *DemangledName = Name;
500     return true;
501   }
502   if (!Name.startswith("_Z"))
503     return false;
504   if (!DemangledName)
505     return true;
506   // OpenCL C++ built-ins are declared in cl namespace.
507   // TODO: consider using 'St' abbriviation for cl namespace mangling.
508   // Similar to ::std:: in C++.
509   if (isCPP) {
510     if (!Name.startswith("_ZN"))
511       return false;
512     // Skip CV and ref qualifiers.
513     size_t NameSpaceStart = Name.find_first_not_of("rVKRO", 3);
514     // All built-ins are in the ::cl:: namespace.
515     if (Name.substr(NameSpaceStart, 11) != "2cl7__spirv")
516       return false;
517     size_t DemangledNameLenStart = NameSpaceStart + 11;
518     size_t Start = Name.find_first_not_of("0123456789", DemangledNameLenStart);
519     size_t Len = 0;
520     Name.substr(DemangledNameLenStart, Start - DemangledNameLenStart)
521         .getAsInteger(10, Len);
522     *DemangledName = Name.substr(Start, Len);
523   } else {
524     size_t Start = Name.find_first_not_of("0123456789", 2);
525     size_t Len = 0;
526     Name.substr(2, Start - 2).getAsInteger(10, Len);
527     *DemangledName = Name.substr(Start, Len);
528   }
529   return true;
530 }
531 
532 // Check if a mangled type name is unsigned
isMangledTypeUnsigned(char Mangled)533 bool isMangledTypeUnsigned(char Mangled) {
534   return Mangled == 'h'    /* uchar */
535          || Mangled == 't' /* ushort */
536          || Mangled == 'j' /* uint */
537          || Mangled == 'm' /* ulong */;
538 }
539 
540 // Check if a mangled type name is signed
isMangledTypeSigned(char Mangled)541 bool isMangledTypeSigned(char Mangled) {
542   return Mangled == 'c'    /* char */
543          || Mangled == 'a' /* signed char */
544          || Mangled == 's' /* short */
545          || Mangled == 'i' /* int */
546          || Mangled == 'l' /* long */;
547 }
548 
549 // Check if a mangled type name is floating point (excludes half)
isMangledTypeFP(char Mangled)550 bool isMangledTypeFP(char Mangled) {
551   return Mangled == 'f'     /* float */
552          || Mangled == 'd'; /* double */
553 }
554 
555 // Check if a mangled type name is half
isMangledTypeHalf(std::string Mangled)556 bool isMangledTypeHalf(std::string Mangled) {
557   return Mangled == "Dh"; /* half */
558 }
559 
560 void
eraseSubstitutionFromMangledName(std::string & MangledName)561 eraseSubstitutionFromMangledName(std::string& MangledName) {
562   auto Len = MangledName.length();
563   while (Len >= 2 && MangledName.substr(Len - 2, 2) == "S_") {
564     Len -= 2;
565     MangledName.erase(Len, 2);
566   }
567 }
568 
LastFuncParamType(const std::string & MangledName)569 ParamType LastFuncParamType(const std::string &MangledName) {
570   auto Copy = MangledName;
571   eraseSubstitutionFromMangledName(Copy);
572   char Mangled = Copy.back();
573   std::string Mangled2 = Copy.substr(Copy.size() - 2);
574 
575   if (isMangledTypeFP(Mangled) || isMangledTypeHalf(Mangled2)) {
576     return ParamType::FLOAT;
577   } else if (isMangledTypeUnsigned(Mangled)) {
578     return ParamType::UNSIGNED;
579   } else if (isMangledTypeSigned(Mangled)) {
580     return ParamType::SIGNED;
581   }
582 
583   return ParamType::UNKNOWN;
584 }
585 
586 // Check if the last argument is signed
587 bool
isLastFuncParamSigned(const std::string & MangledName)588 isLastFuncParamSigned(const std::string& MangledName) {
589   return LastFuncParamType(MangledName) == ParamType::SIGNED;
590 }
591 
592 
593 // Check if a mangled function name contains unsigned atomic type
594 bool
containsUnsignedAtomicType(StringRef Name)595 containsUnsignedAtomicType(StringRef Name) {
596   auto Loc = Name.find(kMangledName::AtomicPrefixIncoming);
597   if (Loc == StringRef::npos)
598     return false;
599   return isMangledTypeUnsigned(Name[Loc + strlen(
600       kMangledName::AtomicPrefixIncoming)]);
601 }
602 
603 bool
isFunctionPointerType(Type * T)604 isFunctionPointerType(Type *T) {
605   if (isa<PointerType>(T) &&
606       isa<FunctionType>(T->getPointerElementType())) {
607     return true;
608   }
609   return false;
610 }
611 
612 bool
hasFunctionPointerArg(Function * F,Function::arg_iterator & AI)613 hasFunctionPointerArg(Function *F, Function::arg_iterator& AI) {
614   AI = F->arg_begin();
615   for (auto AE = F->arg_end(); AI != AE; ++AI) {
616     DEBUG(dbgs() << "[hasFuncPointerArg] " << *AI << '\n');
617     if (isFunctionPointerType(AI->getType())) {
618       return true;
619     }
620   }
621   return false;
622 }
623 
624 Constant *
castToVoidFuncPtr(Function * F)625 castToVoidFuncPtr(Function *F) {
626   auto T = getVoidFuncPtrType(F->getParent());
627   return ConstantExpr::getBitCast(F, T);
628 }
629 
630 bool
hasArrayArg(Function * F)631 hasArrayArg(Function *F) {
632   for (auto I = F->arg_begin(), E = F->arg_end(); I != E; ++I) {
633     DEBUG(dbgs() << "[hasArrayArg] " << *I << '\n');
634     if (I->getType()->isArrayTy()) {
635       return true;
636     }
637   }
638   return false;
639 }
640 
641 CallInst *
mutateCallInst(Module * M,CallInst * CI,std::function<std::string (CallInst *,std::vector<Value * > &)> ArgMutate,BuiltinFuncMangleInfo * Mangle,AttributeSet * Attrs,bool TakeFuncName)642 mutateCallInst(Module *M, CallInst *CI,
643     std::function<std::string (CallInst *, std::vector<Value *> &)>ArgMutate,
644     BuiltinFuncMangleInfo *Mangle, AttributeSet *Attrs, bool TakeFuncName) {
645   DEBUG(dbgs() << "[mutateCallInst] " << *CI);
646 
647   auto Args = getArguments(CI);
648   auto NewName = ArgMutate(CI, Args);
649   std::string InstName;
650   if (!CI->getType()->isVoidTy() && CI->hasName()) {
651     InstName = CI->getName();
652     CI->setName(InstName + ".old");
653   }
654   auto NewCI = addCallInst(M, NewName, CI->getType(), Args, Attrs, CI, Mangle,
655       InstName, TakeFuncName);
656   DEBUG(dbgs() << " => " << *NewCI << '\n');
657   CI->replaceAllUsesWith(NewCI);
658   CI->dropAllReferences();
659   CI->removeFromParent();
660   return NewCI;
661 }
662 
663 Instruction *
mutateCallInst(Module * M,CallInst * CI,std::function<std::string (CallInst *,std::vector<Value * > &,Type * & RetTy)> ArgMutate,std::function<Instruction * (CallInst *)> RetMutate,BuiltinFuncMangleInfo * Mangle,AttributeSet * Attrs,bool TakeFuncName)664 mutateCallInst(Module *M, CallInst *CI,
665     std::function<std::string (CallInst *, std::vector<Value *> &,
666         Type *&RetTy)>ArgMutate,
667     std::function<Instruction *(CallInst *)> RetMutate,
668     BuiltinFuncMangleInfo *Mangle, AttributeSet *Attrs, bool TakeFuncName) {
669   DEBUG(dbgs() << "[mutateCallInst] " << *CI);
670 
671   auto Args = getArguments(CI);
672   Type *RetTy = CI->getType();
673   auto NewName = ArgMutate(CI, Args, RetTy);
674   std::string InstName;
675   if (CI->hasName()) {
676     InstName = CI->getName();
677     CI->setName(InstName + ".old");
678   }
679   auto NewCI = addCallInst(M, NewName, RetTy, Args, Attrs,
680       CI, Mangle, InstName + ".tmp", TakeFuncName);
681   auto NewI = RetMutate(NewCI);
682   NewI->takeName(CI);
683   DEBUG(dbgs() << " => " << *NewI << '\n');
684   CI->replaceAllUsesWith(NewI);
685   CI->dropAllReferences();
686   CI->removeFromParent();
687   return NewI;
688 }
689 
690 void
mutateFunction(Function * F,std::function<std::string (CallInst *,std::vector<Value * > &)> ArgMutate,BuiltinFuncMangleInfo * Mangle,AttributeSet * Attrs,bool TakeFuncName)691 mutateFunction(Function *F,
692     std::function<std::string (CallInst *, std::vector<Value *> &)>ArgMutate,
693     BuiltinFuncMangleInfo *Mangle, AttributeSet *Attrs,
694     bool TakeFuncName) {
695   auto M = F->getParent();
696   for (auto I = F->user_begin(), E = F->user_end(); I != E;) {
697     if (auto CI = dyn_cast<CallInst>(*I++))
698       mutateCallInst(M, CI, ArgMutate, Mangle, Attrs, TakeFuncName);
699   }
700   if (F->use_empty())
701     F->eraseFromParent();
702 }
703 
704 CallInst *
mutateCallInstSPIRV(Module * M,CallInst * CI,std::function<std::string (CallInst *,std::vector<Value * > &)> ArgMutate,AttributeSet * Attrs)705 mutateCallInstSPIRV(Module *M, CallInst *CI,
706     std::function<std::string (CallInst *, std::vector<Value *> &)>ArgMutate,
707     AttributeSet *Attrs) {
708   BuiltinFuncMangleInfo BtnInfo;
709   return mutateCallInst(M, CI, ArgMutate, &BtnInfo, Attrs);
710 }
711 
712 Instruction *
mutateCallInstSPIRV(Module * M,CallInst * CI,std::function<std::string (CallInst *,std::vector<Value * > &,Type * & RetTy)> ArgMutate,std::function<Instruction * (CallInst *)> RetMutate,AttributeSet * Attrs)713 mutateCallInstSPIRV(Module *M, CallInst *CI,
714     std::function<std::string (CallInst *, std::vector<Value *> &,
715         Type *&RetTy)> ArgMutate,
716     std::function<Instruction *(CallInst *)> RetMutate,
717     AttributeSet *Attrs) {
718   BuiltinFuncMangleInfo BtnInfo;
719   return mutateCallInst(M, CI, ArgMutate, RetMutate, &BtnInfo, Attrs);
720 }
721 
722 CallInst *
addCallInst(Module * M,StringRef FuncName,Type * RetTy,ArrayRef<Value * > Args,AttributeSet * Attrs,Instruction * Pos,BuiltinFuncMangleInfo * Mangle,StringRef InstName,bool TakeFuncName)723 addCallInst(Module *M, StringRef FuncName, Type *RetTy, ArrayRef<Value *> Args,
724     AttributeSet *Attrs, Instruction *Pos, BuiltinFuncMangleInfo *Mangle,
725     StringRef InstName, bool TakeFuncName) {
726 
727   auto F = getOrCreateFunction(M, RetTy, getTypes(Args),
728       FuncName, Mangle, Attrs, TakeFuncName);
729   // Cannot assign a name to void typed values
730   auto CI = CallInst::Create(F, Args, RetTy->isVoidTy() ? "" : InstName, Pos);
731   CI->setCallingConv(F->getCallingConv());
732   return CI;
733 }
734 
735 CallInst *
addCallInstSPIRV(Module * M,StringRef FuncName,Type * RetTy,ArrayRef<Value * > Args,AttributeSet * Attrs,Instruction * Pos,StringRef InstName)736 addCallInstSPIRV(Module *M, StringRef FuncName, Type *RetTy, ArrayRef<Value *> Args,
737     AttributeSet *Attrs, Instruction *Pos, StringRef InstName) {
738   BuiltinFuncMangleInfo BtnInfo;
739   return addCallInst(M, FuncName, RetTy, Args, Attrs, Pos, &BtnInfo,
740       InstName);
741 }
742 
743 bool
isValidVectorSize(unsigned I)744 isValidVectorSize(unsigned I) {
745   return I == 2 ||
746          I == 3 ||
747          I == 4 ||
748          I == 8 ||
749          I == 16;
750 }
751 
752 Value *
addVector(Instruction * InsPos,ValueVecRange Range)753 addVector(Instruction *InsPos, ValueVecRange Range) {
754   size_t VecSize = Range.second - Range.first;
755   if (VecSize == 1)
756     return *Range.first;
757   assert(isValidVectorSize(VecSize) && "Invalid vector size");
758   IRBuilder<> Builder(InsPos);
759   auto Vec = Builder.CreateVectorSplat(VecSize, *Range.first);
760   unsigned Index = 1;
761   for (++Range.first; Range.first != Range.second; ++Range.first, ++Index)
762     Vec = Builder.CreateInsertElement(Vec, *Range.first,
763         ConstantInt::get(Type::getInt32Ty(InsPos->getContext()), Index, false));
764   return Vec;
765 }
766 
767 void
makeVector(Instruction * InsPos,std::vector<Value * > & Ops,ValueVecRange Range)768 makeVector(Instruction *InsPos, std::vector<Value *> &Ops,
769     ValueVecRange Range) {
770   auto Vec = addVector(InsPos, Range);
771   Ops.erase(Range.first, Range.second);
772   Ops.push_back(Vec);
773 }
774 
775 void
expandVector(Instruction * InsPos,std::vector<Value * > & Ops,size_t VecPos)776 expandVector(Instruction *InsPos, std::vector<Value *> &Ops,
777     size_t VecPos) {
778   auto Vec = Ops[VecPos];
779   auto VT = Vec->getType();
780   if (!VT->isVectorTy())
781     return;
782   size_t N = VT->getVectorNumElements();
783   IRBuilder<> Builder(InsPos);
784   for (size_t I = 0; I != N; ++I)
785     Ops.insert(Ops.begin() + VecPos + I, Builder.CreateExtractElement(Vec,
786         ConstantInt::get(Type::getInt32Ty(InsPos->getContext()), I, false)));
787   Ops.erase(Ops.begin() + VecPos + N);
788 }
789 
790 Constant *
castToInt8Ptr(Constant * V,unsigned Addr=0)791 castToInt8Ptr(Constant *V, unsigned Addr = 0) {
792   return ConstantExpr::getBitCast(V, Type::getInt8PtrTy(V->getContext(), Addr));
793 }
794 
795 PointerType *
getInt8PtrTy(PointerType * T)796 getInt8PtrTy(PointerType *T) {
797   return Type::getInt8PtrTy(T->getContext(), T->getAddressSpace());
798 }
799 
800 Value *
castToInt8Ptr(Value * V,Instruction * Pos)801 castToInt8Ptr(Value *V, Instruction *Pos) {
802   return CastInst::CreatePointerCast(V, getInt8PtrTy(
803       cast<PointerType>(V->getType())), "", Pos);
804 }
805 
806 CallInst *
addBlockBind(Module * M,Function * InvokeFunc,Value * BlkCtx,Value * CtxLen,Value * CtxAlign,Instruction * InsPos,StringRef InstName)807 addBlockBind(Module *M, Function *InvokeFunc, Value *BlkCtx, Value *CtxLen,
808     Value *CtxAlign, Instruction *InsPos, StringRef InstName) {
809   auto BlkTy = getOrCreateOpaquePtrType(M, SPIR_TYPE_NAME_BLOCK_T,
810       SPIRAS_Private);
811   auto &Ctx = M->getContext();
812   Value *BlkArgs[] = {
813       castToInt8Ptr(InvokeFunc),
814       CtxLen ? CtxLen : UndefValue::get(Type::getInt32Ty(Ctx)),
815       CtxAlign ? CtxAlign : UndefValue::get(Type::getInt32Ty(Ctx)),
816       BlkCtx ? BlkCtx : UndefValue::get(Type::getInt8PtrTy(Ctx))
817   };
818   return addCallInst(M, SPIR_INTRINSIC_BLOCK_BIND, BlkTy, BlkArgs, nullptr,
819       InsPos, nullptr, InstName);
820 }
821 
getSizetType(Module * M)822 IntegerType* getSizetType(Module *M) {
823   return IntegerType::getIntNTy(M->getContext(),
824     M->getDataLayout().getPointerSizeInBits(0));
825 }
826 
827 Type *
getVoidFuncType(Module * M)828 getVoidFuncType(Module *M) {
829   return FunctionType::get(Type::getVoidTy(M->getContext()), false);
830 }
831 
832 Type *
getVoidFuncPtrType(Module * M,unsigned AddrSpace)833 getVoidFuncPtrType(Module *M, unsigned AddrSpace) {
834   return PointerType::get(getVoidFuncType(M), AddrSpace);
835 }
836 
837 ConstantInt *
getInt64(Module * M,int64_t value)838 getInt64(Module *M, int64_t value) {
839   return ConstantInt::get(Type::getInt64Ty(M->getContext()), value, true);
840 }
841 
getFloat32(Module * M,float value)842 Constant *getFloat32(Module *M, float value) {
843   return ConstantFP::get(Type::getFloatTy(M->getContext()), value);
844 }
845 
846 ConstantInt *
getInt32(Module * M,int value)847 getInt32(Module *M, int value) {
848   return ConstantInt::get(Type::getInt32Ty(M->getContext()), value, true);
849 }
850 
851 ConstantInt *
getUInt32(Module * M,unsigned value)852 getUInt32(Module *M, unsigned value) {
853   return ConstantInt::get(Type::getInt32Ty(M->getContext()), value, false);
854 }
855 
856 ConstantInt *
getUInt16(Module * M,unsigned short value)857 getUInt16(Module *M, unsigned short value) {
858   return ConstantInt::get(Type::getInt16Ty(M->getContext()), value, false);
859 }
860 
getInt32(Module * M,const std::vector<int> & value)861 std::vector<Value *> getInt32(Module *M, const std::vector<int> &value) {
862   std::vector<Value *> V;
863   for (auto &I:value)
864     V.push_back(getInt32(M, I));
865   return V;
866 }
867 
868 ConstantInt *
getSizet(Module * M,uint64_t value)869 getSizet(Module *M, uint64_t value) {
870   return ConstantInt::get(getSizetType(M), value, false);
871 }
872 
873 ///////////////////////////////////////////////////////////////////////////////
874 //
875 // Functions for getting metadata
876 //
877 ///////////////////////////////////////////////////////////////////////////////
878 int
getMDOperandAsInt(MDNode * N,unsigned I)879 getMDOperandAsInt(MDNode* N, unsigned I) {
880   return mdconst::dyn_extract<ConstantInt>(N->getOperand(I))->getZExtValue();
881 }
882 
883 std::string
getMDOperandAsString(MDNode * N,unsigned I)884 getMDOperandAsString(MDNode* N, unsigned I) {
885   if (!N)
886     return "";
887 
888   Metadata* Op = N->getOperand(I);
889   if (!Op)
890     return "";
891 
892   if (MDString* Str = dyn_cast<MDString>(Op)) {
893     return Str->getString().str();
894   }
895   return "";
896 }
897 
898 Type*
getMDOperandAsType(MDNode * N,unsigned I)899 getMDOperandAsType(MDNode* N, unsigned I) {
900   return cast<ValueAsMetadata>(N->getOperand(I))->getType();
901 }
902 
903 std::set<std::string>
getNamedMDAsStringSet(Module * M,const std::string & MDName)904 getNamedMDAsStringSet(Module *M, const std::string &MDName) {
905   NamedMDNode *NamedMD = M->getNamedMetadata(MDName);
906   std::set<std::string> StrSet;
907   if (!NamedMD)
908     return StrSet;
909 
910   assert(NamedMD->getNumOperands() > 0 && "Invalid SPIR");
911 
912   for (unsigned I = 0, E = NamedMD->getNumOperands(); I != E; ++I) {
913     MDNode *MD = NamedMD->getOperand(I);
914     if (!MD || MD->getNumOperands() == 0)
915       continue;
916     for (unsigned J = 0, N = MD->getNumOperands(); J != N; ++J)
917       StrSet.insert(getMDOperandAsString(MD, J));
918   }
919 
920   return StrSet;
921 }
922 
923 std::tuple<unsigned, unsigned, std::string>
getSPIRVSource(Module * M)924 getSPIRVSource(Module *M) {
925   std::tuple<unsigned, unsigned, std::string> Tup;
926   if (auto N = SPIRVMDWalker(*M).getNamedMD(kSPIRVMD::Source).nextOp())
927     N.get(std::get<0>(Tup))
928      .get(std::get<1>(Tup))
929      .setQuiet(true)
930      .get(std::get<2>(Tup));
931   return Tup;
932 }
933 
mapUInt(Module * M,ConstantInt * I,std::function<unsigned (unsigned)> F)934 ConstantInt *mapUInt(Module *M, ConstantInt *I,
935     std::function<unsigned(unsigned)> F) {
936   return ConstantInt::get(I->getType(), F(I->getZExtValue()), false);
937 }
938 
mapSInt(Module * M,ConstantInt * I,std::function<int (int)> F)939 ConstantInt *mapSInt(Module *M, ConstantInt *I,
940     std::function<int(int)> F) {
941   return ConstantInt::get(I->getType(), F(I->getSExtValue()), true);
942 }
943 
944 bool
isDecoratedSPIRVFunc(const Function * F,std::string * UndecoratedName)945 isDecoratedSPIRVFunc(const Function *F, std::string *UndecoratedName) {
946   if (!F->hasName() || !F->getName().startswith(kSPIRVName::Prefix))
947     return false;
948   if (UndecoratedName)
949     *UndecoratedName = undecorateSPIRVFunction(F->getName());
950   return true;
951 }
952 
953 /// Get TypePrimitiveEnum for special OpenCL type except opencl.block.
954 SPIR::TypePrimitiveEnum
getOCLTypePrimitiveEnum(StringRef TyName)955 getOCLTypePrimitiveEnum(StringRef TyName) {
956   return StringSwitch<SPIR::TypePrimitiveEnum>(TyName)
957     .Case("opencl.image1d_t",         SPIR::PRIMITIVE_IMAGE_1D_T)
958     .Case("opencl.image1d_array_t",   SPIR::PRIMITIVE_IMAGE_1D_ARRAY_T)
959     .Case("opencl.image1d_buffer_t",  SPIR::PRIMITIVE_IMAGE_1D_BUFFER_T)
960     .Case("opencl.image2d_t",         SPIR::PRIMITIVE_IMAGE_2D_T)
961     .Case("opencl.image2d_array_t",   SPIR::PRIMITIVE_IMAGE_2D_ARRAY_T)
962     .Case("opencl.image3d_t",         SPIR::PRIMITIVE_IMAGE_3D_T)
963     .Case("opencl.image2d_msaa_t",    SPIR::PRIMITIVE_IMAGE_2D_MSAA_T)
964     .Case("opencl.image2d_array_msaa_t",        SPIR::PRIMITIVE_IMAGE_2D_ARRAY_MSAA_T)
965     .Case("opencl.image2d_msaa_depth_t",        SPIR::PRIMITIVE_IMAGE_2D_MSAA_DEPTH_T)
966     .Case("opencl.image2d_array_msaa_depth_t",  SPIR::PRIMITIVE_IMAGE_2D_ARRAY_MSAA_DEPTH_T)
967     .Case("opencl.image2d_depth_t",             SPIR::PRIMITIVE_IMAGE_2D_DEPTH_T)
968     .Case("opencl.image2d_array_depth_t",       SPIR::PRIMITIVE_IMAGE_2D_ARRAY_DEPTH_T)
969     .Case("opencl.event_t",           SPIR::PRIMITIVE_EVENT_T)
970     .Case("opencl.pipe_t",            SPIR::PRIMITIVE_PIPE_T)
971     .Case("opencl.reserve_id_t",      SPIR::PRIMITIVE_RESERVE_ID_T)
972     .Case("opencl.queue_t",           SPIR::PRIMITIVE_QUEUE_T)
973     .Case("opencl.clk_event_t",       SPIR::PRIMITIVE_CLK_EVENT_T)
974     .Case("opencl.sampler_t",         SPIR::PRIMITIVE_SAMPLER_T)
975     .Case("struct.ndrange_t",         SPIR::PRIMITIVE_NDRANGE_T)
976     .Default(                         SPIR::PRIMITIVE_NONE);
977 }
978 /// Translates LLVM type to descriptor for mangler.
979 /// \param Signed indicates integer type should be translated as signed.
980 /// \param VoidPtr indicates i8* should be translated as void*.
981 static SPIR::RefParamType
transTypeDesc(Type * Ty,const BuiltinArgTypeMangleInfo & Info)982 transTypeDesc(Type *Ty, const BuiltinArgTypeMangleInfo &Info) {
983   bool Signed = Info.IsSigned;
984   unsigned Attr = Info.Attr;
985   bool VoidPtr = Info.IsVoidPtr;
986   if (Info.IsEnum)
987     return SPIR::RefParamType(new SPIR::PrimitiveType(Info.Enum));
988   if (Info.IsSampler)
989     return SPIR::RefParamType(new SPIR::PrimitiveType(
990         SPIR::PRIMITIVE_SAMPLER_T));
991   if (Info.IsAtomic && !Ty->isPointerTy()) {
992     BuiltinArgTypeMangleInfo DTInfo = Info;
993     DTInfo.IsAtomic = false;
994     return SPIR::RefParamType(new SPIR::AtomicType(
995         transTypeDesc(Ty, DTInfo)));
996   }
997   if(auto *IntTy = dyn_cast<IntegerType>(Ty)) {
998     switch(IntTy->getBitWidth()) {
999     case 1:
1000       return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_BOOL));
1001     case 8:
1002       return SPIR::RefParamType(new SPIR::PrimitiveType(Signed?
1003           SPIR::PRIMITIVE_CHAR:SPIR::PRIMITIVE_UCHAR));
1004     case 16:
1005       return SPIR::RefParamType(new SPIR::PrimitiveType(Signed?
1006           SPIR::PRIMITIVE_SHORT:SPIR::PRIMITIVE_USHORT));
1007     case 32:
1008       return SPIR::RefParamType(new SPIR::PrimitiveType(Signed?
1009           SPIR::PRIMITIVE_INT:SPIR::PRIMITIVE_UINT));
1010     case 64:
1011       return SPIR::RefParamType(new SPIR::PrimitiveType(Signed?
1012           SPIR::PRIMITIVE_LONG:SPIR::PRIMITIVE_ULONG));
1013     default:
1014       llvm_unreachable("invliad int size");
1015     }
1016   }
1017   if (Ty->isVoidTy())
1018     return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_VOID));
1019   if (Ty->isHalfTy())
1020     return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_HALF));
1021   if (Ty->isFloatTy())
1022     return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_FLOAT));
1023   if (Ty->isDoubleTy())
1024     return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_DOUBLE));
1025   if (Ty->isVectorTy()) {
1026     return SPIR::RefParamType(new SPIR::VectorType(
1027         transTypeDesc(Ty->getVectorElementType(), Info),
1028         Ty->getVectorNumElements()));
1029   }
1030   if (Ty->isArrayTy()) {
1031     return transTypeDesc(PointerType::get(Ty->getArrayElementType(), 0), Info);
1032   }
1033   if (Ty->isStructTy()) {
1034     auto Name = Ty->getStructName();
1035     std::string Tmp;
1036 
1037     if (Name.startswith(kLLVMTypeName::StructPrefix))
1038       Name = Name.drop_front(strlen(kLLVMTypeName::StructPrefix));
1039     if (Name.startswith(kSPIRVTypeName::PrefixAndDelim)) {
1040       Name = Name.substr(sizeof(kSPIRVTypeName::PrefixAndDelim) - 1);
1041       Tmp = Name.str();
1042       auto pos = Tmp.find(kSPIRVTypeName::Delimiter); //first dot
1043       while (pos != std::string::npos) {
1044         Tmp[pos] = '_';
1045         pos = Tmp.find(kSPIRVTypeName::Delimiter, pos);
1046       }
1047       Name = Tmp = kSPIRVName::Prefix + Tmp;
1048     }
1049     // ToDo: Create a better unique name for struct without name
1050     if (Name.empty()) {
1051       std::ostringstream OS;
1052       OS << reinterpret_cast<size_t>(Ty);
1053       Name = Tmp = std::string("struct_") + OS.str();
1054     }
1055     return SPIR::RefParamType(new SPIR::UserDefinedType(Name));
1056   }
1057 
1058   if (Ty->isPointerTy()) {
1059     auto ET = Ty->getPointerElementType();
1060     SPIR::ParamType *EPT = nullptr;
1061     if (auto FT = dyn_cast<FunctionType>(ET)) {
1062       (void) FT;
1063       assert(isVoidFuncTy(FT) && "Not supported");
1064       EPT = new SPIR::BlockType;
1065     } else if (auto StructTy = dyn_cast<StructType>(ET)) {
1066       DEBUG(dbgs() << "ptr to struct: " << *Ty << '\n');
1067       auto TyName = StructTy->getStructName();
1068       if (TyName.startswith(kSPR2TypeName::ImagePrefix) ||
1069           TyName.startswith(kSPR2TypeName::Pipe)) {
1070         auto DelimPos = TyName.find_first_of(kSPR2TypeName::Delimiter,
1071             strlen(kSPR2TypeName::OCLPrefix));
1072         if (DelimPos != StringRef::npos)
1073           TyName = TyName.substr(0, DelimPos);
1074       }
1075       DEBUG(dbgs() << "  type name: " << TyName << '\n');
1076 
1077       auto Prim = getOCLTypePrimitiveEnum(TyName);
1078       if (StructTy->isOpaque()) {
1079         if (TyName == "opencl.block") {
1080           auto BlockTy = new SPIR::BlockType;
1081           // Handle block with local memory arguments according to OpenCL 2.0 spec.
1082           if(Info.IsLocalArgBlock) {
1083             SPIR::RefParamType VoidTyRef(new SPIR::PrimitiveType(SPIR::PRIMITIVE_VOID));
1084             auto VoidPtrTy = new SPIR::PointerType(VoidTyRef);
1085             VoidPtrTy->setAddressSpace(SPIR::ATTR_LOCAL);
1086             // "__local void *"
1087             BlockTy->setParam(0, SPIR::RefParamType(VoidPtrTy));
1088             // "..."
1089             BlockTy->setParam(1, SPIR::RefParamType(
1090               new SPIR::PrimitiveType(SPIR::PRIMITIVE_VAR_ARG)));
1091           }
1092           EPT = BlockTy;
1093         } else if (Prim != SPIR::PRIMITIVE_NONE) {
1094           if (Prim == SPIR::PRIMITIVE_PIPE_T) {
1095             SPIR::RefParamType OpaqueTyRef(new SPIR::PrimitiveType(Prim));
1096             auto OpaquePtrTy = new SPIR::PointerType(OpaqueTyRef);
1097             OpaquePtrTy->setAddressSpace(getOCLOpaqueTypeAddrSpace(Prim));
1098             EPT = OpaquePtrTy;
1099           }
1100           else {
1101             EPT = new SPIR::PrimitiveType(Prim);
1102           }
1103         }
1104       } else if (Prim == SPIR::PRIMITIVE_NDRANGE_T)
1105         // ndrange_t is not opaque type
1106         EPT = new SPIR::PrimitiveType(SPIR::PRIMITIVE_NDRANGE_T);
1107     }
1108     if (EPT)
1109       return SPIR::RefParamType(EPT);
1110 
1111     if (VoidPtr && ET->isIntegerTy(8))
1112       ET = Type::getVoidTy(ET->getContext());
1113     auto PT = new SPIR::PointerType(transTypeDesc(ET, Info));
1114     PT->setAddressSpace(static_cast<SPIR::TypeAttributeEnum>(
1115       Ty->getPointerAddressSpace() + (unsigned)SPIR::ATTR_ADDR_SPACE_FIRST));
1116     for (unsigned I = SPIR::ATTR_QUALIFIER_FIRST,
1117         E = SPIR::ATTR_QUALIFIER_LAST; I <= E; ++I)
1118       PT->setQualifier(static_cast<SPIR::TypeAttributeEnum>(I), I & Attr);
1119     return SPIR::RefParamType(PT);
1120   }
1121   DEBUG(dbgs() << "[transTypeDesc] " << *Ty << '\n');
1122   assert (0 && "not implemented");
1123   return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_INT));
1124 }
1125 
1126 Value *
getScalarOrArray(Value * V,unsigned Size,Instruction * Pos)1127 getScalarOrArray(Value *V, unsigned Size, Instruction *Pos) {
1128   if (!V->getType()->isPointerTy())
1129     return V;
1130   assert((isa<ConstantExpr>(V) || isa<GetElementPtrInst>(V)) &&
1131          "unexpected value type");
1132   auto GEP = cast<User>(V);
1133   assert(GEP->getNumOperands() == 3 && "must be a GEP from an array");
1134   auto P = GEP->getOperand(0);
1135   assert(P->getType()->getPointerElementType()->getArrayNumElements() == Size);
1136   auto Index0 = GEP->getOperand(1);
1137   (void) Index0;
1138   assert(dyn_cast<ConstantInt>(Index0)->getZExtValue() == 0);
1139   auto Index1 = GEP->getOperand(2);
1140   (void) Index1;
1141   assert(dyn_cast<ConstantInt>(Index1)->getZExtValue() == 0);
1142   return new LoadInst(P, "", Pos);
1143 }
1144 
1145 Constant *
getScalarOrVectorConstantInt(Type * T,uint64_t V,bool isSigned)1146 getScalarOrVectorConstantInt(Type *T, uint64_t V, bool isSigned) {
1147   if (auto IT = dyn_cast<IntegerType>(T))
1148     return ConstantInt::get(IT, V);
1149   if (auto VT = dyn_cast<VectorType>(T)) {
1150     std::vector<Constant *> EV(VT->getVectorNumElements(),
1151         getScalarOrVectorConstantInt(VT->getVectorElementType(), V, isSigned));
1152     return ConstantVector::get(EV);
1153   }
1154   llvm_unreachable("Invalid type");
1155   return nullptr;
1156 }
1157 
1158 Value *
getScalarOrArrayConstantInt(Instruction * Pos,Type * T,unsigned Len,uint64_t V,bool isSigned)1159 getScalarOrArrayConstantInt(Instruction *Pos, Type *T, unsigned Len, uint64_t V,
1160     bool isSigned) {
1161   if (auto IT = dyn_cast<IntegerType>(T)) {
1162     assert(Len == 1 && "Invalid length");
1163     return ConstantInt::get(IT, V, isSigned);
1164   }
1165   if (auto PT = dyn_cast<PointerType>(T)) {
1166     auto ET = PT->getPointerElementType();
1167     auto AT = ArrayType::get(ET, Len);
1168     std::vector<Constant *> EV(Len, ConstantInt::get(ET, V, isSigned));
1169     auto CA = ConstantArray::get(AT, EV);
1170     auto Alloca = new AllocaInst(AT, "", Pos);
1171     new StoreInst(CA, Alloca, Pos);
1172     auto Zero = ConstantInt::getNullValue(Type::getInt32Ty(T->getContext()));
1173     Value *Index[] = {Zero, Zero};
1174     auto Ret = GetElementPtrInst::CreateInBounds(Alloca, Index, "", Pos);
1175     DEBUG(dbgs() << "[getScalarOrArrayConstantInt] Alloca: " <<
1176         *Alloca << ", Return: " << *Ret << '\n');
1177     return Ret;
1178   }
1179   if (auto AT = dyn_cast<ArrayType>(T)) {
1180     auto ET = AT->getArrayElementType();
1181     assert(AT->getArrayNumElements() == Len);
1182     std::vector<Constant *> EV(Len, ConstantInt::get(ET, V, isSigned));
1183     auto Ret = ConstantArray::get(AT, EV);
1184     DEBUG(dbgs() << "[getScalarOrArrayConstantInt] Array type: " <<
1185         *AT << ", Return: " << *Ret << '\n');
1186     return Ret;
1187   }
1188   llvm_unreachable("Invalid type");
1189   return nullptr;
1190 }
1191 
1192 void
dumpUsers(Value * V,StringRef Prompt)1193 dumpUsers(Value* V, StringRef Prompt) {
1194   if (!V) return;
1195   DEBUG(dbgs() << Prompt << " Users of " << *V << " :\n");
1196   for (auto UI = V->user_begin(), UE = V->user_end(); UI != UE; ++UI)
1197     DEBUG(dbgs() << "  " << **UI << '\n');
1198 }
1199 
1200 std::string
getSPIRVTypeName(StringRef BaseName,StringRef Postfixes)1201 getSPIRVTypeName(StringRef BaseName, StringRef Postfixes) {
1202   assert(!BaseName.empty() && "Invalid SPIR-V type name");
1203   auto TN = std::string(kSPIRVTypeName::PrefixAndDelim)
1204     + BaseName.str();
1205   if (Postfixes.empty())
1206     return TN;
1207   return TN + kSPIRVTypeName::Delimiter + Postfixes.str();
1208 }
1209 
1210 bool
isSPIRVConstantName(StringRef TyName)1211 isSPIRVConstantName(StringRef TyName) {
1212   if (TyName == getSPIRVTypeName(kSPIRVTypeName::ConstantSampler) ||
1213       TyName == getSPIRVTypeName(kSPIRVTypeName::ConstantPipeStorage))
1214     return true;
1215 
1216   return false;
1217 }
1218 
1219 Type *
getSPIRVTypeByChangeBaseTypeName(Module * M,Type * T,StringRef OldName,StringRef NewName)1220 getSPIRVTypeByChangeBaseTypeName(Module *M, Type *T, StringRef OldName,
1221     StringRef NewName) {
1222   StringRef Postfixes;
1223   if (isSPIRVType(T, OldName, &Postfixes))
1224     return getOrCreateOpaquePtrType(M, getSPIRVTypeName(NewName, Postfixes));
1225   DEBUG(dbgs() << " Invalid SPIR-V type " << *T << '\n');
1226   llvm_unreachable("Invalid SPIRV-V type");
1227   return nullptr;
1228 }
1229 
1230 std::string
getSPIRVImageTypePostfixes(StringRef SampledType,SPIRVTypeImageDescriptor Desc,SPIRVAccessQualifierKind Acc)1231 getSPIRVImageTypePostfixes(StringRef SampledType,
1232     SPIRVTypeImageDescriptor Desc,
1233     SPIRVAccessQualifierKind Acc) {
1234   std::string S;
1235   raw_string_ostream OS(S);
1236   OS << SampledType << kSPIRVTypeName::PostfixDelim
1237      << Desc.Dim << kSPIRVTypeName::PostfixDelim
1238      << Desc.Depth << kSPIRVTypeName::PostfixDelim
1239      << Desc.Arrayed << kSPIRVTypeName::PostfixDelim
1240      << Desc.MS << kSPIRVTypeName::PostfixDelim
1241      << Desc.Sampled << kSPIRVTypeName::PostfixDelim
1242      << Desc.Format << kSPIRVTypeName::PostfixDelim
1243      << Acc;
1244   return OS.str();
1245 }
1246 
1247 std::string
getSPIRVImageSampledTypeName(SPIRVType * Ty)1248 getSPIRVImageSampledTypeName(SPIRVType *Ty) {
1249   switch(Ty->getOpCode()) {
1250   case OpTypeVoid:
1251     return kSPIRVImageSampledTypeName::Void;
1252   case OpTypeInt:
1253     if (Ty->getIntegerBitWidth() == 32) {
1254       if (static_cast<SPIRVTypeInt *>(Ty)->isSigned())
1255         return kSPIRVImageSampledTypeName::Int;
1256       else
1257         return kSPIRVImageSampledTypeName::UInt; }
1258     break;
1259   case OpTypeFloat:
1260     switch(Ty->getFloatBitWidth()) {
1261     case 16:
1262       return kSPIRVImageSampledTypeName::Half;
1263     case 32:
1264       return kSPIRVImageSampledTypeName::Float;
1265     default:
1266       break;
1267     }
1268     break;
1269   default:
1270     break;
1271   }
1272   llvm_unreachable("Invalid sampled type for image");
1273 }
1274 
1275 //ToDo: Find a way to represent uint sampled type in LLVM, maybe an
1276 //      opaque type.
1277 Type*
getLLVMTypeForSPIRVImageSampledTypePostfix(StringRef Postfix,LLVMContext & Ctx)1278 getLLVMTypeForSPIRVImageSampledTypePostfix(StringRef Postfix,
1279   LLVMContext &Ctx) {
1280   if (Postfix == kSPIRVImageSampledTypeName::Void)
1281     return Type::getVoidTy(Ctx);
1282   if (Postfix == kSPIRVImageSampledTypeName::Float)
1283     return Type::getFloatTy(Ctx);
1284   if (Postfix == kSPIRVImageSampledTypeName::Half)
1285     return Type::getHalfTy(Ctx);
1286   if (Postfix == kSPIRVImageSampledTypeName::Int ||
1287       Postfix == kSPIRVImageSampledTypeName::UInt)
1288     return Type::getInt32Ty(Ctx);
1289   llvm_unreachable("Invalid sampled type postfix");
1290 }
1291 
1292 std::string
mapOCLTypeNameToSPIRV(StringRef Name,StringRef Acc)1293 mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc) {
1294   std::string BaseTy;
1295   std::string Postfixes;
1296   raw_string_ostream OS(Postfixes);
1297   if (!Acc.empty())
1298     OS << kSPIRVTypeName::PostfixDelim;
1299   if (Name.startswith(kSPR2TypeName::Pipe)) {
1300     BaseTy = kSPIRVTypeName::Pipe;
1301     OS << SPIRSPIRVAccessQualifierMap::map(Acc);
1302   } else if (Name.startswith(kSPR2TypeName::ImagePrefix)) {
1303     SmallVector<StringRef, 4> SubStrs;
1304     const char Delims[] = {kSPR2TypeName::Delimiter, 0};
1305     Name.split(SubStrs, Delims);
1306     std::string ImageTyName = SubStrs[1].str();
1307     if (hasAccessQualifiedName(Name))
1308       ImageTyName.erase(ImageTyName.size() - 5, 3);
1309     auto Desc = map<SPIRVTypeImageDescriptor>(ImageTyName);
1310     DEBUG(dbgs() << "[trans image type] " << SubStrs[1] << " => " <<
1311         "(" << (unsigned)Desc.Dim << ", " <<
1312                Desc.Depth << ", " <<
1313                Desc.Arrayed << ", " <<
1314                Desc.MS << ", " <<
1315                Desc.Sampled << ", " <<
1316                Desc.Format << ")\n");
1317 
1318     BaseTy = kSPIRVTypeName::Image;
1319     OS << getSPIRVImageTypePostfixes(kSPIRVImageSampledTypeName::Void,
1320                                      Desc,
1321                                      SPIRSPIRVAccessQualifierMap::map(Acc));
1322   } else {
1323     DEBUG(dbgs() << "Mapping of " << Name << " is not implemented\n");
1324     llvm_unreachable("Not implemented");
1325   }
1326   return getSPIRVTypeName(BaseTy, OS.str());
1327 }
1328 
1329 bool
eraseIfNoUse(Function * F)1330 eraseIfNoUse(Function *F) {
1331   bool changed = false;
1332   if (!F)
1333     return changed;
1334   if (!GlobalValue::isInternalLinkage(F->getLinkage()) &&
1335       !F->isDeclaration())
1336     return changed;
1337 
1338   dumpUsers(F, "[eraseIfNoUse] ");
1339   for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) {
1340     auto U = *UI++;
1341     if (auto CE = dyn_cast<ConstantExpr>(U)){
1342       if (CE->use_empty()) {
1343         CE->dropAllReferences();
1344         changed = true;
1345       }
1346     }
1347   }
1348   if (F->use_empty()) {
1349     DEBUG(dbgs() << "Erase ";
1350           F->printAsOperand(dbgs());
1351           dbgs() << '\n');
1352     F->eraseFromParent();
1353     changed = true;
1354   }
1355   return changed;
1356 }
1357 
1358 void
eraseIfNoUse(Value * V)1359 eraseIfNoUse(Value *V) {
1360   if (!V->use_empty())
1361     return;
1362   if (Constant *C = dyn_cast<Constant>(V)) {
1363     C->destroyConstant();
1364     return;
1365   }
1366   if (Instruction *I = dyn_cast<Instruction>(V)) {
1367     if (!I->mayHaveSideEffects())
1368       I->eraseFromParent();
1369   }
1370   eraseIfNoUse(dyn_cast<Function>(V));
1371 }
1372 
1373 bool
eraseUselessFunctions(Module * M)1374 eraseUselessFunctions(Module *M) {
1375   bool changed = false;
1376   for (auto I = M->begin(), E = M->end(); I != E;)
1377     changed |= eraseIfNoUse(static_cast<Function*>(I++));
1378   return changed;
1379 }
1380 
1381 std::string
mangleBuiltin(const std::string & UniqName,ArrayRef<Type * > ArgTypes,BuiltinFuncMangleInfo * BtnInfo)1382 mangleBuiltin(const std::string &UniqName,
1383     ArrayRef<Type*> ArgTypes, BuiltinFuncMangleInfo* BtnInfo) {
1384   if (!BtnInfo)
1385     return UniqName;
1386   BtnInfo->init(UniqName);
1387   std::string MangledName;
1388   DEBUG(dbgs() << "[mangle] " << UniqName << " => ");
1389   SPIR::NameMangler Mangler(SPIR::SPIR20);
1390   SPIR::FunctionDescriptor FD;
1391   FD.name = BtnInfo->getUnmangledName();
1392   bool BIVarArgNegative = BtnInfo->getVarArg() < 0;
1393 
1394   if (ArgTypes.empty()) {
1395     // Function signature cannot be ()(void, ...) so if there is an ellipsis
1396     // it must be ()(...)
1397     if(BIVarArgNegative) {
1398       FD.parameters.emplace_back(SPIR::RefParamType(new SPIR::PrimitiveType(
1399         SPIR::PRIMITIVE_VOID)));
1400     }
1401   } else {
1402     for (unsigned I = 0,
1403          E = BIVarArgNegative ? ArgTypes.size() : (unsigned)BtnInfo->getVarArg();
1404          I != E; ++I) {
1405       auto T = ArgTypes[I];
1406       FD.parameters.emplace_back(transTypeDesc(T, BtnInfo->getTypeMangleInfo(I)));
1407     }
1408   }
1409   // Ellipsis must be the last argument of any function
1410   if(!BIVarArgNegative) {
1411     assert((unsigned)BtnInfo->getVarArg() <= ArgTypes.size()
1412            && "invalid index of an ellipsis");
1413     FD.parameters.emplace_back(SPIR::RefParamType(new SPIR::PrimitiveType(
1414         SPIR::PRIMITIVE_VAR_ARG)));
1415   }
1416   Mangler.mangle(FD, MangledName);
1417   DEBUG(dbgs() << MangledName << '\n');
1418   return MangledName;
1419 }
1420 
1421 /// Check if access qualifier is encoded in the type name.
hasAccessQualifiedName(StringRef TyName)1422 bool hasAccessQualifiedName(StringRef TyName) {
1423   if (TyName.endswith("_ro_t") || TyName.endswith("_wo_t") ||
1424       TyName.endswith("_rw_t"))
1425     return true;
1426   return false;
1427 }
1428 
1429 /// Get access qualifier from the type name.
getAccessQualifier(StringRef TyName)1430 StringRef getAccessQualifier(StringRef TyName) {
1431   assert(hasAccessQualifiedName(TyName) &&
1432          "Type is not qualified with access.");
1433   auto Acc = TyName.substr(TyName.size() - 4, 2);
1434   return llvm::StringSwitch<StringRef>(Acc)
1435       .Case("ro", "read_only")
1436       .Case("wo", "write_only")
1437       .Case("rw", "read_write")
1438       .Default("");
1439 }
1440 
1441 /// Translates OpenCL image type names to SPIR-V.
getSPIRVImageTypeFromOCL(Module * M,Type * ImageTy)1442 Type *getSPIRVImageTypeFromOCL(Module *M, Type *ImageTy) {
1443   assert(isOCLImageType(ImageTy) && "Unsupported type");
1444   auto ImageTypeName = ImageTy->getPointerElementType()->getStructName();
1445   std::string Acc = kAccessQualName::ReadOnly;
1446   if (hasAccessQualifiedName(ImageTypeName))
1447     Acc = getAccessQualifier(ImageTypeName);
1448   return getOrCreateOpaquePtrType(M, mapOCLTypeNameToSPIRV(ImageTypeName, Acc));
1449 }
1450 }
1451