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