1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2016 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_Nucleus_hpp 16*03ce13f7SAndroid Build Coastguard Worker #define rr_Nucleus_hpp 17*03ce13f7SAndroid Build Coastguard Worker 18*03ce13f7SAndroid Build Coastguard Worker #include <atomic> 19*03ce13f7SAndroid Build Coastguard Worker #include <cassert> 20*03ce13f7SAndroid Build Coastguard Worker #include <cstdarg> 21*03ce13f7SAndroid Build Coastguard Worker #include <cstdint> 22*03ce13f7SAndroid Build Coastguard Worker #include <functional> 23*03ce13f7SAndroid Build Coastguard Worker #include <memory> 24*03ce13f7SAndroid Build Coastguard Worker #include <string> 25*03ce13f7SAndroid Build Coastguard Worker #include <vector> 26*03ce13f7SAndroid Build Coastguard Worker 27*03ce13f7SAndroid Build Coastguard Worker #ifdef None 28*03ce13f7SAndroid Build Coastguard Worker # undef None // TODO(b/127920555) 29*03ce13f7SAndroid Build Coastguard Worker #endif 30*03ce13f7SAndroid Build Coastguard Worker 31*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(short) == 2, "Reactor's 'Short' type is 16-bit, and requires the C++ 'short' to match that."); 32*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(int) == 4, "Reactor's 'Int' type is 32-bit, and requires the C++ 'int' to match that."); 33*03ce13f7SAndroid Build Coastguard Worker 34*03ce13f7SAndroid Build Coastguard Worker namespace rr { 35*03ce13f7SAndroid Build Coastguard Worker 36*03ce13f7SAndroid Build Coastguard Worker class Type; 37*03ce13f7SAndroid Build Coastguard Worker class Value; 38*03ce13f7SAndroid Build Coastguard Worker class SwitchCases; 39*03ce13f7SAndroid Build Coastguard Worker class BasicBlock; 40*03ce13f7SAndroid Build Coastguard Worker class Routine; 41*03ce13f7SAndroid Build Coastguard Worker 42*03ce13f7SAndroid Build Coastguard Worker class Nucleus 43*03ce13f7SAndroid Build Coastguard Worker { 44*03ce13f7SAndroid Build Coastguard Worker public: 45*03ce13f7SAndroid Build Coastguard Worker Nucleus(); 46*03ce13f7SAndroid Build Coastguard Worker 47*03ce13f7SAndroid Build Coastguard Worker virtual ~Nucleus(); 48*03ce13f7SAndroid Build Coastguard Worker 49*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Routine> acquireRoutine(const char *name); 50*03ce13f7SAndroid Build Coastguard Worker 51*03ce13f7SAndroid Build Coastguard Worker static Value *allocateStackVariable(Type *type, int arraySize = 0); 52*03ce13f7SAndroid Build Coastguard Worker static BasicBlock *createBasicBlock(); 53*03ce13f7SAndroid Build Coastguard Worker static BasicBlock *getInsertBlock(); 54*03ce13f7SAndroid Build Coastguard Worker static void setInsertBlock(BasicBlock *basicBlock); 55*03ce13f7SAndroid Build Coastguard Worker 56*03ce13f7SAndroid Build Coastguard Worker static void createFunction(Type *returnType, const std::vector<Type *> ¶mTypes); 57*03ce13f7SAndroid Build Coastguard Worker static Value *getArgument(unsigned int index); 58*03ce13f7SAndroid Build Coastguard Worker 59*03ce13f7SAndroid Build Coastguard Worker // Coroutines 60*03ce13f7SAndroid Build Coastguard Worker using CoroutineHandle = void *; 61*03ce13f7SAndroid Build Coastguard Worker 62*03ce13f7SAndroid Build Coastguard Worker template<typename... ARGS> 63*03ce13f7SAndroid Build Coastguard Worker using CoroutineBegin = CoroutineHandle(ARGS...); 64*03ce13f7SAndroid Build Coastguard Worker using CoroutineAwait = bool(CoroutineHandle, void *yieldValue); 65*03ce13f7SAndroid Build Coastguard Worker using CoroutineDestroy = void(CoroutineHandle); 66*03ce13f7SAndroid Build Coastguard Worker 67*03ce13f7SAndroid Build Coastguard Worker enum CoroutineEntries 68*03ce13f7SAndroid Build Coastguard Worker { 69*03ce13f7SAndroid Build Coastguard Worker CoroutineEntryBegin = 0, 70*03ce13f7SAndroid Build Coastguard Worker CoroutineEntryAwait, 71*03ce13f7SAndroid Build Coastguard Worker CoroutineEntryDestroy, 72*03ce13f7SAndroid Build Coastguard Worker CoroutineEntryCount 73*03ce13f7SAndroid Build Coastguard Worker }; 74*03ce13f7SAndroid Build Coastguard Worker 75*03ce13f7SAndroid Build Coastguard Worker // Begins the generation of the three coroutine functions: CoroutineBegin, CoroutineAwait, and CoroutineDestroy, 76*03ce13f7SAndroid Build Coastguard Worker // which will be returned by Routine::getEntry() with arg CoroutineEntryBegin, CoroutineEntryAwait, and CoroutineEntryDestroy 77*03ce13f7SAndroid Build Coastguard Worker // respectively. Called by Coroutine constructor. 78*03ce13f7SAndroid Build Coastguard Worker // Params are used to generate the params to CoroutineBegin, while ReturnType is used as the YieldType for the coroutine, 79*03ce13f7SAndroid Build Coastguard Worker // returned via CoroutineAwait.. 80*03ce13f7SAndroid Build Coastguard Worker static void createCoroutine(Type *returnType, const std::vector<Type *> ¶ms); 81*03ce13f7SAndroid Build Coastguard Worker // Generates code to store the passed in value, and to suspend execution of the coroutine, such that the next call to 82*03ce13f7SAndroid Build Coastguard Worker // CoroutineAwait can set the output yieldValue and resume execution of the coroutine. 83*03ce13f7SAndroid Build Coastguard Worker static void yield(Value *val); 84*03ce13f7SAndroid Build Coastguard Worker // Called to finalize coroutine creation. After this call, Routine::getEntry can be called to retrieve the entry point to any 85*03ce13f7SAndroid Build Coastguard Worker // of the three coroutine functions. Called by Coroutine::finalize. 86*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Routine> acquireCoroutine(const char *name); 87*03ce13f7SAndroid Build Coastguard Worker // Called by Coroutine::operator() to execute CoroutineEntryBegin wrapped up in func. This is needed in case 88*03ce13f7SAndroid Build Coastguard Worker // the call must be run on a separate thread of execution (e.g. on a fiber). 89*03ce13f7SAndroid Build Coastguard Worker static CoroutineHandle invokeCoroutineBegin(Routine &routine, std::function<CoroutineHandle()> func); 90*03ce13f7SAndroid Build Coastguard Worker 91*03ce13f7SAndroid Build Coastguard Worker // Terminators 92*03ce13f7SAndroid Build Coastguard Worker static void createRetVoid(); 93*03ce13f7SAndroid Build Coastguard Worker static void createRet(Value *V); 94*03ce13f7SAndroid Build Coastguard Worker static void createBr(BasicBlock *dest); 95*03ce13f7SAndroid Build Coastguard Worker static void createCondBr(Value *cond, BasicBlock *ifTrue, BasicBlock *ifFalse); 96*03ce13f7SAndroid Build Coastguard Worker 97*03ce13f7SAndroid Build Coastguard Worker // Binary operators 98*03ce13f7SAndroid Build Coastguard Worker static Value *createAdd(Value *lhs, Value *rhs); 99*03ce13f7SAndroid Build Coastguard Worker static Value *createSub(Value *lhs, Value *rhs); 100*03ce13f7SAndroid Build Coastguard Worker static Value *createMul(Value *lhs, Value *rhs); 101*03ce13f7SAndroid Build Coastguard Worker static Value *createUDiv(Value *lhs, Value *rhs); 102*03ce13f7SAndroid Build Coastguard Worker static Value *createSDiv(Value *lhs, Value *rhs); 103*03ce13f7SAndroid Build Coastguard Worker static Value *createFAdd(Value *lhs, Value *rhs); 104*03ce13f7SAndroid Build Coastguard Worker static Value *createFSub(Value *lhs, Value *rhs); 105*03ce13f7SAndroid Build Coastguard Worker static Value *createFMul(Value *lhs, Value *rhs); 106*03ce13f7SAndroid Build Coastguard Worker static Value *createFDiv(Value *lhs, Value *rhs); 107*03ce13f7SAndroid Build Coastguard Worker static Value *createURem(Value *lhs, Value *rhs); 108*03ce13f7SAndroid Build Coastguard Worker static Value *createSRem(Value *lhs, Value *rhs); 109*03ce13f7SAndroid Build Coastguard Worker static Value *createFRem(Value *lhs, Value *rhs); 110*03ce13f7SAndroid Build Coastguard Worker static Value *createShl(Value *lhs, Value *rhs); 111*03ce13f7SAndroid Build Coastguard Worker static Value *createLShr(Value *lhs, Value *rhs); 112*03ce13f7SAndroid Build Coastguard Worker static Value *createAShr(Value *lhs, Value *rhs); 113*03ce13f7SAndroid Build Coastguard Worker static Value *createAnd(Value *lhs, Value *rhs); 114*03ce13f7SAndroid Build Coastguard Worker static Value *createOr(Value *lhs, Value *rhs); 115*03ce13f7SAndroid Build Coastguard Worker static Value *createXor(Value *lhs, Value *rhs); 116*03ce13f7SAndroid Build Coastguard Worker 117*03ce13f7SAndroid Build Coastguard Worker // Unary operators 118*03ce13f7SAndroid Build Coastguard Worker static Value *createNeg(Value *V); 119*03ce13f7SAndroid Build Coastguard Worker static Value *createFNeg(Value *V); 120*03ce13f7SAndroid Build Coastguard Worker static Value *createNot(Value *V); 121*03ce13f7SAndroid Build Coastguard Worker 122*03ce13f7SAndroid Build Coastguard Worker // Memory instructions 123*03ce13f7SAndroid Build Coastguard Worker static Value *createLoad(Value *ptr, Type *type, bool isVolatile = false, unsigned int alignment = 0, bool atomic = false, std::memory_order memoryOrder = std::memory_order_relaxed); 124*03ce13f7SAndroid Build Coastguard Worker static Value *createStore(Value *value, Value *ptr, Type *type, bool isVolatile = false, unsigned int aligment = 0, bool atomic = false, std::memory_order memoryOrder = std::memory_order_relaxed); 125*03ce13f7SAndroid Build Coastguard Worker static Value *createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex); 126*03ce13f7SAndroid Build Coastguard Worker 127*03ce13f7SAndroid Build Coastguard Worker // Masked Load / Store instructions 128*03ce13f7SAndroid Build Coastguard Worker static Value *createMaskedLoad(Value *base, Type *elementType, Value *mask, unsigned int alignment, bool zeroMaskedLanes); 129*03ce13f7SAndroid Build Coastguard Worker static void createMaskedStore(Value *base, Value *value, Value *mask, unsigned int alignment); 130*03ce13f7SAndroid Build Coastguard Worker 131*03ce13f7SAndroid Build Coastguard Worker // Barrier instructions 132*03ce13f7SAndroid Build Coastguard Worker static void createFence(std::memory_order memoryOrder); 133*03ce13f7SAndroid Build Coastguard Worker 134*03ce13f7SAndroid Build Coastguard Worker // Atomic instructions 135*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicAdd(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 136*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicSub(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 137*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicAnd(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 138*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicOr(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 139*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicXor(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 140*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicMin(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 141*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicMax(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 142*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicUMin(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 143*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicUMax(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 144*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicExchange(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed); 145*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicCompareExchange(Value *ptr, Value *value, Value *compare, std::memory_order memoryOrderEqual, std::memory_order memoryOrderUnequal); 146*03ce13f7SAndroid Build Coastguard Worker 147*03ce13f7SAndroid Build Coastguard Worker // Cast/Conversion Operators 148*03ce13f7SAndroid Build Coastguard Worker static Value *createTrunc(Value *V, Type *destType); 149*03ce13f7SAndroid Build Coastguard Worker static Value *createZExt(Value *V, Type *destType); 150*03ce13f7SAndroid Build Coastguard Worker static Value *createSExt(Value *V, Type *destType); 151*03ce13f7SAndroid Build Coastguard Worker static Value *createFPToUI(Value *V, Type *destType); 152*03ce13f7SAndroid Build Coastguard Worker static Value *createFPToSI(Value *V, Type *destType); 153*03ce13f7SAndroid Build Coastguard Worker static Value *createSIToFP(Value *V, Type *destType); 154*03ce13f7SAndroid Build Coastguard Worker static Value *createFPTrunc(Value *V, Type *destType); 155*03ce13f7SAndroid Build Coastguard Worker static Value *createFPExt(Value *V, Type *destType); 156*03ce13f7SAndroid Build Coastguard Worker static Value *createBitCast(Value *V, Type *destType); 157*03ce13f7SAndroid Build Coastguard Worker 158*03ce13f7SAndroid Build Coastguard Worker // Compare instructions 159*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpEQ(Value *lhs, Value *rhs); 160*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpNE(Value *lhs, Value *rhs); 161*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpUGT(Value *lhs, Value *rhs); 162*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpUGE(Value *lhs, Value *rhs); 163*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpULT(Value *lhs, Value *rhs); 164*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpULE(Value *lhs, Value *rhs); 165*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpSGT(Value *lhs, Value *rhs); 166*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpSGE(Value *lhs, Value *rhs); 167*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpSLT(Value *lhs, Value *rhs); 168*03ce13f7SAndroid Build Coastguard Worker static Value *createICmpSLE(Value *lhs, Value *rhs); 169*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpOEQ(Value *lhs, Value *rhs); 170*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpOGT(Value *lhs, Value *rhs); 171*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpOGE(Value *lhs, Value *rhs); 172*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpOLT(Value *lhs, Value *rhs); 173*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpOLE(Value *lhs, Value *rhs); 174*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpONE(Value *lhs, Value *rhs); 175*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpORD(Value *lhs, Value *rhs); 176*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpUNO(Value *lhs, Value *rhs); 177*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpUEQ(Value *lhs, Value *rhs); 178*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpUGT(Value *lhs, Value *rhs); 179*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpUGE(Value *lhs, Value *rhs); 180*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpULT(Value *lhs, Value *rhs); 181*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpULE(Value *lhs, Value *rhs); 182*03ce13f7SAndroid Build Coastguard Worker static Value *createFCmpUNE(Value *lhs, Value *rhs); 183*03ce13f7SAndroid Build Coastguard Worker 184*03ce13f7SAndroid Build Coastguard Worker // Vector instructions 185*03ce13f7SAndroid Build Coastguard Worker static Value *createExtractElement(Value *vector, Type *type, int index); 186*03ce13f7SAndroid Build Coastguard Worker static Value *createInsertElement(Value *vector, Value *element, int index); 187*03ce13f7SAndroid Build Coastguard Worker static Value *createShuffleVector(Value *V1, Value *V2, std::vector<int> select); 188*03ce13f7SAndroid Build Coastguard Worker 189*03ce13f7SAndroid Build Coastguard Worker // Other instructions 190*03ce13f7SAndroid Build Coastguard Worker static Value *createSelect(Value *C, Value *ifTrue, Value *ifFalse); 191*03ce13f7SAndroid Build Coastguard Worker static SwitchCases *createSwitch(Value *control, BasicBlock *defaultBranch, unsigned numCases); 192*03ce13f7SAndroid Build Coastguard Worker static void addSwitchCase(SwitchCases *switchCases, int label, BasicBlock *branch); 193*03ce13f7SAndroid Build Coastguard Worker static void createUnreachable(); 194*03ce13f7SAndroid Build Coastguard Worker 195*03ce13f7SAndroid Build Coastguard Worker // Constant values 196*03ce13f7SAndroid Build Coastguard Worker static Value *createNullValue(Type *type); 197*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantLong(int64_t i); 198*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantInt(int i); 199*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantInt(unsigned int i); 200*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantBool(bool b); 201*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantByte(signed char i); 202*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantByte(unsigned char i); 203*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantShort(short i); 204*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantShort(unsigned short i); 205*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantFloat(float x); 206*03ce13f7SAndroid Build Coastguard Worker static Value *createNullPointer(Type *type); 207*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantVector(std::vector<int64_t> constants, Type *type); 208*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantVector(std::vector<double> constants, Type *type); 209*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantString(const char *v); createConstantString(const std::string & v)210*03ce13f7SAndroid Build Coastguard Worker static Value *createConstantString(const std::string &v) { return createConstantString(v.c_str()); } 211*03ce13f7SAndroid Build Coastguard Worker 212*03ce13f7SAndroid Build Coastguard Worker static Type *getType(Value *value); 213*03ce13f7SAndroid Build Coastguard Worker static Type *getContainedType(Type *vectorType); 214*03ce13f7SAndroid Build Coastguard Worker static Type *getPointerType(Type *elementType); 215*03ce13f7SAndroid Build Coastguard Worker static Type *getPrintfStorageType(Type *valueType); 216*03ce13f7SAndroid Build Coastguard Worker 217*03ce13f7SAndroid Build Coastguard Worker // Diagnostic utilities 218*03ce13f7SAndroid Build Coastguard Worker struct OptimizerReport 219*03ce13f7SAndroid Build Coastguard Worker { 220*03ce13f7SAndroid Build Coastguard Worker int allocas = 0; 221*03ce13f7SAndroid Build Coastguard Worker int loads = 0; 222*03ce13f7SAndroid Build Coastguard Worker int stores = 0; 223*03ce13f7SAndroid Build Coastguard Worker }; 224*03ce13f7SAndroid Build Coastguard Worker 225*03ce13f7SAndroid Build Coastguard Worker using OptimizerCallback = void(const OptimizerReport *report); 226*03ce13f7SAndroid Build Coastguard Worker 227*03ce13f7SAndroid Build Coastguard Worker // Sets the callback to be used by the next optimizer invocation (during acquireRoutine), 228*03ce13f7SAndroid Build Coastguard Worker // for reporting stats about the resulting IR code. For testing only. 229*03ce13f7SAndroid Build Coastguard Worker static void setOptimizerCallback(OptimizerCallback *callback); 230*03ce13f7SAndroid Build Coastguard Worker }; 231*03ce13f7SAndroid Build Coastguard Worker 232*03ce13f7SAndroid Build Coastguard Worker } // namespace rr 233*03ce13f7SAndroid Build Coastguard Worker 234*03ce13f7SAndroid Build Coastguard Worker #endif // rr_Nucleus_hpp 235