1 //===- Target/DirectX/PointerTypeAnalisis.cpp - PointerType analysis ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Analysis pass to assign types to opaque pointers.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "PointerTypeAnalysis.h"
14 #include "llvm/IR/Instructions.h"
15
16 using namespace llvm;
17 using namespace llvm::dxil;
18
19 namespace {
20
21 // Classifies the type of the value passed in by walking the value's users to
22 // find a typed instruction to materialize a type from.
classifyPointerType(const Value * V)23 TypedPointerType *classifyPointerType(const Value *V) {
24 assert(V->getType()->isOpaquePointerTy() &&
25 "classifyPointerType called with non-opaque pointer");
26 Type *PointeeTy = nullptr;
27 if (auto *Inst = dyn_cast<GetElementPtrInst>(V)) {
28 if (!Inst->getResultElementType()->isOpaquePointerTy())
29 PointeeTy = Inst->getResultElementType();
30 } else if (auto *Inst = dyn_cast<AllocaInst>(V)) {
31 PointeeTy = Inst->getAllocatedType();
32 }
33 for (const auto *User : V->users()) {
34 Type *NewPointeeTy = nullptr;
35 if (const auto *Inst = dyn_cast<LoadInst>(User)) {
36 NewPointeeTy = Inst->getType();
37 } else if (const auto *Inst = dyn_cast<StoreInst>(User)) {
38 NewPointeeTy = Inst->getValueOperand()->getType();
39 } else if (const auto *Inst = dyn_cast<GetElementPtrInst>(User)) {
40 NewPointeeTy = Inst->getSourceElementType();
41 }
42 if (NewPointeeTy) {
43 // HLSL doesn't support pointers, so it is unlikely to get more than one
44 // or two levels of indirection in the IR. Because of this, recursion is
45 // pretty safe.
46 if (NewPointeeTy->isOpaquePointerTy())
47 return TypedPointerType::get(classifyPointerType(User),
48 V->getType()->getPointerAddressSpace());
49 if (!PointeeTy)
50 PointeeTy = NewPointeeTy;
51 else if (PointeeTy != NewPointeeTy)
52 PointeeTy = Type::getInt8Ty(V->getContext());
53 }
54 }
55 // If we were unable to determine the pointee type, set to i8
56 if (!PointeeTy)
57 PointeeTy = Type::getInt8Ty(V->getContext());
58 return TypedPointerType::get(PointeeTy,
59 V->getType()->getPointerAddressSpace());
60 }
61
62 // This function constructs a function type accepting typed pointers. It only
63 // handles function arguments and return types, and assigns the function type to
64 // the function's value in the type map.
classifyFunctionType(const Function & F,PointerTypeMap & Map)65 void classifyFunctionType(const Function &F, PointerTypeMap &Map) {
66 SmallVector<Type *, 8> NewArgs;
67 bool HasOpaqueTy = false;
68 Type *RetTy = F.getReturnType();
69 if (RetTy->isOpaquePointerTy()) {
70 RetTy = nullptr;
71 for (const auto &B : F) {
72 for (const auto &I : B) {
73 if (const auto *RetInst = dyn_cast_or_null<ReturnInst>(&I)) {
74 Type *NewRetTy = classifyPointerType(RetInst->getReturnValue());
75 if (!RetTy)
76 RetTy = NewRetTy;
77 else if (RetTy != NewRetTy)
78 RetTy = TypedPointerType::get(
79 Type::getInt8Ty(I.getContext()),
80 F.getReturnType()->getPointerAddressSpace());
81 }
82 }
83 }
84 }
85 for (auto &A : F.args()) {
86 Type *ArgTy = A.getType();
87 if (ArgTy->isOpaquePointerTy()) {
88 TypedPointerType *NewTy = classifyPointerType(&A);
89 Map[&A] = NewTy;
90 ArgTy = NewTy;
91 HasOpaqueTy = true;
92 }
93 NewArgs.push_back(ArgTy);
94 }
95 if (!HasOpaqueTy)
96 return;
97 Map[&F] = FunctionType::get(RetTy, NewArgs, false);
98 }
99 } // anonymous namespace
100
run(const Module & M)101 PointerTypeMap PointerTypeAnalysis::run(const Module &M) {
102 PointerTypeMap Map;
103 for (auto &G : M.globals()) {
104 if (G.getType()->isOpaquePointerTy())
105 Map[&G] = classifyPointerType(&G);
106 }
107 for (auto &F : M) {
108 classifyFunctionType(F, Map);
109
110 for (const auto &B : F) {
111 for (const auto &I : B) {
112 if (I.getType()->isOpaquePointerTy())
113 Map[&I] = classifyPointerType(&I);
114 }
115 }
116 }
117
118 return Map;
119 }
120