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#include "LLVMRoutineManager.hpp"
16
17#include "LLVMRoutine.hpp"
18#include "llvm/Function.h"
19#include "../Common/Memory.hpp"
20#include "../Common/Thread.hpp"
21#include "../Common/Debug.hpp"
22
23namespace sw
24{
25	using namespace llvm;
26
27	volatile int LLVMRoutineManager::averageInstructionSize = 4;
28
29	LLVMRoutineManager::LLVMRoutineManager()
30	{
31		routine = nullptr;
32	}
33
34	LLVMRoutineManager::~LLVMRoutineManager()
35	{
36		delete routine;
37	}
38
39	void LLVMRoutineManager::AllocateGOT()
40	{
41		UNIMPLEMENTED();
42	}
43
44	uint8_t *LLVMRoutineManager::allocateStub(const GlobalValue *function, unsigned stubSize, unsigned alignment)
45	{
46		UNIMPLEMENTED();
47		return nullptr;
48	}
49
50	uint8_t *LLVMRoutineManager::startFunctionBody(const llvm::Function *function, uintptr_t &actualSize)
51	{
52		if(actualSize == 0)   // Estimate size
53		{
54			size_t instructionCount = 0;
55			for(llvm::Function::const_iterator basicBlock = function->begin(); basicBlock != function->end(); basicBlock++)
56			{
57				instructionCount += basicBlock->size();
58			}
59
60			actualSize = instructionCount * averageInstructionSize;
61		}
62		else   // Estimate was too low
63		{
64			sw::atomicIncrement(&averageInstructionSize);
65		}
66
67		// Round up to the next page size
68		size_t pageSize = memoryPageSize();
69		actualSize = (actualSize + pageSize - 1) & ~(pageSize - 1);
70
71		delete routine;
72		routine = new LLVMRoutine(static_cast<int>(actualSize));
73
74		return (uint8_t*)routine->buffer;
75	}
76
77	void LLVMRoutineManager::endFunctionBody(const llvm::Function *function, uint8_t *functionStart, uint8_t *functionEnd)
78	{
79		routine->functionSize = static_cast<int>(static_cast<ptrdiff_t>(functionEnd - functionStart));
80	}
81
82	uint8_t *LLVMRoutineManager::startExceptionTable(const llvm::Function* F, uintptr_t &ActualSize)
83	{
84		UNIMPLEMENTED();
85		return nullptr;
86	}
87
88	void LLVMRoutineManager::endExceptionTable(const llvm::Function *F, uint8_t *TableStart, uint8_t *TableEnd, uint8_t* FrameRegister)
89	{
90		UNIMPLEMENTED();
91	}
92
93	uint8_t *LLVMRoutineManager::getGOTBase() const
94	{
95		ASSERT(!HasGOT);
96		return nullptr;
97	}
98
99	uint8_t *LLVMRoutineManager::allocateSpace(intptr_t Size, unsigned Alignment)
100	{
101		UNIMPLEMENTED();
102		return nullptr;
103	}
104
105	uint8_t *LLVMRoutineManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
106	{
107		UNIMPLEMENTED();
108		return nullptr;
109	}
110
111	void LLVMRoutineManager::deallocateFunctionBody(void *Body)
112	{
113		delete routine;
114		routine = nullptr;
115	}
116
117	void LLVMRoutineManager::deallocateExceptionTable(void *ET)
118	{
119		if(ET)
120		{
121			UNIMPLEMENTED();
122		}
123	}
124
125	void LLVMRoutineManager::setMemoryWritable()
126	{
127	}
128
129	void LLVMRoutineManager::setMemoryExecutable()
130	{
131		markExecutable(routine->buffer, routine->bufferSize);
132	}
133
134	void LLVMRoutineManager::setPoisonMemory(bool poison)
135	{
136		UNIMPLEMENTED();
137	}
138
139	LLVMRoutine *LLVMRoutineManager::acquireRoutine(void *entry)
140	{
141		routine->entry = entry;
142
143		LLVMRoutine *result = routine;
144		routine = nullptr;
145
146		return result;
147	}
148}
149