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