File: Layout.cpp

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; 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 (107 lines) | stat: -rw-r--r-- 2,604 bytes parent folder | download | duplicates (2)
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
#include "stdafx.h"
#include "Layout.h"
#include "Core/GcType.h"
#include "Type.h"
#include "Exception.h"

namespace storm {

	Layout::Layout() {
		vars = new (this) Array<MemberVar *>();
	}

	void Layout::add(Named *n, Type *into) {
		if (MemberVar *v = as<MemberVar>(n))
			add(v, into);
	}

	void Layout::add(MemberVar *v, Type *into) {
		if (v->owner() != into) {
			StrBuf *msg = new (this) StrBuf();
			*msg << S("The member variable ") << v << S(" is not defined as ");
			*msg << S("a member of the type ") << into->identifier() << S(" to ");
			*msg << S("which it is being added. It is defined to be a member of ");
			*msg << v->owner()->identifier() << S(".");
			throw new (this) TypedefError(v->pos, msg->toS());
		}

		vars->push(v);
		// The layout is lazily created. 'v' will ask us when we need to lay it out.
	}

	Size Layout::doLayout(Size parentSize) {
		Size s = parentSize;

		for (nat i = 0; i < vars->count(); i++) {
			MemberVar *v = vars->at(i);

			Size vSize = v->type.size();
			s += vSize.alignment();
			v->setOffset(Offset(s));

			s += vSize;
		}

		return s;
	}

	// Validate the generated GcType.
	static bool validate(const GcType *type) {
		for (nat i = 0; i < type->count; i++) {
			if (type->offset[i] >= type->stride) {
				PLN(L"@" << i << L": " << type->offset[i] << L" >= " << type->stride);
				return false;
			}
		}
		return true;
	}

	nat Layout::fillGcType(Size parentSize, const GcType *parent, GcType *to) {
		Size s = parentSize;
		nat pos = parent ? Nat(parent->count) : 0;

		// Copy entries from the parent.
		if (to && parent) {
			for (nat i = 0; i < parent->count; i++)
				to->offset[i] = parent->offset[i];
		}

		for (nat i = 0; i < vars->count(); i++) {
			MemberVar *v = vars->at(i);
			Value vType = v->type;
			Size vSize = vType.size();
			s += vSize.alignment();

			Offset offset(s);
			if (vType.isPtr() || vType.ref) {
				// We need to GC this one!
				if (to)
					to->offset[pos] = offset.current();
				pos++;
			} else if (vType.isValue()) {
				// Copy and offset all members of this value.
				const GcType *src = vType.type->gcType();
				for (nat j = 0; j < src->count; j++) {
					if (to)
						to->offset[pos] = offset.current() + src->offset[j];
					pos++;
				}
			}

			s += vSize;
		}

		if (to) {
			assert(validate(to), L"Invalid GcType generated!");
			assert(to->stride == s.current(), L"Size of the provided GcType does not match!");
			assert(pos == to->count, L"Too small GcType provided!");
		}

		return pos;
	}

	Array<MemberVar *> *Layout::variables() {
		return new (this) Array<MemberVar *>(*vars);
	}

}