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 "RoutineManager.hpp"
16
17#include "Routine.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 RoutineManager::averageInstructionSize = 4;
28
29	RoutineManager::RoutineManager()
30	{
31		routine = 0;
32	}
33
34	RoutineManager::~RoutineManager()
35	{
36		delete routine;
37	}
38
39	void RoutineManager::AllocateGOT()
40	{
41		UNIMPLEMENTED();
42	}
43
44	uint8_t *RoutineManager::allocateStub(const GlobalValue *function, unsigned stubSize, unsigned alignment)
45	{
46		UNIMPLEMENTED();
47		return 0;
48	}
49
50	uint8_t *RoutineManager::startFunctionBody(const llvm::Function *function, uintptr_t &actualSize)
51	{
52		if(actualSize == 0)   // Estimate size
53		{
54			int 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 Routine(actualSize);
73
74		return (uint8_t*)routine->getBuffer();
75	}
76
77	void RoutineManager::endFunctionBody(const llvm::Function *function, uint8_t *functionStart, uint8_t *functionEnd)
78	{
79		routine->setFunctionSize(functionEnd - functionStart);
80	}
81
82	uint8_t *RoutineManager::startExceptionTable(const llvm::Function* F, uintptr_t &ActualSize)
83	{
84		UNIMPLEMENTED();
85		return 0;
86	}
87
88	void RoutineManager::endExceptionTable(const llvm::Function *F, uint8_t *TableStart, uint8_t *TableEnd, uint8_t* FrameRegister)
89	{
90		UNIMPLEMENTED();
91	}
92
93	uint8_t *RoutineManager::getGOTBase() const
94	{
95		ASSERT(!HasGOT);
96		return 0;
97	}
98
99	uint8_t *RoutineManager::allocateSpace(intptr_t Size, unsigned Alignment)
100	{
101		UNIMPLEMENTED();
102		return 0;
103	}
104
105	uint8_t *RoutineManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
106	{
107		UNIMPLEMENTED();
108		return 0;
109	}
110
111	void RoutineManager::deallocateFunctionBody(void *Body)
112	{
113		delete routine;
114		routine = 0;
115	}
116
117	void RoutineManager::deallocateExceptionTable(void *ET)
118	{
119		if(ET)
120		{
121			UNIMPLEMENTED();
122		}
123	}
124
125	void RoutineManager::setMemoryWritable()
126	{
127	}
128
129	void RoutineManager::setMemoryExecutable()
130	{
131		markExecutable(routine->buffer, routine->bufferSize);
132	}
133
134	void RoutineManager::setPoisonMemory(bool poison)
135	{
136		UNIMPLEMENTED();
137	}
138
139	Routine *RoutineManager::acquireRoutine(void *entry)
140	{
141		routine->entry = entry;
142
143		Routine *result = routine;
144		routine = 0;
145
146		return result;
147	}
148}
149