blob: c23f19db0a8a8426763f125ac9d07c4735630edf [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) {
James Pricecf53df42020-04-20 14:41:24 -040032 if (auto VecTy = dyn_cast<VectorType>(Ty)) {
33 auto NumVecElems = std::to_string(VecTy->getNumElements());
Kévin Petit617a76d2019-04-04 13:54:16 +010034 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()) {
James Price71403812020-03-16 08:18:47 -040050 case 16:
51 return "Dh";
Kévin Petitff03aee2019-06-12 19:39:03 +010052 case 32:
53 return "f";
54 case 64:
55 return "d";
56 }
Kévin Petit9b340262019-06-19 18:31:11 +010057 } else if (Ty->isPointerTy()) {
58 auto PtrTy = cast<PointerType>(Ty);
59 auto AS = std::to_string(PtrTy->getAddressSpace());
60 return "P" + AS + mangleType(PtrTy->getElementType());
Kévin Petit617a76d2019-04-04 13:54:16 +010061 }
62
63 llvm_unreachable("Unhandled type in SPIR-V intrinsic name mangler");
64}
65
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040066Instruction *InsertSPIRVOp(Instruction *Insert, spv::Op Opcode,
Kévin Petit617a76d2019-04-04 13:54:16 +010067 ArrayRef<Attribute::AttrKind> Attributes,
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040068 Type *RetType, ArrayRef<Value *> Args) {
Kévin Petit617a76d2019-04-04 13:54:16 +010069
70 // Prepare mangled name
71 std::string MangledName = clspv::SPIRVOpIntrinsicFunction();
72 MangledName += std::to_string(Opcode);
73 MangledName += ".";
74 for (auto Arg : Args) {
75 MangledName += mangleType(Arg->getType());
76 }
77
78 // Create a function in the module
79 auto M = Insert->getModule();
80 auto Int32Ty = Type::getInt32Ty(M->getContext());
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040081 SmallVector<Type *, 8> ArgTypes = {Int32Ty};
Kévin Petit617a76d2019-04-04 13:54:16 +010082 for (auto Arg : Args) {
83 ArgTypes.push_back(Arg->getType());
84 }
85 auto NewFType = FunctionType::get(RetType, ArgTypes, false);
86 auto NewFTyC = M->getOrInsertFunction(MangledName, NewFType);
87 auto NewF = cast<Function>(NewFTyC.getCallee());
88 for (auto A : Attributes) {
89 NewF->addFnAttr(A);
90 }
91
92 // Now call it with the values we were passed
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040093 SmallVector<Value *, 8> ArgValues = {ConstantInt::get(Int32Ty, Opcode)};
Kévin Petit617a76d2019-04-04 13:54:16 +010094 for (auto Arg : Args) {
95 ArgValues.push_back(Arg);
96 }
97
98 return CallInst::Create(NewF, ArgValues, "", Insert);
99}
100
Diego Novillo3cc8d7a2019-04-10 13:30:34 -0400101}; // namespace clspv