blob: 32b3f342a4bb81d254360664403b96f33841b4fc [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.
31static std::string mangleType(Type* Ty) {
32 if (Ty->isVectorTy()) {
33 auto NumVecElems = std::to_string(Ty->getVectorNumElements());
34 return "Dv" + NumVecElems + "_" + mangleType(Ty->getScalarType());
35 } else if (Ty->isIntegerTy()) {
36 if (Ty->getScalarSizeInBits() == 8) {
37 return "h";
38 } else if (Ty->getScalarSizeInBits() == 16) {
39 return "t";
40 } else if (Ty->getScalarSizeInBits() == 32) {
41 return "j";
42 } else if (Ty->getScalarSizeInBits() == 64) {
43 return "m";
44 }
45 }
46
47 llvm_unreachable("Unhandled type in SPIR-V intrinsic name mangler");
48}
49
50Instruction* InsertSPIRVOp(Instruction* Insert, spv::Op Opcode,
51 ArrayRef<Attribute::AttrKind> Attributes,
52 Type* RetType, ArrayRef<Value*> Args) {
53
54 // Prepare mangled name
55 std::string MangledName = clspv::SPIRVOpIntrinsicFunction();
56 MangledName += std::to_string(Opcode);
57 MangledName += ".";
58 for (auto Arg : Args) {
59 MangledName += mangleType(Arg->getType());
60 }
61
62 // Create a function in the module
63 auto M = Insert->getModule();
64 auto Int32Ty = Type::getInt32Ty(M->getContext());
65 SmallVector<Type*, 8> ArgTypes = { Int32Ty };
66 for (auto Arg : Args) {
67 ArgTypes.push_back(Arg->getType());
68 }
69 auto NewFType = FunctionType::get(RetType, ArgTypes, false);
70 auto NewFTyC = M->getOrInsertFunction(MangledName, NewFType);
71 auto NewF = cast<Function>(NewFTyC.getCallee());
72 for (auto A : Attributes) {
73 NewF->addFnAttr(A);
74 }
75
76 // Now call it with the values we were passed
77 SmallVector<Value*, 8> ArgValues = { ConstantInt::get(Int32Ty, Opcode) };
78 for (auto Arg : Args) {
79 ArgValues.push_back(Arg);
80 }
81
82 return CallInst::Create(NewF, ArgValues, "", Insert);
83}
84
85};