File: Operand.h

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • 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 (355 lines) | stat: -rw-r--r-- 13,273 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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
#pragma once
#include "Reg.h"
#include "OpCode.h"
#include "CondFlag.h"
#include "Var.h"
#include "Block.h"
#include "Label.h"
#include "Reference.h"
#include "OffsetReference.h"
#include "Core/SrcPos.h"

namespace code {
	STORM_PKG(core.asm);

	/**
	 * Class describing an operand for an asm instruction. May be either:
	 * - a constant
	 * - a register
	 * - a pointer
	 * - a pointer relative a register
	 * - a label
	 * - a reference to something else in the Arena
	 * - a variable
	 * - a block
	 * - a condition flag
	 *
	 * Not all kinds of operands are valid for all kind of operations. Use the creator functions in
	 * 'Instruction.h' to create instructions, as these enforce the correct types.
	 */

	/**
	 * Type of the operand.
	 */
	enum OpType {
		// No data.
		STORM_NAME(opNone, none),

		// Constant.
		STORM_NAME(opConstant, constant),

		// Dual-constant (one value for 32-bit and one for 64-bit). Appears as 'opConstant', but is stored in 'opOffset'.
		STORM_NAME(opDualConstant, dualConstant),

		// Register
		STORM_NAME(opRegister, register),

		// Relative to a register. ie. [reg + offset/offset-ref]
		STORM_NAME(opRelative, relative),

		// Relative to a label. TODO: Implement for X86!
		STORM_NAME(opRelativeLbl, relativeLabel),

		// Variable (+ offset/offset-ref).
		STORM_NAME(opVariable, variable),

		// Label.
		STORM_NAME(opLabel, label),

		// Block.
		STORM_NAME(opBlock, block),

		// Reference to another object.
		STORM_NAME(opReference, reference),

		// Reference to an object.
		STORM_NAME(opObjReference, objReference),

		// Reference to an offset.
		STORM_NAME(opOffReference, offsetReference),

		// Condition flag.
		STORM_NAME(opCondFlag, condFlag),

		// Source code reference (SrcPos).
		STORM_NAME(opSrcPos, srcPos),
	};

	/**
	 * The operand itself.
	 */
	class Operand {
		STORM_VALUE;
	public:
		// No value.
		STORM_CTOR Operand();

		// Register.
		STORM_CAST_CTOR Operand(Reg reg);

		// CondFlag.
		STORM_CAST_CTOR Operand(CondFlag flag);

		// Variable.
		STORM_CAST_CTOR Operand(Var var);

		// Block or part.
		STORM_CAST_CTOR Operand(Block part);

		// Label.
		STORM_CAST_CTOR Operand(Label label);

		// Reference.
		STORM_CAST_CTOR Operand(Ref ref);
		STORM_CAST_CTOR Operand(Reference *ref);

		// SrcPos.
		STORM_CAST_CTOR Operand(SrcPos pos);

		/**
		 * Operations.
		 */

		// Compare.
		Bool STORM_FN operator ==(const Operand &o) const;
		Bool STORM_FN operator !=(const Operand &o) const;

		// Empty?
		Bool STORM_FN empty() const;
		Bool STORM_FN any() const;

		// Get the type of the operand.
		OpType STORM_FN type() const;

		// Get the size of the operand.
		Size STORM_FN size() const;

		// Is this operand readable?
		Bool STORM_FN readable() const;

		// Is this operand writable?
		Bool STORM_FN writable() const;

		// Throw an exception unless the value is readable/writable.
		void STORM_FN ensureReadable(op::OpCode op) const;
		void STORM_FN ensureWritable(op::OpCode op) const;

		// Does this operand use a register (Note: local variables that will use ptrBase later are
		// not considered to be using a register). This currently includes raw registers and memory
		// accesses relative to registers.
		Bool STORM_FN hasRegister() const;

		/**
		 * Get values. Throws an error if used incorrectly.
		 */

		// Get the constant in the operand. Valid if `type` returns `constant`. If the value stored is
		// a `Size` or an `Offset`, then the value obtained by calling `current` is returned.
		Word STORM_FN constant() const;

		// Get the content register. Valid if `type` returns `register` or `relative`.
		Reg STORM_FN reg() const;

		// Get the offset used. Possible to call any time, but only makes sense for `relative`,
		// `variable`, and `relativeLabel`.
		Offset STORM_FN offset() const;

		// Does this operand have a reference that affects `offset`?
		Bool STORM_FN hasOffsetRef() const;

		// Get the condition flag. Valid if `type` returns `condFlag`.
		CondFlag STORM_FN condFlag() const;

		// Get the block. Valid if `type` returns `block`.
		Block STORM_FN block() const;

		// Get the label. Valid if `type` returns `label`.
		Label STORM_FN label() const;

		// Get the reference. Valid if `type` returns `reference`.
		Ref STORM_FN ref() const;

		// Get an offset reference.
		OffsetRef STORM_FN offsetRef() const;

		// Convenient internal access.
		RefSource *refSource() const;

		// Get the variable accessed. Valid if `type` returns `variable`.
		//
		// Note: The size of the returned variable is equal to the size we wish to read. This
		// may differ from the size of the original variable!
		Var STORM_FN var() const;

		// Get the source position. Valid if `type` returns `srcPos`.
		SrcPos STORM_FN srcPos() const;

		// Get the object from C++.
		RootObject *object() const;

		// Get the referenced object. Valid if `type` returns `objReference`. Returns an `Object`.
		MAYBE(Object *) STORM_FN obj() const;

		// Get the referenced object. Valid if `type` returns `objReference`. Returns a `TObject`.
		MAYBE(TObject *) STORM_FN tObj() const;

		// Replace the register in this operand. If no register, this is a no-op.
		Operand STORM_FN replaceRegister(Reg replace) const;

		/**
		 * Debug.
		 */

		void dbg_dump() const;

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

	private:
		// Create constants.
		Operand(Word c, Size size);
		Operand(Size s, Size size);
		Operand(Offset o, Size size);
		Operand(RootObject *obj);

		// Offset reference with specified size.
		Operand(OffsetRef ref, Size size);

		// [register,variable,label] + offset.
		Operand(Reg r, Offset offset, Size size);
		Operand(Var v, Offset offset, Size size);
		Operand(Label l, Offset offset, Size size);

		// [register,variable] + offset-ref
		Operand(Reg r, OffsetRef ref, Size size);
		Operand(Var r, OffsetRef ref, Size size);

		// Our type. Note: may contain other flags as well!
		OpType opType;

		/**
		 * Storage. Optimized for small storage, while not using unions (as they are not supported by the CppTypes).
		 */

		// Store pointers here (ie. references, etc.)
		UNKNOWN(PTR_GC) void *opPtr;

		// Constant data/size data/offset data.
		Word opNum;

		// Offset (if needed).
		Offset opOffset;

		// Size of our data.
		Size opSize;

		// Friends.
		friend Operand intConst(Offset v);
		friend Operand intConst(OffsetRef v);
		friend Operand natConst(Size v);
		friend Operand ptrConst(Size v);
		friend Operand ptrConst(Offset v);
		friend Operand ptrConst(OffsetRef v);
		friend Operand xConst(Size s, Word w);
		friend Operand objPtr(Object *ptr);
		friend Operand objPtr(TObject *ptr);
		friend Operand xRel(Size size, Reg reg, Offset offset);
		friend Operand xRel(Size size, Reg reg, OffsetRef ref);
		friend Operand xRel(Size size, Var v, Offset offset);
		friend Operand xRel(Size size, Var v, OffsetRef ref);
		friend Operand xRel(Size size, Label l, Offset offset);
		friend wostream &operator <<(wostream &to, const Operand &o);
	};

	// Output.
	wostream &operator <<(wostream &to, const Operand &o);

	// Create constants. Note: Do not try to create a pointer to a Gc:d object using xConst. That
	// will fail miserably, as the pointer will not be updated whenever the Gc moves the object.
	Operand STORM_FN byteConst(Byte v);
	Operand STORM_FN intConst(Int v);
	Operand STORM_FN intConst(Offset v);
	Operand STORM_FN intConst(OffsetRef v);
	Operand STORM_FN natConst(Nat v);
	Operand STORM_FN natConst(Size v);
	Operand STORM_FN longConst(Long v);
	Operand STORM_FN wordConst(Word v);
	Operand STORM_FN floatConst(Float v);
	Operand STORM_FN doubleConst(Double v);
	Operand STORM_FN ptrConst(Size v);
	Operand STORM_FN ptrConst(Offset v);
	Operand STORM_FN ptrConst(OffsetRef v);
	Operand STORM_FN ptrConst(Nat v);
	Operand STORM_FN xConst(Size s, Word v);

	// Store a pointer to a GC:d object as a constant.
	Operand STORM_FN objPtr(Object *ptr);
	Operand STORM_FN objPtr(TObject *ptr);

	// Relative values (dereference pointers).
	inline Operand STORM_FN xRel(Size size, Reg reg, Offset offset) { return Operand(reg, offset, size); }
	inline Operand STORM_FN byteRel(Reg reg, Offset offset) { return xRel(Size::sByte, reg, offset); }
	inline Operand STORM_FN intRel(Reg reg, Offset offset) { return xRel(Size::sInt, reg, offset); }
	inline Operand STORM_FN longRel(Reg reg, Offset offset) { return xRel(Size::sLong, reg, offset); }
	inline Operand STORM_FN floatRel(Reg reg, Offset offset) { return xRel(Size::sFloat, reg, offset); }
	inline Operand STORM_FN doubleRel(Reg reg, Offset offset) { return xRel(Size::sDouble, reg, offset); }
	inline Operand STORM_FN ptrRel(Reg reg, Offset offset) { return xRel(Size::sPtr, reg, offset); }

	inline Operand STORM_FN xRel(Size size, Reg reg) { return xRel(size, reg, Offset()); }
	inline Operand STORM_FN byteRel(Reg reg) { return xRel(Size::sByte, reg, Offset()); }
	inline Operand STORM_FN intRel(Reg reg) { return xRel(Size::sInt, reg, Offset()); }
	inline Operand STORM_FN longRel(Reg reg) { return xRel(Size::sLong, reg, Offset()); }
	inline Operand STORM_FN floatRel(Reg reg) { return xRel(Size::sFloat, reg, Offset()); }
	inline Operand STORM_FN doubleRel(Reg reg) { return xRel(Size::sDouble, reg, Offset()); }
	inline Operand STORM_FN ptrRel(Reg reg) { return xRel(Size::sPtr, reg, Offset()); }

	inline Operand STORM_FN xRel(Size size, Reg reg, OffsetRef ref) { return Operand(reg, ref, size); }
	inline Operand STORM_FN byteRel(Reg reg, OffsetRef ref) { return xRel(Size::sByte, reg, ref); }
	inline Operand STORM_FN intRel(Reg reg, OffsetRef ref) { return xRel(Size::sInt, reg, ref); }
	inline Operand STORM_FN longRel(Reg reg, OffsetRef ref) { return xRel(Size::sLong, reg, ref); }
	inline Operand STORM_FN floatRel(Reg reg, OffsetRef ref) { return xRel(Size::sFloat, reg, ref); }
	inline Operand STORM_FN doubleRel(Reg reg, OffsetRef ref) { return xRel(Size::sDouble, reg, ref); }
	inline Operand STORM_FN ptrRel(Reg reg, OffsetRef ref) { return xRel(Size::sPtr, reg, ref); }

	// Access offsets inside variables.
	inline Operand STORM_FN xRel(Size size, Var v, Offset offset) { return Operand(v, offset, size); }
	inline Operand STORM_FN byteRel(Var v, Offset offset) { return xRel(Size::sByte, v, offset); }
	inline Operand STORM_FN intRel(Var v, Offset offset) { return xRel(Size::sInt, v, offset); }
	inline Operand STORM_FN longRel(Var v, Offset offset) { return xRel(Size::sLong, v, offset); }
	inline Operand STORM_FN floatRel(Var v, Offset offset) { return xRel(Size::sFloat, v, offset); }
	inline Operand STORM_FN doubleRel(Var v, Offset offset) { return xRel(Size::sDouble, v, offset); }
	inline Operand STORM_FN ptrRel(Var v, Offset offset) { return xRel(Size::sPtr, v, offset); }

	inline Operand STORM_FN xRel(Size size, Var v) { return xRel(size, v, Offset()); }
	inline Operand STORM_FN byteRel(Var v) { return xRel(Size::sByte, v, Offset()); }
	inline Operand STORM_FN intRel(Var v) { return xRel(Size::sInt, v, Offset()); }
	inline Operand STORM_FN longRel(Var v) { return xRel(Size::sLong, v, Offset()); }
	inline Operand STORM_FN floatRel(Var v) { return xRel(Size::sFloat, v, Offset()); }
	inline Operand STORM_FN doubleRel(Var v) { return xRel(Size::sDouble, v, Offset()); }
	inline Operand STORM_FN ptrRel(Var v) { return xRel(Size::sPtr, v, Offset()); }

	inline Operand STORM_FN xRel(Size size, Var v, OffsetRef ref) { return Operand(v, ref, size); }
	inline Operand STORM_FN byteRel(Var v, OffsetRef ref) { return xRel(Size::sByte, v, ref); }
	inline Operand STORM_FN intRel(Var v, OffsetRef ref) { return xRel(Size::sInt, v, ref); }
	inline Operand STORM_FN longRel(Var v, OffsetRef ref) { return xRel(Size::sLong, v, ref); }
	inline Operand STORM_FN floatRel(Var v, OffsetRef ref) { return xRel(Size::sFloat, v, ref); }
	inline Operand STORM_FN doubleRel(Var v, OffsetRef ref) { return xRel(Size::sDouble, v, ref); }
	inline Operand STORM_FN ptrRel(Var v, OffsetRef ref) { return xRel(Size::sPtr, v, ref); }

	// Access offsets inside labels.
	inline Operand STORM_FN xRel(Size size, Label l, Offset offset) { return Operand(l, offset, size); }
	inline Operand STORM_FN byteRel(Label l, Offset offset) { return xRel(Size::sByte, l, offset); }
	inline Operand STORM_FN intRel(Label l, Offset offset) { return xRel(Size::sInt, l, offset); }
	inline Operand STORM_FN longRel(Label l, Offset offset) { return xRel(Size::sLong, l, offset); }
	inline Operand STORM_FN floatRel(Label l, Offset offset) { return xRel(Size::sFloat, l, offset); }
	inline Operand STORM_FN doubleRel(Label l, Offset offset) { return xRel(Size::sDouble, l, offset); }
	inline Operand STORM_FN ptrRel(Label l, Offset offset) { return xRel(Size::sPtr, l, offset); }

	inline Operand STORM_FN xRel(Size size, Label l) { return xRel(size, l, Offset()); }
	inline Operand STORM_FN byteRel(Label l) { return xRel(Size::sByte, l, Offset()); }
	inline Operand STORM_FN intRel(Label l) { return xRel(Size::sInt, l, Offset()); }
	inline Operand STORM_FN longRel(Label l) { return xRel(Size::sLong, l, Offset()); }
	inline Operand STORM_FN floatRel(Label l) { return xRel(Size::sFloat, l, Offset()); }
	inline Operand STORM_FN doubleRel(Label l) { return xRel(Size::sDouble, l, Offset()); }
	inline Operand STORM_FN ptrRel(Label l) { return xRel(Size::sPtr, l, Offset()); }
}