blob: 5391a365544c0db350f2e6c3bbb05e781684c786 [file] [log] [blame]
Kévin Petit617a76d2019-04-04 13:54:16 +01001// Copyright 2019 The Clspv Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "SPIRVOp.h"
16
17#include "llvm/IR/Constants.h"
18#include "llvm/IR/DerivedTypes.h"
19#include "llvm/IR/Instructions.h"
20#include "llvm/IR/Module.h"
21
22#include "Constants.h"
23
24namespace clspv {
25
26using namespace llvm;
27
28// The mangling loosely follows the Itanium convention.
29// Its purpose is solely to ensure uniqueness of names, it is not
30// meant to convey type information.
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040031static std::string mangleType(Type *Ty) {
Kévin Petit617a76d2019-04-04 13:54:16 +010032 if (Ty->isVectorTy()) {
33 auto NumVecElems = std::to_string(Ty->getVectorNumElements());
34 return "Dv" + NumVecElems + "_" + mangleType(Ty->getScalarType());
35 } else if (Ty->isIntegerTy()) {
Kévin Petitff03aee2019-06-12 19:39:03 +010036 switch (Ty->getScalarSizeInBits()) {
37 case 1:
38 return "b";
39 case 8:
Kévin Petit617a76d2019-04-04 13:54:16 +010040 return "h";
Kévin Petitff03aee2019-06-12 19:39:03 +010041 case 16:
Kévin Petit617a76d2019-04-04 13:54:16 +010042 return "t";
Kévin Petitff03aee2019-06-12 19:39:03 +010043 case 32:
Kévin Petit617a76d2019-04-04 13:54:16 +010044 return "j";
Kévin Petitff03aee2019-06-12 19:39:03 +010045 case 64:
Kévin Petit617a76d2019-04-04 13:54:16 +010046 return "m";
47 }
Kévin Petitff03aee2019-06-12 19:39:03 +010048 } else if (Ty->isFloatingPointTy()) {
49 switch (Ty->getScalarSizeInBits()) {
50 case 32:
51 return "f";
52 case 64:
53 return "d";
54 }
Kévin Petit9b340262019-06-19 18:31:11 +010055 } else if (Ty->isPointerTy()) {
56 auto PtrTy = cast<PointerType>(Ty);
57 auto AS = std::to_string(PtrTy->getAddressSpace());
58 return "P" + AS + mangleType(PtrTy->getElementType());
Kévin Petit617a76d2019-04-04 13:54:16 +010059 }
60
61 llvm_unreachable("Unhandled type in SPIR-V intrinsic name mangler");
62}
63
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040064Instruction *InsertSPIRVOp(Instruction *Insert, spv::Op Opcode,
Kévin Petit617a76d2019-04-04 13:54:16 +010065 ArrayRef<Attribute::AttrKind> Attributes,
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040066 Type *RetType, ArrayRef<Value *> Args) {
Kévin Petit617a76d2019-04-04 13:54:16 +010067
68 // Prepare mangled name
69 std::string MangledName = clspv::SPIRVOpIntrinsicFunction();
70 MangledName += std::to_string(Opcode);
71 MangledName += ".";
72 for (auto Arg : Args) {
73 MangledName += mangleType(Arg->getType());
74 }
75
76 // Create a function in the module
77 auto M = Insert->getModule();
78 auto Int32Ty = Type::getInt32Ty(M->getContext());
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040079 SmallVector<Type *, 8> ArgTypes = {Int32Ty};
Kévin Petit617a76d2019-04-04 13:54:16 +010080 for (auto Arg : Args) {
81 ArgTypes.push_back(Arg->getType());
82 }
83 auto NewFType = FunctionType::get(RetType, ArgTypes, false);
84 auto NewFTyC = M->getOrInsertFunction(MangledName, NewFType);
85 auto NewF = cast<Function>(NewFTyC.getCallee());
86 for (auto A : Attributes) {
87 NewF->addFnAttr(A);
88 }
89
90 // Now call it with the values we were passed
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040091 SmallVector<Value *, 8> ArgValues = {ConstantInt::get(Int32Ty, Opcode)};
Kévin Petit617a76d2019-04-04 13:54:16 +010092 for (auto Arg : Args) {
93 ArgValues.push_back(Arg);
94 }
95
96 return CallInst::Create(NewF, ArgValues, "", Insert);
97}
98
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040099}; // namespace clspv