xref: /aosp_15_r20/external/swiftshader/src/Reactor/LLVMReactor.hpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //  http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #ifndef rr_LLVMReactor_hpp
16*03ce13f7SAndroid Build Coastguard Worker #define rr_LLVMReactor_hpp
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "Nucleus.hpp"
19*03ce13f7SAndroid Build Coastguard Worker 
20*03ce13f7SAndroid Build Coastguard Worker #include "Debug.hpp"
21*03ce13f7SAndroid Build Coastguard Worker #include "LLVMReactorDebugInfo.hpp"
22*03ce13f7SAndroid Build Coastguard Worker #include "Print.hpp"
23*03ce13f7SAndroid Build Coastguard Worker 
24*03ce13f7SAndroid Build Coastguard Worker #ifdef _MSC_VER
25*03ce13f7SAndroid Build Coastguard Worker __pragma(warning(push))
26*03ce13f7SAndroid Build Coastguard Worker     __pragma(warning(disable : 4146))  // unary minus operator applied to unsigned type, result still unsigned
27*03ce13f7SAndroid Build Coastguard Worker #endif
28*03ce13f7SAndroid Build Coastguard Worker 
29*03ce13f7SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
30*03ce13f7SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
31*03ce13f7SAndroid Build Coastguard Worker 
32*03ce13f7SAndroid Build Coastguard Worker #ifdef _MSC_VER
33*03ce13f7SAndroid Build Coastguard Worker     __pragma(warning(pop))
34*03ce13f7SAndroid Build Coastguard Worker #endif
35*03ce13f7SAndroid Build Coastguard Worker 
36*03ce13f7SAndroid Build Coastguard Worker #include <memory>
37*03ce13f7SAndroid Build Coastguard Worker 
38*03ce13f7SAndroid Build Coastguard Worker         namespace llvm
39*03ce13f7SAndroid Build Coastguard Worker {
40*03ce13f7SAndroid Build Coastguard Worker 
41*03ce13f7SAndroid Build Coastguard Worker 	class Type;
42*03ce13f7SAndroid Build Coastguard Worker 	class Value;
43*03ce13f7SAndroid Build Coastguard Worker 
44*03ce13f7SAndroid Build Coastguard Worker }  // namespace llvm
45*03ce13f7SAndroid Build Coastguard Worker 
46*03ce13f7SAndroid Build Coastguard Worker namespace rr {
47*03ce13f7SAndroid Build Coastguard Worker 
48*03ce13f7SAndroid Build Coastguard Worker class Type;
49*03ce13f7SAndroid Build Coastguard Worker class Value;
50*03ce13f7SAndroid Build Coastguard Worker 
51*03ce13f7SAndroid Build Coastguard Worker llvm::Type *T(Type *t);
52*03ce13f7SAndroid Build Coastguard Worker 
T(llvm::Type * t)53*03ce13f7SAndroid Build Coastguard Worker inline Type *T(llvm::Type *t)
54*03ce13f7SAndroid Build Coastguard Worker {
55*03ce13f7SAndroid Build Coastguard Worker 	return reinterpret_cast<Type *>(t);
56*03ce13f7SAndroid Build Coastguard Worker }
57*03ce13f7SAndroid Build Coastguard Worker 
V(Value * t)58*03ce13f7SAndroid Build Coastguard Worker inline llvm::Value *V(Value *t)
59*03ce13f7SAndroid Build Coastguard Worker {
60*03ce13f7SAndroid Build Coastguard Worker 	return reinterpret_cast<llvm::Value *>(t);
61*03ce13f7SAndroid Build Coastguard Worker }
62*03ce13f7SAndroid Build Coastguard Worker 
V(llvm::Value * t)63*03ce13f7SAndroid Build Coastguard Worker inline Value *V(llvm::Value *t)
64*03ce13f7SAndroid Build Coastguard Worker {
65*03ce13f7SAndroid Build Coastguard Worker 	return reinterpret_cast<Value *>(t);
66*03ce13f7SAndroid Build Coastguard Worker }
67*03ce13f7SAndroid Build Coastguard Worker 
V(const std::vector<Value * > & values)68*03ce13f7SAndroid Build Coastguard Worker inline std::vector<llvm::Value *> V(const std::vector<Value *> &values)
69*03ce13f7SAndroid Build Coastguard Worker {
70*03ce13f7SAndroid Build Coastguard Worker 	std::vector<llvm::Value *> result;
71*03ce13f7SAndroid Build Coastguard Worker 	result.reserve(values.size());
72*03ce13f7SAndroid Build Coastguard Worker 	for(auto &v : values)
73*03ce13f7SAndroid Build Coastguard Worker 	{
74*03ce13f7SAndroid Build Coastguard Worker 		result.push_back(V(v));
75*03ce13f7SAndroid Build Coastguard Worker 	}
76*03ce13f7SAndroid Build Coastguard Worker 	return result;
77*03ce13f7SAndroid Build Coastguard Worker }
78*03ce13f7SAndroid Build Coastguard Worker 
79*03ce13f7SAndroid Build Coastguard Worker // Emits a no-op instruction that will not be optimized away.
80*03ce13f7SAndroid Build Coastguard Worker // Useful for emitting something that can have a source location without
81*03ce13f7SAndroid Build Coastguard Worker // effect.
82*03ce13f7SAndroid Build Coastguard Worker void Nop();
83*03ce13f7SAndroid Build Coastguard Worker 
84*03ce13f7SAndroid Build Coastguard Worker class Routine;
85*03ce13f7SAndroid Build Coastguard Worker 
86*03ce13f7SAndroid Build Coastguard Worker // JITBuilder holds all the LLVM state for building routines.
87*03ce13f7SAndroid Build Coastguard Worker class JITBuilder
88*03ce13f7SAndroid Build Coastguard Worker {
89*03ce13f7SAndroid Build Coastguard Worker public:
90*03ce13f7SAndroid Build Coastguard Worker 	JITBuilder();
91*03ce13f7SAndroid Build Coastguard Worker 
92*03ce13f7SAndroid Build Coastguard Worker 	void runPasses();
93*03ce13f7SAndroid Build Coastguard Worker 
94*03ce13f7SAndroid Build Coastguard Worker 	std::shared_ptr<rr::Routine> acquireRoutine(const char *name, llvm::Function **funcs, size_t count);
95*03ce13f7SAndroid Build Coastguard Worker 
96*03ce13f7SAndroid Build Coastguard Worker 	std::unique_ptr<llvm::LLVMContext> context;
97*03ce13f7SAndroid Build Coastguard Worker 	std::unique_ptr<llvm::Module> module;
98*03ce13f7SAndroid Build Coastguard Worker 	std::unique_ptr<llvm::IRBuilder<>> builder;
99*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *function = nullptr;
100*03ce13f7SAndroid Build Coastguard Worker 
101*03ce13f7SAndroid Build Coastguard Worker 	struct CoroutineState
102*03ce13f7SAndroid Build Coastguard Worker 	{
103*03ce13f7SAndroid Build Coastguard Worker 		llvm::Function *await = nullptr;
104*03ce13f7SAndroid Build Coastguard Worker 		llvm::Function *destroy = nullptr;
105*03ce13f7SAndroid Build Coastguard Worker 		llvm::Value *handle = nullptr;
106*03ce13f7SAndroid Build Coastguard Worker 		llvm::Value *id = nullptr;
107*03ce13f7SAndroid Build Coastguard Worker 		llvm::Value *promise = nullptr;
108*03ce13f7SAndroid Build Coastguard Worker 		llvm::Type *yieldType = nullptr;
109*03ce13f7SAndroid Build Coastguard Worker 		llvm::BasicBlock *entryBlock = nullptr;
110*03ce13f7SAndroid Build Coastguard Worker 		llvm::BasicBlock *suspendBlock = nullptr;
111*03ce13f7SAndroid Build Coastguard Worker 		llvm::BasicBlock *endBlock = nullptr;
112*03ce13f7SAndroid Build Coastguard Worker 		llvm::BasicBlock *destroyBlock = nullptr;
113*03ce13f7SAndroid Build Coastguard Worker 	};
114*03ce13f7SAndroid Build Coastguard Worker 	CoroutineState coroutine;
115*03ce13f7SAndroid Build Coastguard Worker 
116*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
117*03ce13f7SAndroid Build Coastguard Worker 	std::unique_ptr<rr::DebugInfo> debugInfo;
118*03ce13f7SAndroid Build Coastguard Worker #endif
119*03ce13f7SAndroid Build Coastguard Worker 
120*03ce13f7SAndroid Build Coastguard Worker 	bool msanInstrumentation = false;
121*03ce13f7SAndroid Build Coastguard Worker };
122*03ce13f7SAndroid Build Coastguard Worker 
atomicOrdering(llvm::AtomicOrdering memoryOrder)123*03ce13f7SAndroid Build Coastguard Worker inline std::memory_order atomicOrdering(llvm::AtomicOrdering memoryOrder)
124*03ce13f7SAndroid Build Coastguard Worker {
125*03ce13f7SAndroid Build Coastguard Worker 	switch(memoryOrder)
126*03ce13f7SAndroid Build Coastguard Worker 	{
127*03ce13f7SAndroid Build Coastguard Worker 	case llvm::AtomicOrdering::Monotonic: return std::memory_order_relaxed;  // https://llvm.org/docs/Atomics.html#monotonic
128*03ce13f7SAndroid Build Coastguard Worker 	case llvm::AtomicOrdering::Acquire: return std::memory_order_acquire;
129*03ce13f7SAndroid Build Coastguard Worker 	case llvm::AtomicOrdering::Release: return std::memory_order_release;
130*03ce13f7SAndroid Build Coastguard Worker 	case llvm::AtomicOrdering::AcquireRelease: return std::memory_order_acq_rel;
131*03ce13f7SAndroid Build Coastguard Worker 	case llvm::AtomicOrdering::SequentiallyConsistent: return std::memory_order_seq_cst;
132*03ce13f7SAndroid Build Coastguard Worker 	default:
133*03ce13f7SAndroid Build Coastguard Worker 		UNREACHABLE("memoryOrder: %d", int(memoryOrder));
134*03ce13f7SAndroid Build Coastguard Worker 		return std::memory_order_acq_rel;
135*03ce13f7SAndroid Build Coastguard Worker 	}
136*03ce13f7SAndroid Build Coastguard Worker }
137*03ce13f7SAndroid Build Coastguard Worker 
atomicOrdering(bool atomic,std::memory_order memoryOrder)138*03ce13f7SAndroid Build Coastguard Worker inline llvm::AtomicOrdering atomicOrdering(bool atomic, std::memory_order memoryOrder)
139*03ce13f7SAndroid Build Coastguard Worker {
140*03ce13f7SAndroid Build Coastguard Worker 	if(!atomic)
141*03ce13f7SAndroid Build Coastguard Worker 	{
142*03ce13f7SAndroid Build Coastguard Worker 		return llvm::AtomicOrdering::NotAtomic;
143*03ce13f7SAndroid Build Coastguard Worker 	}
144*03ce13f7SAndroid Build Coastguard Worker 
145*03ce13f7SAndroid Build Coastguard Worker 	switch(memoryOrder)
146*03ce13f7SAndroid Build Coastguard Worker 	{
147*03ce13f7SAndroid Build Coastguard Worker 	case std::memory_order_relaxed: return llvm::AtomicOrdering::Monotonic;  // https://llvm.org/docs/Atomics.html#monotonic
148*03ce13f7SAndroid Build Coastguard Worker 	case std::memory_order_consume: return llvm::AtomicOrdering::Acquire;    // https://llvm.org/docs/Atomics.html#acquire: "It should also be used for C++11/C11 memory_order_consume."
149*03ce13f7SAndroid Build Coastguard Worker 	case std::memory_order_acquire: return llvm::AtomicOrdering::Acquire;
150*03ce13f7SAndroid Build Coastguard Worker 	case std::memory_order_release: return llvm::AtomicOrdering::Release;
151*03ce13f7SAndroid Build Coastguard Worker 	case std::memory_order_acq_rel: return llvm::AtomicOrdering::AcquireRelease;
152*03ce13f7SAndroid Build Coastguard Worker 	case std::memory_order_seq_cst: return llvm::AtomicOrdering::SequentiallyConsistent;
153*03ce13f7SAndroid Build Coastguard Worker 	default:
154*03ce13f7SAndroid Build Coastguard Worker 		UNREACHABLE("memoryOrder: %d", int(memoryOrder));
155*03ce13f7SAndroid Build Coastguard Worker 		return llvm::AtomicOrdering::AcquireRelease;
156*03ce13f7SAndroid Build Coastguard Worker 	}
157*03ce13f7SAndroid Build Coastguard Worker }
158*03ce13f7SAndroid Build Coastguard Worker 
159*03ce13f7SAndroid Build Coastguard Worker }  // namespace rr
160*03ce13f7SAndroid Build Coastguard Worker 
161*03ce13f7SAndroid Build Coastguard Worker #endif  // rr_LLVMReactor_hpp
162