HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Pie
|
9.0.0_r8
下载
查看原文件
收藏
根目录
external
swiftshader
src
Reactor
LLVMReactor.cpp
// Copyright 2016 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. #include "Reactor.hpp" #include "llvm/Support/IRBuilder.h" #include "llvm/Function.h" #include "llvm/GlobalVariable.h" #include "llvm/Module.h" #include "llvm/LLVMContext.h" #include "llvm/Constants.h" #include "llvm/Intrinsics.h" #include "llvm/PassManager.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/TargetSelect.h" #include "../lib/ExecutionEngine/JIT/JIT.h" #include "LLVMRoutine.hpp" #include "LLVMRoutineManager.hpp" #include "x86.hpp" #include "Common/CPUID.hpp" #include "Common/Thread.hpp" #include "Common/Memory.hpp" #include "Common/MutexLock.hpp" #include
#if defined(__i386__) || defined(__x86_64__) #include
#endif #if defined(__x86_64__) && defined(_WIN32) extern "C" void X86CompilationCallback() { assert(false); // UNIMPLEMENTED } #endif extern "C" { bool (*CodeAnalystInitialize)() = 0; void (*CodeAnalystCompleteJITLog)() = 0; bool (*CodeAnalystLogJITCode)(const void *jitCodeStartAddr, unsigned int jitCodeSize, const wchar_t *functionName) = 0; } namespace llvm { extern bool JITEmitDebugInfo; } namespace { sw::LLVMRoutineManager *routineManager = nullptr; llvm::ExecutionEngine *executionEngine = nullptr; llvm::IRBuilder<> *builder = nullptr; llvm::LLVMContext *context = nullptr; llvm::Module *module = nullptr; llvm::Function *function = nullptr; sw::MutexLock codegenMutex; } namespace sw { Optimization optimization[10] = {InstructionCombining, Disabled}; enum EmulatedType { Type_v2i32, Type_v4i16, Type_v2i16, Type_v8i8, Type_v4i8, Type_v2f32, EmulatedTypeCount }; class Value : public llvm::Value {}; class SwitchCases : public llvm::SwitchInst {}; class BasicBlock : public llvm::BasicBlock {}; llvm::Type *T(Type *t) { uintptr_t type = reinterpret_cast
(t); if(type < EmulatedTypeCount) { // Use 128-bit vectors to implement logically shorter ones. switch(type) { case Type_v2i32: return T(Int4::getType()); case Type_v4i16: return T(Short8::getType()); case Type_v2i16: return T(Short8::getType()); case Type_v8i8: return T(Byte16::getType()); case Type_v4i8: return T(Byte16::getType()); case Type_v2f32: return T(Float4::getType()); default: assert(false); } } return reinterpret_cast
(t); } inline Type *T(llvm::Type *t) { return reinterpret_cast
(t); } Type *T(EmulatedType t) { return reinterpret_cast
(t); } inline Value *V(llvm::Value *t) { return reinterpret_cast
(t); } inline std::vector
&T(std::vector
&t) { return reinterpret_cast
&>(t); } inline BasicBlock *B(llvm::BasicBlock *t) { return reinterpret_cast
(t); } static size_t typeSize(Type *type) { uintptr_t t = reinterpret_cast
(type); if(t < EmulatedTypeCount) { switch(t) { case Type_v2i32: return 8; case Type_v4i16: return 8; case Type_v2i16: return 4; case Type_v8i8: return 8; case Type_v4i8: return 4; case Type_v2f32: return 8; default: assert(false); } } return T(type)->getPrimitiveSizeInBits() / 8; } static unsigned int elementCount(Type *type) { uintptr_t t = reinterpret_cast
(type); if(t < EmulatedTypeCount) { switch(t) { case Type_v2i32: return 2; case Type_v4i16: return 4; case Type_v2i16: return 2; case Type_v8i8: return 8; case Type_v4i8: return 4; case Type_v2f32: return 2; default: assert(false); } } return llvm::cast
(T(type))->getNumElements(); } Nucleus::Nucleus() { ::codegenMutex.lock(); // Reactor and LLVM are currently not thread safe llvm::InitializeNativeTarget(); llvm::JITEmitDebugInfo = false; if(!::context) { ::context = new llvm::LLVMContext(); } ::module = new llvm::Module("", *::context); ::routineManager = new LLVMRoutineManager(); #if defined(__x86_64__) const char *architecture = "x86-64"; #else const char *architecture = "x86"; #endif llvm::SmallVector
MAttrs; MAttrs.push_back(CPUID::supportsMMX() ? "+mmx" : "-mmx"); MAttrs.push_back(CPUID::supportsCMOV() ? "+cmov" : "-cmov"); MAttrs.push_back(CPUID::supportsSSE() ? "+sse" : "-sse"); MAttrs.push_back(CPUID::supportsSSE2() ? "+sse2" : "-sse2"); MAttrs.push_back(CPUID::supportsSSE3() ? "+sse3" : "-sse3"); MAttrs.push_back(CPUID::supportsSSSE3() ? "+ssse3" : "-ssse3"); MAttrs.push_back(CPUID::supportsSSE4_1() ? "+sse41" : "-sse41"); std::string error; llvm::TargetMachine *targetMachine = llvm::EngineBuilder::selectTarget(::module, architecture, "", MAttrs, llvm::Reloc::Default, llvm::CodeModel::JITDefault, &error); ::executionEngine = llvm::JIT::createJIT(::module, 0, ::routineManager, llvm::CodeGenOpt::Aggressive, true, targetMachine); if(!::builder) { ::builder = new llvm::IRBuilder<>(*::context); #if defined(_WIN32) HMODULE CodeAnalyst = LoadLibrary("CAJitNtfyLib.dll"); if(CodeAnalyst) { CodeAnalystInitialize = (bool(*)())GetProcAddress(CodeAnalyst, "CAJIT_Initialize"); CodeAnalystCompleteJITLog = (void(*)())GetProcAddress(CodeAnalyst, "CAJIT_CompleteJITLog"); CodeAnalystLogJITCode = (bool(*)(const void*, unsigned int, const wchar_t*))GetProcAddress(CodeAnalyst, "CAJIT_LogJITCode"); CodeAnalystInitialize(); } #endif } } Nucleus::~Nucleus() { delete ::executionEngine; ::executionEngine = nullptr; ::routineManager = nullptr; ::function = nullptr; ::module = nullptr; ::codegenMutex.unlock(); } Routine *Nucleus::acquireRoutine(const wchar_t *name, bool runOptimizations) { if(::builder->GetInsertBlock()->empty() || !::builder->GetInsertBlock()->back().isTerminator()) { llvm::Type *type = ::function->getReturnType(); if(type->isVoidTy()) { createRetVoid(); } else { createRet(V(llvm::UndefValue::get(type))); } } if(false) { std::string error; llvm::raw_fd_ostream file("llvm-dump-unopt.txt", error); ::module->print(file, 0); } if(runOptimizations) { optimize(); } if(false) { std::string error; llvm::raw_fd_ostream file("llvm-dump-opt.txt", error); ::module->print(file, 0); } void *entry = ::executionEngine->getPointerToFunction(::function); LLVMRoutine *routine = ::routineManager->acquireRoutine(entry); if(CodeAnalystLogJITCode) { CodeAnalystLogJITCode(routine->getEntry(), routine->getCodeSize(), name); } return routine; } void Nucleus::optimize() { static llvm::PassManager *passManager = nullptr; if(!passManager) { passManager = new llvm::PassManager(); llvm::UnsafeFPMath = true; // llvm::NoInfsFPMath = true; // llvm::NoNaNsFPMath = true; passManager->add(new llvm::TargetData(*::executionEngine->getTargetData())); passManager->add(llvm::createScalarReplAggregatesPass()); for(int pass = 0; pass < 10 && optimization[pass] != Disabled; pass++) { switch(optimization[pass]) { case Disabled: break; case CFGSimplification: passManager->add(llvm::createCFGSimplificationPass()); break; case LICM: passManager->add(llvm::createLICMPass()); break; case AggressiveDCE: passManager->add(llvm::createAggressiveDCEPass()); break; case GVN: passManager->add(llvm::createGVNPass()); break; case InstructionCombining: passManager->add(llvm::createInstructionCombiningPass()); break; case Reassociate: passManager->add(llvm::createReassociatePass()); break; case DeadStoreElimination: passManager->add(llvm::createDeadStoreEliminationPass()); break; case SCCP: passManager->add(llvm::createSCCPPass()); break; case ScalarReplAggregates: passManager->add(llvm::createScalarReplAggregatesPass()); break; default: assert(false); } } } passManager->run(*::module); } Value *Nucleus::allocateStackVariable(Type *type, int arraySize) { // Need to allocate it in the entry block for mem2reg to work llvm::BasicBlock &entryBlock = ::function->getEntryBlock(); llvm::Instruction *declaration; if(arraySize) { declaration = new llvm::AllocaInst(T(type), Nucleus::createConstantInt(arraySize)); } else { declaration = new llvm::AllocaInst(T(type), (Value*)nullptr); } entryBlock.getInstList().push_front(declaration); return V(declaration); } BasicBlock *Nucleus::createBasicBlock() { return B(BasicBlock::Create(*::context, "", ::function)); } BasicBlock *Nucleus::getInsertBlock() { return B(::builder->GetInsertBlock()); } void Nucleus::setInsertBlock(BasicBlock *basicBlock) { // assert(::builder->GetInsertBlock()->back().isTerminator()); return ::builder->SetInsertPoint(basicBlock); } void Nucleus::createFunction(Type *ReturnType, std::vector
&Params) { llvm::FunctionType *functionType = llvm::FunctionType::get(T(ReturnType), T(Params), false); ::function = llvm::Function::Create(functionType, llvm::GlobalValue::InternalLinkage, "", ::module); ::function->setCallingConv(llvm::CallingConv::C); ::builder->SetInsertPoint(BasicBlock::Create(*::context, "", ::function)); } Value *Nucleus::getArgument(unsigned int index) { llvm::Function::arg_iterator args = ::function->arg_begin(); while(index) { args++; index--; } return V(&*args); } void Nucleus::createRetVoid() { ::builder->CreateRetVoid(); } void Nucleus::createRet(Value *v) { ::builder->CreateRet(v); } void Nucleus::createBr(BasicBlock *dest) { ::builder->CreateBr(dest); } void Nucleus::createCondBr(Value *cond, BasicBlock *ifTrue, BasicBlock *ifFalse) { ::builder->CreateCondBr(cond, ifTrue, ifFalse); } Value *Nucleus::createAdd(Value *lhs, Value *rhs) { return V(::builder->CreateAdd(lhs, rhs)); } Value *Nucleus::createSub(Value *lhs, Value *rhs) { return V(::builder->CreateSub(lhs, rhs)); } Value *Nucleus::createMul(Value *lhs, Value *rhs) { return V(::builder->CreateMul(lhs, rhs)); } Value *Nucleus::createUDiv(Value *lhs, Value *rhs) { return V(::builder->CreateUDiv(lhs, rhs)); } Value *Nucleus::createSDiv(Value *lhs, Value *rhs) { return V(::builder->CreateSDiv(lhs, rhs)); } Value *Nucleus::createFAdd(Value *lhs, Value *rhs) { return V(::builder->CreateFAdd(lhs, rhs)); } Value *Nucleus::createFSub(Value *lhs, Value *rhs) { return V(::builder->CreateFSub(lhs, rhs)); } Value *Nucleus::createFMul(Value *lhs, Value *rhs) { return V(::builder->CreateFMul(lhs, rhs)); } Value *Nucleus::createFDiv(Value *lhs, Value *rhs) { return V(::builder->CreateFDiv(lhs, rhs)); } Value *Nucleus::createURem(Value *lhs, Value *rhs) { return V(::builder->CreateURem(lhs, rhs)); } Value *Nucleus::createSRem(Value *lhs, Value *rhs) { return V(::builder->CreateSRem(lhs, rhs)); } Value *Nucleus::createFRem(Value *lhs, Value *rhs) { return V(::builder->CreateFRem(lhs, rhs)); } Value *Nucleus::createShl(Value *lhs, Value *rhs) { return V(::builder->CreateShl(lhs, rhs)); } Value *Nucleus::createLShr(Value *lhs, Value *rhs) { return V(::builder->CreateLShr(lhs, rhs)); } Value *Nucleus::createAShr(Value *lhs, Value *rhs) { return V(::builder->CreateAShr(lhs, rhs)); } Value *Nucleus::createAnd(Value *lhs, Value *rhs) { return V(::builder->CreateAnd(lhs, rhs)); } Value *Nucleus::createOr(Value *lhs, Value *rhs) { return V(::builder->CreateOr(lhs, rhs)); } Value *Nucleus::createXor(Value *lhs, Value *rhs) { return V(::builder->CreateXor(lhs, rhs)); } Value *Nucleus::createNeg(Value *v) { return V(::builder->CreateNeg(v)); } Value *Nucleus::createFNeg(Value *v) { return V(::builder->CreateFNeg(v)); } Value *Nucleus::createNot(Value *v) { return V(::builder->CreateNot(v)); } Value *Nucleus::createLoad(Value *ptr, Type *type, bool isVolatile, unsigned int alignment) { uintptr_t t = reinterpret_cast
(type); if(t < EmulatedTypeCount) { switch(t) { case Type_v2i32: case Type_v4i16: case Type_v8i8: case Type_v2f32: return createBitCast(createInsertElement(V(llvm::UndefValue::get(llvm::VectorType::get(T(Long::getType()), 2))), createLoad(createBitCast(ptr, Pointer
::getType()), Long::getType(), isVolatile, alignment), 0), T(T(type))); case Type_v2i16: case Type_v4i8: if(alignment != 0) // Not a local variable (all vectors are 128-bit). { Value *u = V(llvm::UndefValue::get(llvm::VectorType::get(T(Long::getType()), 2))); Value *i = V(createLoad(createBitCast(ptr, Pointer
::getType()), Int::getType(), isVolatile, alignment)); i = createZExt(i, Long::getType()); Value *v = V(createInsertElement(u, i, 0)); return createBitCast(v, T(T(type))); } break; default: assert(false); } } assert(ptr->getType()->getContainedType(0) == T(type)); return V(::builder->Insert(new llvm::LoadInst(ptr, "", isVolatile, alignment))); } Value *Nucleus::createStore(Value *value, Value *ptr, Type *type, bool isVolatile, unsigned int alignment) { uintptr_t t = reinterpret_cast
(type); if(t < EmulatedTypeCount) { switch(t) { case Type_v2i32: case Type_v4i16: case Type_v8i8: case Type_v2f32: createStore(createExtractElement(createBitCast(value, T(llvm::VectorType::get(T(Long::getType()), 2))), Long::getType(), 0), createBitCast(ptr, Pointer
::getType()), Long::getType(), isVolatile, alignment); return value; case Type_v2i16: case Type_v4i8: if(alignment != 0) // Not a local variable (all vectors are 128-bit). { createStore(createExtractElement(createBitCast(value, Int4::getType()), Int::getType(), 0), createBitCast(ptr, Pointer
::getType()), Int::getType(), isVolatile, alignment); return value; } break; default: assert(false); } } assert(ptr->getType()->getContainedType(0) == T(type)); ::builder->Insert(new llvm::StoreInst(value, ptr, isVolatile, alignment)); return value; } Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex) { if(sizeof(void*) == 8) { if(unsignedIndex) { index = createZExt(index, Long::getType()); } else { index = createSExt(index, Long::getType()); } index = createMul(index, createConstantLong((int64_t)typeSize(type))); } else { index = createMul(index, createConstantInt((int)typeSize(type))); } assert(ptr->getType()->getContainedType(0) == T(type)); return createBitCast(V(::builder->CreateGEP(createBitCast(ptr, T(llvm::PointerType::get(T(Byte::getType()), 0))), index)), T(llvm::PointerType::get(T(type), 0))); } Value *Nucleus::createAtomicAdd(Value *ptr, Value *value) { return V(::builder->CreateAtomicRMW(llvm::AtomicRMWInst::Add, ptr, value, llvm::SequentiallyConsistent)); } Value *Nucleus::createTrunc(Value *v, Type *destType) { return V(::builder->CreateTrunc(v, T(destType))); } Value *Nucleus::createZExt(Value *v, Type *destType) { return V(::builder->CreateZExt(v, T(destType))); } Value *Nucleus::createSExt(Value *v, Type *destType) { return V(::builder->CreateSExt(v, T(destType))); } Value *Nucleus::createFPToSI(Value *v, Type *destType) { return V(::builder->CreateFPToSI(v, T(destType))); } Value *Nucleus::createSIToFP(Value *v, Type *destType) { return V(::builder->CreateSIToFP(v, T(destType))); } Value *Nucleus::createFPTrunc(Value *v, Type *destType) { return V(::builder->CreateFPTrunc(v, T(destType))); } Value *Nucleus::createFPExt(Value *v, Type *destType) { return V(::builder->CreateFPExt(v, T(destType))); } Value *Nucleus::createBitCast(Value *v, Type *destType) { // Bitcasts must be between types of the same logical size. But with emulated narrow vectors we need // support for casting between scalars and wide vectors. Emulate them by writing to the stack and // reading back as the destination type. if(!v->getType()->isVectorTy() && T(destType)->isVectorTy()) { Value *readAddress = allocateStackVariable(destType); Value *writeAddress = createBitCast(readAddress, T(llvm::PointerType::get(v->getType(), 0))); createStore(v, writeAddress, T(v->getType())); return createLoad(readAddress, destType); } else if(v->getType()->isVectorTy() && !T(destType)->isVectorTy()) { Value *writeAddress = allocateStackVariable(T(v->getType())); createStore(v, writeAddress, T(v->getType())); Value *readAddress = createBitCast(writeAddress, T(llvm::PointerType::get(T(destType), 0))); return createLoad(readAddress, destType); } return V(::builder->CreateBitCast(v, T(destType))); } Value *Nucleus::createICmpEQ(Value *lhs, Value *rhs) { return V(::builder->CreateICmpEQ(lhs, rhs)); } Value *Nucleus::createICmpNE(Value *lhs, Value *rhs) { return V(::builder->CreateICmpNE(lhs, rhs)); } Value *Nucleus::createICmpUGT(Value *lhs, Value *rhs) { return V(::builder->CreateICmpUGT(lhs, rhs)); } Value *Nucleus::createICmpUGE(Value *lhs, Value *rhs) { return V(::builder->CreateICmpUGE(lhs, rhs)); } Value *Nucleus::createICmpULT(Value *lhs, Value *rhs) { return V(::builder->CreateICmpULT(lhs, rhs)); } Value *Nucleus::createICmpULE(Value *lhs, Value *rhs) { return V(::builder->CreateICmpULE(lhs, rhs)); } Value *Nucleus::createICmpSGT(Value *lhs, Value *rhs) { return V(::builder->CreateICmpSGT(lhs, rhs)); } Value *Nucleus::createICmpSGE(Value *lhs, Value *rhs) { return V(::builder->CreateICmpSGE(lhs, rhs)); } Value *Nucleus::createICmpSLT(Value *lhs, Value *rhs) { return V(::builder->CreateICmpSLT(lhs, rhs)); } Value *Nucleus::createICmpSLE(Value *lhs, Value *rhs) { return V(::builder->CreateICmpSLE(lhs, rhs)); } Value *Nucleus::createFCmpOEQ(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpOEQ(lhs, rhs)); } Value *Nucleus::createFCmpOGT(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpOGT(lhs, rhs)); } Value *Nucleus::createFCmpOGE(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpOGE(lhs, rhs)); } Value *Nucleus::createFCmpOLT(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpOLT(lhs, rhs)); } Value *Nucleus::createFCmpOLE(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpOLE(lhs, rhs)); } Value *Nucleus::createFCmpONE(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpONE(lhs, rhs)); } Value *Nucleus::createFCmpORD(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpORD(lhs, rhs)); } Value *Nucleus::createFCmpUNO(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpUNO(lhs, rhs)); } Value *Nucleus::createFCmpUEQ(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpUEQ(lhs, rhs)); } Value *Nucleus::createFCmpUGT(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpUGT(lhs, rhs)); } Value *Nucleus::createFCmpUGE(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpUGE(lhs, rhs)); } Value *Nucleus::createFCmpULT(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpULT(lhs, rhs)); } Value *Nucleus::createFCmpULE(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpULE(lhs, rhs)); } Value *Nucleus::createFCmpUNE(Value *lhs, Value *rhs) { return V(::builder->CreateFCmpULE(lhs, rhs)); } Value *Nucleus::createExtractElement(Value *vector, Type *type, int index) { assert(vector->getType()->getContainedType(0) == T(type)); return V(::builder->CreateExtractElement(vector, createConstantInt(index))); } Value *Nucleus::createInsertElement(Value *vector, Value *element, int index) { return V(::builder->CreateInsertElement(vector, element, createConstantInt(index))); } Value *Nucleus::createShuffleVector(Value *V1, Value *V2, const int *select) { int size = llvm::cast
(V1->getType())->getNumElements(); const int maxSize = 16; llvm::Constant *swizzle[maxSize]; assert(size <= maxSize); for(int i = 0; i < size; i++) { swizzle[i] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(*::context), select[i]); } llvm::Value *shuffle = llvm::ConstantVector::get(llvm::ArrayRef
(swizzle, size)); return V(::builder->CreateShuffleVector(V1, V2, shuffle)); } Value *Nucleus::createSelect(Value *C, Value *ifTrue, Value *ifFalse) { return V(::builder->CreateSelect(C, ifTrue, ifFalse)); } SwitchCases *Nucleus::createSwitch(Value *control, BasicBlock *defaultBranch, unsigned numCases) { return reinterpret_cast
(::builder->CreateSwitch(control, defaultBranch, numCases)); } void Nucleus::addSwitchCase(SwitchCases *switchCases, int label, BasicBlock *branch) { switchCases->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*::context), label, true), branch); } void Nucleus::createUnreachable() { ::builder->CreateUnreachable(); } static Value *createSwizzle4(Value *val, unsigned char select) { int swizzle[4] = { (select >> 0) & 0x03, (select >> 2) & 0x03, (select >> 4) & 0x03, (select >> 6) & 0x03, }; return Nucleus::createShuffleVector(val, val, swizzle); } static Value *createMask4(Value *lhs, Value *rhs, unsigned char select) { bool mask[4] = {false, false, false, false}; mask[(select >> 0) & 0x03] = true; mask[(select >> 2) & 0x03] = true; mask[(select >> 4) & 0x03] = true; mask[(select >> 6) & 0x03] = true; int swizzle[4] = { mask[0] ? 4 : 0, mask[1] ? 5 : 1, mask[2] ? 6 : 2, mask[3] ? 7 : 3, }; return Nucleus::createShuffleVector(lhs, rhs, swizzle); } Type *Nucleus::getPointerType(Type *ElementType) { return T(llvm::PointerType::get(T(ElementType), 0)); } Value *Nucleus::createNullValue(Type *Ty) { return V(llvm::Constant::getNullValue(T(Ty))); } Value *Nucleus::createConstantLong(int64_t i) { return V(llvm::ConstantInt::get(llvm::Type::getInt64Ty(*::context), i, true)); } Value *Nucleus::createConstantInt(int i) { return V(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*::context), i, true)); } Value *Nucleus::createConstantInt(unsigned int i) { return V(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*::context), i, false)); } Value *Nucleus::createConstantBool(bool b) { return V(llvm::ConstantInt::get(llvm::Type::getInt1Ty(*::context), b)); } Value *Nucleus::createConstantByte(signed char i) { return V(llvm::ConstantInt::get(llvm::Type::getInt8Ty(*::context), i, true)); } Value *Nucleus::createConstantByte(unsigned char i) { return V(llvm::ConstantInt::get(llvm::Type::getInt8Ty(*::context), i, false)); } Value *Nucleus::createConstantShort(short i) { return V(llvm::ConstantInt::get(llvm::Type::getInt16Ty(*::context), i, true)); } Value *Nucleus::createConstantShort(unsigned short i) { return V(llvm::ConstantInt::get(llvm::Type::getInt16Ty(*::context), i, false)); } Value *Nucleus::createConstantFloat(float x) { return V(llvm::ConstantFP::get(T(Float::getType()), x)); } Value *Nucleus::createNullPointer(Type *Ty) { return V(llvm::ConstantPointerNull::get(llvm::PointerType::get(T(Ty), 0))); } Value *Nucleus::createConstantVector(const int64_t *constants, Type *type) { assert(llvm::isa
(T(type))); const int numConstants = elementCount(type); // Number of provided constants for the (emulated) type. const int numElements = llvm::cast
(T(type))->getNumElements(); // Number of elements of the underlying vector type. assert(numElements <= 16 && numConstants <= numElements); llvm::Constant *constantVector[16]; for(int i = 0; i < numElements; i++) { constantVector[i] = llvm::ConstantInt::get(T(type)->getContainedType(0), constants[i % numConstants]); } return V(llvm::ConstantVector::get(llvm::ArrayRef
(constantVector, numElements))); } Value *Nucleus::createConstantVector(const double *constants, Type *type) { assert(llvm::isa
(T(type))); const int numConstants = elementCount(type); // Number of provided constants for the (emulated) type. const int numElements = llvm::cast
(T(type))->getNumElements(); // Number of elements of the underlying vector type. assert(numElements <= 8 && numConstants <= numElements); llvm::Constant *constantVector[8]; for(int i = 0; i < numElements; i++) { constantVector[i] = llvm::ConstantFP::get(T(type)->getContainedType(0), constants[i % numConstants]); } return V(llvm::ConstantVector::get(llvm::ArrayRef
(constantVector, numElements))); } Type *Void::getType() { return T(llvm::Type::getVoidTy(*::context)); } Bool::Bool(Argument
argument) { storeValue(argument.value); } Bool::Bool(bool x) { storeValue(Nucleus::createConstantBool(x)); } Bool::Bool(RValue
rhs) { storeValue(rhs.value); } Bool::Bool(const Bool &rhs) { Value *value = rhs.loadValue(); storeValue(value); } Bool::Bool(const Reference
&rhs) { Value *value = rhs.loadValue(); storeValue(value); } RValue
Bool::operator=(RValue
rhs) { storeValue(rhs.value); return rhs; } RValue
Bool::operator=(const Bool &rhs) { Value *value = rhs.loadValue(); storeValue(value); return RValue
(value); } RValue
Bool::operator=(const Reference
&rhs) { Value *value = rhs.loadValue(); storeValue(value); return RValue
(value); } RValue
operator!(RValue
val) { return RValue
(Nucleus::createNot(val.value)); } RValue
operator&&(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createAnd(lhs.value, rhs.value)); } RValue
operator||(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createOr(lhs.value, rhs.value)); } Type *Bool::getType() { return T(llvm::Type::getInt1Ty(*::context)); } Byte::Byte(Argument
argument) { storeValue(argument.value); } Byte::Byte(RValue
cast) { Value *integer = Nucleus::createTrunc(cast.value, Byte::getType()); storeValue(integer); } Byte::Byte(RValue
cast) { Value *integer = Nucleus::createTrunc(cast.value, Byte::getType()); storeValue(integer); } Byte::Byte(RValue
cast) { Value *integer = Nucleus::createTrunc(cast.value, Byte::getType()); storeValue(integer); } Byte::Byte(int x) { storeValue(Nucleus::createConstantByte((unsigned char)x)); } Byte::Byte(unsigned char x) { storeValue(Nucleus::createConstantByte(x)); } Byte::Byte(RValue
rhs) { storeValue(rhs.value); } Byte::Byte(const Byte &rhs) { Value *value = rhs.loadValue(); storeValue(value); } Byte::Byte(const Reference
&rhs) { Value *value = rhs.loadValue(); storeValue(value); } RValue
Byte::operator=(RValue
rhs) { storeValue(rhs.value); return rhs; } RValue
Byte::operator=(const Byte &rhs) { Value *value = rhs.loadValue(); storeValue(value); return RValue
(value); } RValue
Byte::operator=(const Reference
&rhs) { Value *value = rhs.loadValue(); storeValue(value); return RValue
(value); } RValue
operator+(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createAdd(lhs.value, rhs.value)); } RValue
operator-(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createSub(lhs.value, rhs.value)); } RValue
operator*(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createMul(lhs.value, rhs.value)); } RValue
operator/(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createUDiv(lhs.value, rhs.value)); } RValue
operator%(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createURem(lhs.value, rhs.value)); } RValue
operator&(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createAnd(lhs.value, rhs.value)); } RValue
operator|(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createOr(lhs.value, rhs.value)); } RValue
operator^(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createXor(lhs.value, rhs.value)); } RValue
operator<<(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createShl(lhs.value, rhs.value)); } RValue
operator>>(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createLShr(lhs.value, rhs.value)); } RValue
operator+=(Byte &lhs, RValue
rhs) { return lhs = lhs + rhs; } RValue
operator-=(Byte &lhs, RValue
rhs) { return lhs = lhs - rhs; } RValue
operator*=(Byte &lhs, RValue
rhs) { return lhs = lhs * rhs; } RValue
operator/=(Byte &lhs, RValue
rhs) { return lhs = lhs / rhs; } RValue
operator%=(Byte &lhs, RValue
rhs) { return lhs = lhs % rhs; } RValue
operator&=(Byte &lhs, RValue
rhs) { return lhs = lhs & rhs; } RValue
operator|=(Byte &lhs, RValue
rhs) { return lhs = lhs | rhs; } RValue
operator^=(Byte &lhs, RValue
rhs) { return lhs = lhs ^ rhs; } RValue
operator<<=(Byte &lhs, RValue
rhs) { return lhs = lhs << rhs; } RValue
operator>>=(Byte &lhs, RValue
rhs) { return lhs = lhs >> rhs; } RValue
operator+(RValue
val) { return val; } RValue
operator-(RValue
val) { return RValue
(Nucleus::createNeg(val.value)); } RValue
operator~(RValue
val) { return RValue
(Nucleus::createNot(val.value)); } RValue
operator++(Byte &val, int) // Post-increment { RValue
res = val; Value *inc = Nucleus::createAdd(res.value, V(Nucleus::createConstantByte((unsigned char)1))); val.storeValue(inc); return res; } const Byte &operator++(Byte &val) // Pre-increment { Value *inc = Nucleus::createAdd(val.loadValue(), V(Nucleus::createConstantByte((unsigned char)1))); val.storeValue(inc); return val; } RValue
operator--(Byte &val, int) // Post-decrement { RValue
res = val; Value *inc = Nucleus::createSub(res.value, V(Nucleus::createConstantByte((unsigned char)1))); val.storeValue(inc); return res; } const Byte &operator--(Byte &val) // Pre-decrement { Value *inc = Nucleus::createSub(val.loadValue(), V(Nucleus::createConstantByte((unsigned char)1))); val.storeValue(inc); return val; } RValue
operator<(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createICmpULT(lhs.value, rhs.value)); } RValue
operator<=(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createICmpULE(lhs.value, rhs.value)); } RValue
operator>(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createICmpUGT(lhs.value, rhs.value)); } RValue
operator>=(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createICmpUGE(lhs.value, rhs.value)); } RValue
operator!=(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createICmpNE(lhs.value, rhs.value)); } RValue
operator==(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createICmpEQ(lhs.value, rhs.value)); } Type *Byte::getType() { return T(llvm::Type::getInt8Ty(*::context)); } SByte::SByte(Argument
argument) { storeValue(argument.value); } SByte::SByte(RValue
cast) { Value *integer = Nucleus::createTrunc(cast.value, SByte::getType()); storeValue(integer); } SByte::SByte(RValue
cast) { Value *integer = Nucleus::createTrunc(cast.value, SByte::getType()); storeValue(integer); } SByte::SByte(signed char x) { storeValue(Nucleus::createConstantByte(x)); } SByte::SByte(RValue
rhs) { storeValue(rhs.value); } SByte::SByte(const SByte &rhs) { Value *value = rhs.loadValue(); storeValue(value); } SByte::SByte(const Reference
&rhs) { Value *value = rhs.loadValue(); storeValue(value); } RValue
SByte::operator=(RValue
rhs) { storeValue(rhs.value); return rhs; } RValue
SByte::operator=(const SByte &rhs) { Value *value = rhs.loadValue(); storeValue(value); return RValue
(value); } RValue
SByte::operator=(const Reference
&rhs) { Value *value = rhs.loadValue(); storeValue(value); return RValue
(value); } RValue
operator+(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createAdd(lhs.value, rhs.value)); } RValue
operator-(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createSub(lhs.value, rhs.value)); } RValue
operator*(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createMul(lhs.value, rhs.value)); } RValue
operator/(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createSDiv(lhs.value, rhs.value)); } RValue
operator%(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createSRem(lhs.value, rhs.value)); } RValue
operator&(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createAnd(lhs.value, rhs.value)); } RValue
operator|(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createOr(lhs.value, rhs.value)); } RValue
operator^(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createXor(lhs.value, rhs.value)); } RValue
operator<<(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createShl(lhs.value, rhs.value)); } RValue
operator>>(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createAShr(lhs.value, rhs.value)); } RValue
operator+=(SByte &lhs, RValue
rhs) { return lhs = lhs + rhs; } RValue
operator-=(SByte &lhs, RValue
rhs) { return lhs = lhs - rhs; } RValue
operator*=(SByte &lhs, RValue
rhs) { return lhs = lhs * rhs; } RValue
operator/=(SByte &lhs, RValue
rhs) { return lhs = lhs / rhs; } RValue
operator%=(SByte &lhs, RValue
rhs) { return lhs = lhs % rhs; } RValue
operator&=(SByte &lhs, RValue
rhs) { return lhs = lhs & rhs; } RValue
operator|=(SByte &lhs, RValue
rhs) { return lhs = lhs | rhs; } RValue
operator^=(SByte &lhs, RValue
rhs) { return lhs = lhs ^ rhs; } RValue
operator<<=(SByte &lhs, RValue
rhs) { return lhs = lhs << rhs; } RValue
operator>>=(SByte &lhs, RValue
rhs) { return lhs = lhs >> rhs; } RValue
operator+(RValue
val) { return val; } RValue
operator-(RValue
val) { return RValue
(Nucleus::createNeg(val.value)); } RValue
operator~(RValue
val) { return RValue
(Nucleus::createNot(val.value)); } RValue
operator++(SByte &val, int) // Post-increment { RValue
res = val; Value *inc = Nucleus::createAdd(res.value, V(Nucleus::createConstantByte((signed char)1))); val.storeValue(inc); return res; } const SByte &operator++(SByte &val) // Pre-increment { Value *inc = Nucleus::createAdd(val.loadValue(), V(Nucleus::createConstantByte((signed char)1))); val.storeValue(inc); return val; } RValue
operator--(SByte &val, int) // Post-decrement { RValue
res = val; Value *inc = Nucleus::createSub(res.value, V(Nucleus::createConstantByte((signed char)1))); val.storeValue(inc); return res; } const SByte &operator--(SByte &val) // Pre-decrement { Value *inc = Nucleus::createSub(val.loadValue(), V(Nucleus::createConstantByte((signed char)1))); val.storeValue(inc); return val; } RValue
operator<(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createICmpSLT(lhs.value, rhs.value)); } RValue
operator<=(RValue
lhs, RValue
rhs) { return RValue
(Nucleus::createICmpSLE(lhs.value, rhs.value)); } RValue