// Copyright 2019 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef rr_LLVMReactor_hpp #define rr_LLVMReactor_hpp #include "Nucleus.hpp" #include "Debug.hpp" #include "LLVMReactorDebugInfo.hpp" #include "Print.hpp" #ifdef _MSC_VER __pragma(warning(push)) __pragma(warning(disable : 4146)) // unary minus operator applied to unsigned type, result still unsigned #endif #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #ifdef _MSC_VER __pragma(warning(pop)) #endif #include namespace llvm { class Type; class Value; } // namespace llvm namespace rr { class Type; class Value; llvm::Type *T(Type *t); inline Type *T(llvm::Type *t) { return reinterpret_cast(t); } inline llvm::Value *V(Value *t) { return reinterpret_cast(t); } inline Value *V(llvm::Value *t) { return reinterpret_cast(t); } inline std::vector V(const std::vector &values) { std::vector result; result.reserve(values.size()); for(auto &v : values) { result.push_back(V(v)); } return result; } // Emits a no-op instruction that will not be optimized away. // Useful for emitting something that can have a source location without // effect. void Nop(); class Routine; class Config; // JITBuilder holds all the LLVM state for building routines. class JITBuilder { public: JITBuilder(const rr::Config &config); void optimize(const rr::Config &cfg); std::shared_ptr acquireRoutine(llvm::Function **funcs, size_t count, const rr::Config &cfg); const Config config; llvm::LLVMContext context; std::unique_ptr module; std::unique_ptr> builder; llvm::Function *function = nullptr; struct CoroutineState { llvm::Function *await = nullptr; llvm::Function *destroy = nullptr; llvm::Value *handle = nullptr; llvm::Value *id = nullptr; llvm::Value *promise = nullptr; llvm::Type *yieldType = nullptr; llvm::BasicBlock *entryBlock = nullptr; llvm::BasicBlock *suspendBlock = nullptr; llvm::BasicBlock *endBlock = nullptr; llvm::BasicBlock *destroyBlock = nullptr; }; CoroutineState coroutine; #ifdef ENABLE_RR_DEBUG_INFO std::unique_ptr debugInfo; #endif }; inline std::memory_order atomicOrdering(llvm::AtomicOrdering memoryOrder) { switch(memoryOrder) { case llvm::AtomicOrdering::Monotonic: return std::memory_order_relaxed; // https://llvm.org/docs/Atomics.html#monotonic case llvm::AtomicOrdering::Acquire: return std::memory_order_acquire; case llvm::AtomicOrdering::Release: return std::memory_order_release; case llvm::AtomicOrdering::AcquireRelease: return std::memory_order_acq_rel; case llvm::AtomicOrdering::SequentiallyConsistent: return std::memory_order_seq_cst; default: UNREACHABLE("memoryOrder: %d", int(memoryOrder)); return std::memory_order_acq_rel; } } inline llvm::AtomicOrdering atomicOrdering(bool atomic, std::memory_order memoryOrder) { if(!atomic) { return llvm::AtomicOrdering::NotAtomic; } switch(memoryOrder) { case std::memory_order_relaxed: return llvm::AtomicOrdering::Monotonic; // https://llvm.org/docs/Atomics.html#monotonic 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." case std::memory_order_acquire: return llvm::AtomicOrdering::Acquire; case std::memory_order_release: return llvm::AtomicOrdering::Release; case std::memory_order_acq_rel: return llvm::AtomicOrdering::AcquireRelease; case std::memory_order_seq_cst: return llvm::AtomicOrdering::SequentiallyConsistent; default: UNREACHABLE("memoryOrder: %d", int(memoryOrder)); return llvm::AtomicOrdering::AcquireRelease; } } } // namespace rr #endif // rr_LLVMReactor_hpp