File: InlineParams.cpp

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (121 lines) | stat: -rw-r--r-- 3,035 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "stdafx.h"
#include "InlineParams.h"
#include "Exception.h"

namespace storm {

	InlineParams::InlineParams(CodeGen *state, Array<code::Operand> *params, CodeResult *result) :
		state(state), originalParams(params), params(params), result(result) {}

	void InlineParams::deepCopy(CloneEnv *env) {
		clone(state, env);
		clone(originalParams, env);
		clone(params, env);
		clone(result, env);
	}

	void InlineParams::spillParams() {
		params = spillRegisters(state, params);
	}

	void InlineParams::allocRegs(Nat id0) {
		Nat d[] = { id0 };
		allocRegs(id0, d, 1);
	}

	void InlineParams::allocRegs(Nat id0, Nat id1) {
		Nat d[] = { id0, id1 };
		allocRegs(id0, d, 2);
		allocRegs(id1, d, 2);
	}

	void InlineParams::allocRegs(Nat id0, Nat id1, Nat id2) {
		Nat d[] = { id0, id1, id2 };
		allocRegs(id0, d, 3);
		allocRegs(id1, d, 3);
		allocRegs(id2, d, 3);
	}

	void InlineParams::allocRegs(Nat id, Nat *avoid, Nat avoidCount) {
		using namespace code;

		Operand p = params->at(id);
		if (p.type() == opRegister) {
			// Nothing to do.
		} else if (p.type() == code::opRelative) {
			// Just read the value into the register.
			Reg r = asSize(p.reg(), p.size());
			*state->l << mov(r, p);
			replace(id, r);
		} else {
			Reg free = asSize(findReg(avoid, avoidCount), p.size());
			*state->l << mov(free, p);
			replace(id, free);
		}
	}

	static Bool contains(Nat *array, Nat count, Nat elem) {
		for (Nat i = 0; i < count; i++)
			if (array[i] == elem)
				return true;

		return false;
	}

	code::Reg InlineParams::findReg(Nat *avoid, Nat avoidCount) {
		using namespace code;

		{
			// See if one of the registers are free already.
			Reg candidates[] = { ptrA, ptrB, ptrC };
			for (Nat i = 0; i < params->count(); i++) {
				const Operand &p = params->at(i);
				if (p.hasRegister()) {
					for (Nat j = 0; j < ARRAY_COUNT(candidates); j++) {
						if (same(candidates[j], p.reg()))
							candidates[j] = noReg;
					}
				}
			}

			for (Nat i = 0; i < ARRAY_COUNT(candidates); i++) {
				if (candidates[i] != noReg)
					return candidates[i];
			}
		}

		// If we get here, we did not find a free register. This means we shall pick a register that
		// is used by another parameter and use that.
		Reg chosen = noReg;
		Nat id = 0;
		for (Nat i = 0; i < params->count(); i++) {
			if (contains(avoid, avoidCount, i))
				continue;

			if (params->at(i).hasRegister()) {
				chosen = noReg;
				id = i;
				break;
			}
		}

		if (chosen == noReg) {
			// Should not happen as we only allow assigning 3 parameters to registers.
			throw new (state) InternalError(S("Unable to find a free register."));
		}

		// Move the old value out of the way so that we can reuse the register.
		Var mem = state->l->createVar(state->block, params->at(id).size());
		*state->l << mov(mem, params->at(id));
		replace(id, mem);

		return chosen;
	}

	void InlineParams::replace(Nat id, const code::Operand &op) {
		if (params == originalParams)
			params = new (params) Array<code::Operand>(*params);
		params->at(id) = op;
	}

}