File: TypeDesc.h

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 (201 lines) | stat: -rw-r--r-- 5,830 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#pragma once
#include "Size.h"
#include "Reference.h"
#include "Core/Array.h"
#include "Core/GcArray.h"
#include "Core/Object.h"
#include "Core/Exception.h"

namespace code {
	STORM_PKG(core.asm);

	namespace primitive {
		// Kind of primitives.
		enum PrimitiveKind {
			none,
			pointer,
			integer,
			real,
		};

		// C++ friendly name. Can not be used in function declarations visible to Storm.
		typedef PrimitiveKind Kind;

		// Get the name as a string.
		const wchar *name(Kind kind);
	}

	/**
	 * Description of a primitive type. Used inside 'TypeDesc'.
	 */
	class Primitive {
		STORM_VALUE;
	public:
		// Create a 'void' value.
		STORM_CTOR Primitive();

		// Create a primitive.
		STORM_CTOR Primitive(primitive::PrimitiveKind kind, Size size, Offset offset);

		// Get the kind.
		inline primitive::PrimitiveKind STORM_FN kind() const {
			return primitive::Kind((dataA & 0x1) | ((dataB & 0x1) << 1));
		}

		// Get the size (we do not preserve alignment).
		inline Size STORM_FN size() const {
			Nat s32 = (dataA & 0xFE) >> 1;
			Nat s64 = (dataB & 0xFE) >> 1;
			return Size(s32, s32, s64, s64);
		}

		// Get the offset.
		inline Offset STORM_FN offset() const {
			Nat o32 = (dataA & 0xFFFFFF00) >> 8;
			Nat o64 = (dataB & 0xFFFFFF00) >> 8;
			return Offset(o32, o64);
		}

		// Move to another offset.
		Primitive STORM_FN move(Offset to) const;

		// Output.
		void STORM_FN toS(StrBuf *to) const;

	private:
		// We store these fields inside 'dataA' and 'dataB'.
		// A0, B0: kind (A0 is LSB).
		// A1-7: 32-bit size
		// B1-7: 64-bit size
		// A8-31: 32-bit offset
		// B8-31: 64-bit offset
		Nat dataA;
		Nat dataB;
	};

	wostream &operator <<(wostream &to, const Primitive &p);

	// Create primitive types easily.
	inline Primitive STORM_FN bytePrimitive() { return Primitive(primitive::integer, Size::sByte, Offset()); }
	inline Primitive STORM_FN intPrimitive() { return Primitive(primitive::integer, Size::sInt, Offset()); }
	inline Primitive STORM_FN ptrPrimitive() { return Primitive(primitive::pointer, Size::sPtr, Offset()); }
	inline Primitive STORM_FN longPrimitive() { return Primitive(primitive::integer, Size::sLong, Offset()); }
	inline Primitive STORM_FN floatPrimitive() { return Primitive(primitive::real, Size::sFloat, Offset()); }
	inline Primitive STORM_FN doublePrimitive() { return Primitive(primitive::real, Size::sDouble, Offset()); }

	/**
	 * Low-level description of a type. Instances of this class are used to tell the code backend
	 * enough about a type that is being passed as a parameter so that it can properly follow the
	 * calling convention of the system being targeted.
	 *
	 * A TypeDesc may describe the following categories of types:
	 * - A primitive type (size, floating point)
	 * - A complex type (size, constructor, destructor)
	 * - A simple type (size and offset off all members)
	 *
	 * A primitive type is some kind of number that can be handled by the CPU (eg. int, float). In
	 * this case, we store the total size of the type and what kind of number we're dealing with
	 * (ie. pointer, integer, floating point).
	 *
	 * A complex type is a composite type (ie. struct or class) that can not be trivially
	 * copied. Therefore, we are only concerned with the total size of the type and its copy
	 * constructor and destructor.
	 *
	 * A simple type is a composite type (ie. struct or class) that can be trivially copied. This
	 * means we do not need to concern ourselves with the copy constructor and destructor of the
	 * type, but we need to know all members of the type. If the simple type contains other simple
	 * types, these are also disassembled until only primitive types remain.
	 */
	class TypeDesc : public ObjectOn<Compiler> {
		STORM_CLASS;
	public:
		// Get the size of this type.
		virtual Size STORM_FN size() const;
	};


	/**
	 * A primitive type:
	 *
	 * This is a type that the CPU can handle directly, and that can be stored in a register.
	 */
	class PrimitiveDesc : public TypeDesc {
		STORM_CLASS;
	public:
		STORM_CTOR PrimitiveDesc(Primitive p);

		Primitive v;

		virtual Size STORM_FN size() const { return v.size(); }
		void STORM_FN toS(StrBuf *to) const;
	};


	/**
	 * A complex type:
	 *
	 * This is a type that needs to reside in memory, and that needs to be manipulated through
	 * copy-constructors and destructors.
	 */
	class ComplexDesc : public TypeDesc {
		STORM_CLASS;
	public:
		ComplexDesc(Size size, Ref ctor, Ref dtor);

		Size s;
		Ref ctor;
		Ref dtor;

		virtual Size STORM_FN size() const { return s; }
		void STORM_FN toS(StrBuf *to) const;
	};


	/**
	 * A simple type:
	 *
	 * This is a type that consists of a set of primitive types. While it may not be possible to
	 * store the type in a register, it is possible to decompose the type into multiple registers
	 * and manipulate it in that way.
	 */
	class SimpleDesc : public TypeDesc {
		STORM_CLASS;
	public:
		STORM_CTOR SimpleDesc(Size size, Nat entries);

		// Total size:
		Size s;

		// Primitives. These are assumed to be sorted according to their offset.
		GcArray<Primitive> *v;

		Primitive &STORM_FN at(Nat id) {
			if (id >= v->count)
				throw new (this) storm::ArrayError(id, Nat(v->count));
			return v->v[id];
		}
		Nat STORM_FN count() const {
			return Nat(v->count);
		}

		// Sort primitives.
		void STORM_FN sort();

		// virtual void STORM_FN deepCopy(CloneEnv *env);
		virtual Size STORM_FN size() const { return s; }
		void STORM_FN toS(StrBuf *to) const;
	};


	/**
	 * Helpers for creating TypeDesc objects.
	 */
	TypeDesc *STORM_FN voidDesc(EnginePtr e);
	TypeDesc *STORM_FN byteDesc(EnginePtr e);
	TypeDesc *STORM_FN intDesc(EnginePtr e);
	TypeDesc *STORM_FN ptrDesc(EnginePtr e);
	TypeDesc *STORM_FN longDesc(EnginePtr e);
	TypeDesc *STORM_FN floatDesc(EnginePtr e);
	TypeDesc *STORM_FN doubleDesc(EnginePtr e);

}