|  | // 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 "LLVMRoutineManager.hpp" | 
|  |  | 
|  | #include "LLVMRoutine.hpp" | 
|  | #include "llvm/Function.h" | 
|  | #include "../Common/Memory.hpp" | 
|  | #include "../Common/Thread.hpp" | 
|  | #include "../Common/Debug.hpp" | 
|  |  | 
|  | namespace sw | 
|  | { | 
|  | using namespace llvm; | 
|  |  | 
|  | volatile int LLVMRoutineManager::averageInstructionSize = 4; | 
|  |  | 
|  | LLVMRoutineManager::LLVMRoutineManager() | 
|  | { | 
|  | routine = nullptr; | 
|  | } | 
|  |  | 
|  | LLVMRoutineManager::~LLVMRoutineManager() | 
|  | { | 
|  | delete routine; | 
|  | } | 
|  |  | 
|  | void LLVMRoutineManager::AllocateGOT() | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | } | 
|  |  | 
|  | uint8_t *LLVMRoutineManager::allocateStub(const GlobalValue *function, unsigned stubSize, unsigned alignment) | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | uint8_t *LLVMRoutineManager::startFunctionBody(const llvm::Function *function, uintptr_t &actualSize) | 
|  | { | 
|  | if(actualSize == 0)   // Estimate size | 
|  | { | 
|  | size_t instructionCount = 0; | 
|  | for(llvm::Function::const_iterator basicBlock = function->begin(); basicBlock != function->end(); basicBlock++) | 
|  | { | 
|  | instructionCount += basicBlock->size(); | 
|  | } | 
|  |  | 
|  | actualSize = instructionCount * averageInstructionSize; | 
|  | } | 
|  | else   // Estimate was too low | 
|  | { | 
|  | sw::atomicIncrement(&averageInstructionSize); | 
|  | } | 
|  |  | 
|  | // Round up to the next page size | 
|  | size_t pageSize = memoryPageSize(); | 
|  | actualSize = (actualSize + pageSize - 1) & ~(pageSize - 1); | 
|  |  | 
|  | delete routine; | 
|  | routine = new LLVMRoutine(static_cast<int>(actualSize)); | 
|  |  | 
|  | return (uint8_t*)routine->buffer; | 
|  | } | 
|  |  | 
|  | void LLVMRoutineManager::endFunctionBody(const llvm::Function *function, uint8_t *functionStart, uint8_t *functionEnd) | 
|  | { | 
|  | routine->functionSize = static_cast<int>(static_cast<ptrdiff_t>(functionEnd - functionStart)); | 
|  | } | 
|  |  | 
|  | uint8_t *LLVMRoutineManager::startExceptionTable(const llvm::Function* F, uintptr_t &ActualSize) | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | void LLVMRoutineManager::endExceptionTable(const llvm::Function *F, uint8_t *TableStart, uint8_t *TableEnd, uint8_t* FrameRegister) | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | } | 
|  |  | 
|  | uint8_t *LLVMRoutineManager::getGOTBase() const | 
|  | { | 
|  | ASSERT(!HasGOT); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | uint8_t *LLVMRoutineManager::allocateSpace(intptr_t Size, unsigned Alignment) | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | uint8_t *LLVMRoutineManager::allocateGlobal(uintptr_t Size, unsigned Alignment) | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | void LLVMRoutineManager::deallocateFunctionBody(void *Body) | 
|  | { | 
|  | delete routine; | 
|  | routine = nullptr; | 
|  | } | 
|  |  | 
|  | void LLVMRoutineManager::deallocateExceptionTable(void *ET) | 
|  | { | 
|  | if(ET) | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void LLVMRoutineManager::setMemoryWritable() | 
|  | { | 
|  | } | 
|  |  | 
|  | void LLVMRoutineManager::setMemoryExecutable() | 
|  | { | 
|  | markExecutable(routine->buffer, routine->bufferSize); | 
|  | } | 
|  |  | 
|  | void LLVMRoutineManager::setPoisonMemory(bool poison) | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | } | 
|  |  | 
|  | LLVMRoutine *LLVMRoutineManager::acquireRoutine(void *entry) | 
|  | { | 
|  | routine->entry = entry; | 
|  |  | 
|  | LLVMRoutine *result = routine; | 
|  | routine = nullptr; | 
|  |  | 
|  | return result; | 
|  | } | 
|  | } |