File: VTableCall.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 (101 lines) | stat: -rw-r--r-- 2,756 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
#include "stdafx.h"
#include "VTableCall.h"
#include "Code/Listing.h"
#include "Core/StrBuf.h"
#include "Engine.h"

namespace storm {

	VTableCalls::VTableCalls() {
		cpp = new (this) Array<code::RefSource *>();
		storm = new (this) Array<code::RefSource *>();
		variants = engine().arena()->firstParamId(null);
	}


	code::RefSource *VTableCalls::get(VTableSlot slot, Value result) {
		Engine &e = engine();
		Nat id = e.arena()->firstParamId(result.desc(e));

		switch (slot.type) {
		case VTableSlot::tCpp:
			return getCpp(slot.offset, id);
		case VTableSlot::tStorm:
			return getStorm(slot.offset, id);
		default:
			assert(false, L"Unknown slot type.");
			return null;
		}
	}

	code::RefSource *&VTableCalls::find(Array<code::RefSource *> *in, Nat offset, Nat id) {
		Nat arrayId = offset*variants + id;
		while (in->count() <= arrayId)
			in->push(null);

		return in->at(arrayId);
	}


	code::RefSource *VTableCalls::getCpp(Nat offset, Nat id) {
		code::RefSource *&entry = find(cpp, offset, id);
		if (entry)
			return entry;

		using namespace code;
		Reg tmpReg = engine().arena()->functionDispatchReg();
		Reg firstReg = tmpReg;
		Operand firstParam = engine().arena()->firstParamLoc(id);

		Listing *l = new (this) Listing();
		if (firstParam.type() == opRegister) {
			firstReg = firstParam.reg();
		} else {
			*l << mov(tmpReg, firstParam);
			firstReg = tmpReg;
		}

		*l << mov(tmpReg, ptrRel(firstReg, Offset()));
		*l << jmp(ptrRel(tmpReg, Offset::sPtr * offset));

		Binary *b = new (this) Binary(engine().arena(), l);
		entry = new (this) VTableSource(cppSlot(offset), id, b);
		return entry;
	}

	code::RefSource *VTableCalls::getStorm(Nat offset, Nat id) {
		code::RefSource *&entry = find(storm, offset, id);
		if (entry)
			return entry;

		using namespace code;
		Reg tmpReg = engine().arena()->functionDispatchReg();
		Reg firstReg = tmpReg;
		Operand firstParam = engine().arena()->firstParamLoc(id);

		Listing *l = new (this) Listing();
		if (firstParam.type() == opRegister) {
			firstReg = firstParam.reg();
		} else {
			*l << mov(tmpReg, engine().arena()->firstParamLoc(id));
			firstReg = tmpReg;
		}

		*l << mov(tmpReg, ptrRel(firstReg, Offset()));
		*l << mov(tmpReg, ptrRel(tmpReg, -Offset::sPtr * vtable::extraOffset));
		*l << jmp(ptrRel(tmpReg, Offset::sPtr * (offset + 2))); // 2 for the 2 size_t members in arrays.

		Binary *b = new (this) Binary(engine().arena(), l);
		entry = new (this) VTableSource(stormSlot(offset), id, b);
		return entry;
	}

	VTableSource::VTableSource(VTableSlot slot, Nat id, code::Content *c) : RefSource(c), slot(slot), id(id) {}

	Str *VTableSource::title() const {
		StrBuf *out = new (this) StrBuf();
		*out << S("vtable ") << slot << S(",") << id;
		return out->toS();
	}

}