1 using System;
2 using System.Collections;
3
4 namespace cmsx.intermediate
5 {
6 public abstract class Value
7 {
8 public default nothrow Value();
9 public virtual default ~Value();
10 public abstract nothrow string Name() const;
11 public virtual nothrow string PrintName() const
12 {
13 return Name();
14 }
15 public virtual nothrow string IndexStr() const
16 {
17 return Name();
18 }
19 public virtual nothrow Location* HomeLocation() const
20 {
21 return null;
22 }
23 public virtual nothrow bool IsImmediate(byte& immediateValue) const
24 {
25 return false;
26 }
27 public virtual void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
28 {
29 throw Exception("error: tried to generate set for '" + string(type->Name()) + "' value (line " + ToString(line) + ")");
30 }
31 public virtual Value* SignExtendTo(Type* targetType, int line)
32 {
33 throw Exception("error: tried to sign extend '" + type->Name() + "' type value to '" + targetType->Name() + " type value (line " + ToString(line) + ")");
34 }
35 public virtual Value* ZeroExtendTo(Type* targetType, int line)
36 {
37 throw Exception("error: tried to zero extend '" + type->Name() + "' type value to '" + targetType->Name() + " type value (line " + ToString(line) + ")");
38 }
39 public virtual Value* TruncateTo(Type* targetType, int line)
40 {
41 throw Exception("error: tried to truncate '" + type->Name() + "' type value to '" + targetType->Name() + " type value (line " + ToString(line) + ")");
42 }
43 public virtual void Validate(Type* type, const string& index)
44 {
45 Type* thisType = this->type;
46 if (thisType != type)
47 {
48 throw Exception("error: type conflict: element " + index + " has type '" + thisType->Name() + "', type '" + type->Name() + "' expected");
49 }
50 }
51 public virtual nothrow void IncNumUses()
52 {
53 }
54 public Type* type;
55 public int line;
56 }
57
58 public class ConstantValue : Value
59 {
60 public override nothrow string Name() const
61 {
62 return "constant";
63 }
64 public virtual void GenerateCode(MachineCode& machineCode, string& label, Context& context)
65 {
66 throw Exception("error: tried to generate code for " + string(typename(*this)));
67 }
68 public virtual Operand* MakeDataOperand(Context& context) const
69 {
70 throw Exception("error: tried to make data operand for " + string(typename(*this)));
71 }
72 }
73
74 public class LiteralValue : ConstantValue
75 {
76 public override nothrow string Name() const
77 {
78 return "literal";
79 }
80 }
81
82 public class BoolValue : LiteralValue
83 {
84 public default nothrow BoolValue();
85 public nothrow BoolValue(bool value_) : value(value_)
86 {
87 }
88 public override nothrow string Name() const
89 {
90 return ToString(value);
91 }
92 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
93 {
94 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
95 setInst->AddOperand(reg);
96 setInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(value)));
97 }
98 public override ConstantValue* SignExtendTo(Type* targetType, int line)
99 {
100 return targetType->MakeValue(cmsx.util.SignExtend(cast<byte>(value)));
101 }
102 public override ConstantValue* ZeroExtendTo(Type* targetType, int line)
103 {
104 return targetType->MakeValue(cast<ulong>(value));
105 }
106 public override ConstantValue* TruncateTo(Type* targetType, int line)
107 {
108 return targetType->MakeValue(cast<ulong>(value));
109 }
110 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
111 {
112 MachineInstruction* byteInst = machineCode.GetInstruction(cmsx.assembly.BYTE, label);
113 byteInst->AddOperand(MakeDataOperand(context));
114 label.Clear();
115 }
116 public override Operand* MakeDataOperand(Context& context) const
117 {
118 return context.GetLiteralOperand(cast<byte>(value));
119 }
120 public bool value;
121 }
122
123 public class SByteValue : LiteralValue
124 {
125 public default nothrow SByteValue();
126 public nothrow SByteValue(sbyte value_) : value(value_)
127 {
128 }
129 public override nothrow string Name() const
130 {
131 return ToString(value);
132 }
133 public override nothrow bool IsImmediate(byte& immediateValue) const
134 {
135 if (value >= 0)
136 {
137 immediateValue = cast<byte>(value);
138 return true;
139 }
140 else
141 {
142 return false;
143 }
144 }
145 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
146 {
147 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
148 setInst->AddOperand(reg);
149 setInst->AddOperand(machineCode.context.GetLiteralOperand(cast<byte>(value)));
150 }
151 public override ConstantValue* SignExtendTo(Type* targetType, int line)
152 {
153 return targetType->MakeValue(cmsx.util.SignExtend(cast<byte>(value)));
154 }
155 public override ConstantValue* TruncateTo(Type* targetType, int line)
156 {
157 return targetType->MakeValue(cast<ulong>(value));
158 }
159 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
160 {
161 MachineInstruction* byteInst = machineCode.GetInstruction(cmsx.assembly.BYTE, label);
162 byteInst->AddOperand(MakeDataOperand(context));
163 label.Clear();
164 }
165 public override Operand* MakeDataOperand(Context& context) const
166 {
167 return context.GetLiteralOperand(cast<byte>(value));
168 }
169 public sbyte value;
170 }
171
172 public class ByteValue : LiteralValue
173 {
174 public default nothrow ByteValue();
175 public nothrow ByteValue(byte value_) : value(value_)
176 {
177 }
178 public override nothrow string Name() const
179 {
180 return ToString(value);
181 }
182 public override nothrow bool IsImmediate(byte& immediateValue) const
183 {
184 immediateValue = value;
185 return true;
186 }
187 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
188 {
189 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
190 setInst->AddOperand(reg);
191 setInst->AddOperand(machineCode.context.GetLiteralOperand(value));
192 }
193 public override ConstantValue* SignExtendTo(Type* targetType, int line)
194 {
195 return targetType->MakeValue(cmsx.util.SignExtend(value));
196 }
197 public override ConstantValue* ZeroExtendTo(Type* targetType, int line)
198 {
199 return targetType->MakeValue(value);
200 }
201 public override ConstantValue* TruncateTo(Type* targetType, int line)
202 {
203 return targetType->MakeValue(cast<ulong>(value));
204 }
205 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
206 {
207 MachineInstruction* byteInst = machineCode.GetInstruction(cmsx.assembly.BYTE, label);
208 byteInst->AddOperand(MakeDataOperand(context));
209 label.Clear();
210 }
211 public override Operand* MakeDataOperand(Context& context) const
212 {
213 return context.GetLiteralOperand(value);
214 }
215 public byte value;
216 }
217
218 public class ShortValue : LiteralValue
219 {
220 public default nothrow ShortValue();
221 public nothrow ShortValue(short value_) : value(value_)
222 {
223 }
224 public override nothrow string Name() const
225 {
226 return ToString(value);
227 }
228 public override nothrow bool IsImmediate(byte& immediateValue) const
229 {
230 if (value >= 0 && value <= 255)
231 {
232 immediateValue = cast<byte>(value);
233 return true;
234 }
235 else
236 {
237 return false;
238 }
239 }
240 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
241 {
242 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
243 setInst->AddOperand(reg);
244 setInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ushort>(value)));
245 }
246 public override ConstantValue* SignExtendTo(Type* targetType, int line)
247 {
248 return targetType->MakeValue(cmsx.util.SignExtend(cast<ushort>(value)));
249 }
250 public override ConstantValue* TruncateTo(Type* targetType, int line)
251 {
252 return targetType->MakeValue(cast<ulong>(value));
253 }
254 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
255 {
256 MachineInstruction* wydeInst = machineCode.GetInstruction(cmsx.assembly.WYDE, label);
257 wydeInst->AddOperand(MakeDataOperand(context));
258 label.Clear();
259 }
260 public override Operand* MakeDataOperand(Context& context) const
261 {
262 return context.GetLiteralOperand(cast<ushort>(value));
263 }
264 public short value;
265 }
266
267 public class UShortValue : LiteralValue
268 {
269 public default nothrow UShortValue();
270 public nothrow UShortValue(ushort value_) : value(value_)
271 {
272 }
273 public override nothrow string Name() const
274 {
275 return ToString(value);
276 }
277 public override nothrow bool IsImmediate(byte& immediateValue) const
278 {
279 if (value <= 255u)
280 {
281 immediateValue = cast<byte>(value);
282 return true;
283 }
284 else
285 {
286 return false;
287 }
288 }
289 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
290 {
291 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
292 setInst->AddOperand(reg);
293 setInst->AddOperand(machineCode.context.GetLiteralOperand(value));
294 }
295 public override ConstantValue* SignExtendTo(Type* targetType, int line)
296 {
297 return targetType->MakeValue(cmsx.util.SignExtend(value));
298 }
299 public override ConstantValue* ZeroExtendTo(Type* targetType, int line)
300 {
301 return targetType->MakeValue(value);
302 }
303 public override ConstantValue* TruncateTo(Type* targetType, int line)
304 {
305 return targetType->MakeValue(cast<ulong>(value));
306 }
307 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
308 {
309 MachineInstruction* wydeInst = machineCode.GetInstruction(cmsx.assembly.WYDE, label);
310 wydeInst->AddOperand(MakeDataOperand(context));
311 label.Clear();
312 }
313 public override Operand* MakeDataOperand(Context& context) const
314 {
315 return context.GetLiteralOperand(value);
316 }
317 public ushort value;
318 }
319
320 public class IntValue : LiteralValue
321 {
322 public default nothrow IntValue();
323 public nothrow IntValue(int value_) : value(value_)
324 {
325 }
326 public override nothrow string Name() const
327 {
328 return ToString(value);
329 }
330 public override nothrow bool IsImmediate(byte& immediateValue) const
331 {
332 if (value >= 0 && value <= 255)
333 {
334 immediateValue = cast<byte>(value);
335 return true;
336 }
337 else
338 {
339 return false;
340 }
341 }
342 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
343 {
344 ushort low = cast<ushort>(value);
345 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
346 setInst->AddOperand(reg);
347 setInst->AddOperand(machineCode.context.GetLiteralOperand(low));
348 ushort high = cast<ushort>(value >> 16);
349 if (high != 0u)
350 {
351 MachineInstruction* orMLInst = machineCode.GetInstruction(cmsx.machine.ORML, inst);
352 orMLInst->AddOperand(reg);
353 orMLInst->AddOperand(machineCode.context.GetLiteralOperand(high));
354 }
355 }
356 public override ConstantValue* SignExtendTo(Type* targetType, int line)
357 {
358 return targetType->MakeValue(cmsx.util.SignExtend(cast<uint>(value)));
359 }
360 public override ConstantValue* TruncateTo(Type* targetType, int line)
361 {
362 return targetType->MakeValue(cast<ulong>(value));
363 }
364 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
365 {
366 MachineInstruction* tetraInst = machineCode.GetInstruction(cmsx.assembly.TETRA, label);
367 tetraInst->AddOperand(MakeDataOperand(context));
368 label.Clear();
369 }
370 public override Operand* MakeDataOperand(Context& context) const
371 {
372 return context.GetLiteralOperand(cast<uint>(value));
373 }
374 public int value;
375 }
376
377 public class UIntValue : LiteralValue
378 {
379 public default nothrow UIntValue();
380 public nothrow UIntValue(uint value_) : value(value_)
381 {
382 }
383 public override nothrow string Name() const
384 {
385 return ToString(value);
386 }
387 public override nothrow bool IsImmediate(byte& immediateValue) const
388 {
389 if (value <= 255u)
390 {
391 immediateValue = cast<byte>(value);
392 return true;
393 }
394 else
395 {
396 return false;
397 }
398 }
399 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
400 {
401 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
402 setInst->AddOperand(reg);
403 ushort low = cast<ushort>(value);
404 setInst->AddOperand(machineCode.context.GetLiteralOperand(low));
405 ushort high = cast<ushort>(value >> 16u);
406 if (high != 0u)
407 {
408 MachineInstruction* orMLInst = machineCode.GetInstruction(cmsx.machine.ORML, inst);
409 orMLInst->AddOperand(reg);
410 orMLInst->AddOperand(machineCode.context.GetLiteralOperand(high));
411 }
412 }
413 public override ConstantValue* SignExtendTo(Type* targetType, int line)
414 {
415 return targetType->MakeValue(cmsx.util.SignExtend(value));
416 }
417 public override ConstantValue* ZeroExtendTo(Type* targetType, int line)
418 {
419 return targetType->MakeValue(value);
420 }
421 public override ConstantValue* TruncateTo(Type* targetType, int line)
422 {
423 return targetType->MakeValue(cast<ulong>(value));
424 }
425 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
426 {
427 MachineInstruction* tetraInst = machineCode.GetInstruction(cmsx.assembly.TETRA, label);
428 tetraInst->AddOperand(MakeDataOperand(context));
429 label.Clear();
430 }
431 public override Operand* MakeDataOperand(Context& context) const
432 {
433 return context.GetLiteralOperand(value);
434 }
435 public uint value;
436 }
437
438 public class LongValue : LiteralValue
439 {
440 public default nothrow LongValue();
441 public nothrow LongValue(long value_) : value(value_)
442 {
443 }
444 public override nothrow string Name() const
445 {
446 return ToString(value);
447 }
448 public override nothrow bool IsImmediate(byte& immediateValue) const
449 {
450 if (value >= 0 && value <= 255)
451 {
452 immediateValue = cast<byte>(value);
453 return true;
454 }
455 else
456 {
457 return false;
458 }
459 }
460 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
461 {
462 ushort low = cast<ushort>(value);
463 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
464 setInst->AddOperand(reg);
465 setInst->AddOperand(machineCode.context.GetLiteralOperand(low));
466 ushort ml = cast<ushort>(value >> 16u);
467 if (ml != 0u)
468 {
469 MachineInstruction* orMLInst = machineCode.GetInstruction(cmsx.machine.ORML, inst);
470 orMLInst->AddOperand(reg);
471 orMLInst->AddOperand(machineCode.context.GetLiteralOperand(ml));
472 }
473 ushort mh = cast<ushort>(value >> 32u);
474 if (mh != 0u)
475 {
476 MachineInstruction* orMHInst = machineCode.GetInstruction(cmsx.machine.ORMH, inst);
477 orMHInst->AddOperand(reg);
478 orMHInst->AddOperand(machineCode.context.GetLiteralOperand(mh));
479 }
480 ushort h = cast<ushort>(value >> 48u);
481 if (h != 0u)
482 {
483 MachineInstruction* orHInst = machineCode.GetInstruction(cmsx.machine.ORH, inst);
484 orHInst->AddOperand(reg);
485 orHInst->AddOperand(machineCode.context.GetLiteralOperand(h));
486 }
487 }
488 public override ConstantValue* SignExtendTo(Type* targetType, int line)
489 {
490 return targetType->MakeValue(cast<ulong>(value));
491 }
492 public override ConstantValue* TruncateTo(Type* targetType, int line)
493 {
494 return targetType->MakeValue(cast<ulong>(value));
495 }
496 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
497 {
498 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTA, label);
499 octaInst->AddOperand(MakeDataOperand(context));
500 label.Clear();
501 }
502 public override Operand* MakeDataOperand(Context& context) const
503 {
504 return context.GetLiteralOperand(cast<ulong>(value));
505 }
506 public long value;
507 }
508
509 public class ULongValue : LiteralValue
510 {
511 public default nothrow ULongValue();
512 public nothrow ULongValue(ulong value_) : value(value_)
513 {
514 }
515 public override nothrow string Name() const
516 {
517 return ToString(value);
518 }
519 public override nothrow bool IsImmediate(byte& immediateValue) const
520 {
521 if (value <= 255u)
522 {
523 immediateValue = cast<byte>(value);
524 return true;
525 }
526 else
527 {
528 return false;
529 }
530 }
531 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
532 {
533 ushort low = cast<ushort>(value);
534 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
535 setInst->AddOperand(reg);
536 setInst->AddOperand(machineCode.context.GetLiteralOperand(low));
537 ushort ml = cast<ushort>(value >> 16u);
538 if (ml != 0)
539 {
540 MachineInstruction* orMLInst = machineCode.GetInstruction(cmsx.machine.ORML, inst);
541 orMLInst->AddOperand(reg);
542 orMLInst->AddOperand(machineCode.context.GetLiteralOperand(ml));
543 }
544 ushort mh = cast<ushort>(value >> 32u);
545 if (mh != 0u)
546 {
547 MachineInstruction* orMHInst = machineCode.GetInstruction(cmsx.machine.ORMH, inst);
548 orMHInst->AddOperand(reg);
549 orMHInst->AddOperand(machineCode.context.GetLiteralOperand(mh));
550 }
551 ushort h = cast<ushort>(value >> 48u);
552 if (h != 0u)
553 {
554 MachineInstruction* orHInst = machineCode.GetInstruction(cmsx.machine.ORH, inst);
555 orHInst->AddOperand(reg);
556 orHInst->AddOperand(machineCode.context.GetLiteralOperand(h));
557 }
558 }
559 public override ConstantValue* SignExtendTo(Type* targetType, int line)
560 {
561 return targetType->MakeValue(value);
562 }
563 public override ConstantValue* ZeroExtendTo(Type* targetType, int line)
564 {
565 return targetType->MakeValue(value);
566 }
567 public override ConstantValue* TruncateTo(Type* targetType, int line)
568 {
569 return targetType->MakeValue(value);
570 }
571 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
572 {
573 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTA, label);
574 octaInst->AddOperand(MakeDataOperand(context));
575 label.Clear();
576 }
577 public override Operand* MakeDataOperand(Context& context) const
578 {
579 return context.GetLiteralOperand(value);
580 }
581 public ulong value;
582 }
583
584 public class FloatValue : LiteralValue
585 {
586 public default nothrow FloatValue();
587 public nothrow FloatValue(float value_) : value(value_)
588 {
589 }
590 public override nothrow string Name() const
591 {
592 return ToString(value, 1, 15);
593 }
594 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
595 {
596 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
597 setInst->AddOperand(reg);
598 uint x = *cast<uint*>(cast<void*>(&value));
599 ushort low = cast<ushort>(x);
600 setInst->AddOperand(machineCode.context.GetLiteralOperand(low));
601 ushort ml = cast<ushort>(x >> 16u);
602 if (ml != 0)
603 {
604 MachineInstruction* orMLInst = machineCode.GetInstruction(cmsx.machine.ORML, inst);
605 orMLInst->AddOperand(reg);
606 orMLInst->AddOperand(machineCode.context.GetLiteralOperand(ml));
607 }
608 }
609 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
610 {
611 MachineInstruction* tetraInst = machineCode.GetInstruction(cmsx.assembly.TETRA, label);
612 tetraInst->AddOperand(MakeDataOperand(context));
613 label.Clear();
614 }
615 public override Operand* MakeDataOperand(Context& context) const
616 {
617 return context.GetLiteralOperand(*cast<uint*>(cast<void*>(&value)));
618 }
619 public float value;
620 }
621
622 public class DoubleValue : LiteralValue
623 {
624 public default nothrow DoubleValue();
625 public nothrow DoubleValue(double value_) : value(value_)
626 {
627 }
628 public override nothrow string Name() const
629 {
630 return ToString(value, 1, 15);
631 }
632 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
633 {
634 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
635 setInst->AddOperand(reg);
636 ulong x = *cast<ulong*>(cast<void*>(&value));
637 ushort low = cast<ushort>(x);
638 setInst->AddOperand(machineCode.context.GetLiteralOperand(low));
639 ushort ml = cast<ushort>(x >> 16u);
640 if (ml != 0)
641 {
642 MachineInstruction* orMLInst = machineCode.GetInstruction(cmsx.machine.ORML, inst);
643 orMLInst->AddOperand(reg);
644 orMLInst->AddOperand(machineCode.context.GetLiteralOperand(ml));
645 }
646 ushort mh = cast<ushort>(x >> 32u);
647 if (mh != 0u)
648 {
649 MachineInstruction* orMHInst = machineCode.GetInstruction(cmsx.machine.ORMH, inst);
650 orMHInst->AddOperand(reg);
651 orMHInst->AddOperand(machineCode.context.GetLiteralOperand(mh));
652 }
653 ushort h = cast<ushort>(x >> 48u);
654 if (h != 0u)
655 {
656 MachineInstruction* orHInst = machineCode.GetInstruction(cmsx.machine.ORH, inst);
657 orHInst->AddOperand(reg);
658 orHInst->AddOperand(machineCode.context.GetLiteralOperand(h));
659 }
660 }
661 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
662 {
663 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTA, label);
664 octaInst->AddOperand(MakeDataOperand(context));
665 label.Clear();
666 }
667 public override Operand* MakeDataOperand(Context& context) const
668 {
669 return context.GetLiteralOperand(*cast<ulong*>(cast<void*>(&value)));
670 }
671 public double value;
672 }
673
674 public class NullValue : LiteralValue
675 {
676 public nothrow NullValue(PtrType* ptrType_) : ptrType(ptrType_)
677 {
678 type = ptrType;
679 }
680 public override nothrow string Name() const
681 {
682 return "null";
683 }
684 public override void GenerateSetValue(Register* reg, MachineCode& machineCode, int line, Instruction* inst)
685 {
686 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, inst);
687 setInst->AddOperand(reg);
688 setInst->AddOperand(machineCode.context.GetLiteralOperand(0u));
689 }
690 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
691 {
692 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTA, label);
693 octaInst->AddOperand(MakeDataOperand(context));
694 label.Clear();
695 }
696 public override Operand* MakeDataOperand(Context& context) const
697 {
698 return context.GetLiteralOperand(0u);
699 }
700 public PtrType* ptrType;
701 }
702
703 public class PtrValue : ConstantValue
704 {
705 public nothrow PtrValue(PtrType* ptrType_, GlobalVariable* globalVariable_) : globalVariable(globalVariable_)
706 {
707 type = ptrType_;
708 }
709 public override nothrow string Name() const
710 {
711 return globalVariable->Name();
712 }
713 public override nothrow Location* HomeLocation() const
714 {
715 return globalVariable->HomeLocation();
716 }
717 public override Operand* MakeDataOperand(Context& context) const
718 {
719 return context.GetSymbolOperand(globalVariable->name);
720 }
721 public GlobalVariable* globalVariable;
722 }
723
724 public abstract class AggregateValue : ConstantValue
725 {
726 }
727
728 public class ArrayValue : AggregateValue
729 {
730 public nothrow ArrayValue()
731 {
732 }
733 public void AddElement(ConstantValue* element)
734 {
735 elements.Add(element);
736 }
737 public override void Validate(Type* type, const string& index)
738 {
739 if (!(type is ArrayType*))
740 {
741 throw Exception("error: element " + index + " not an array value ('" + type->Name() + "')");
742 }
743 ArrayType* arrayType = cast<ArrayType*>(type);
744 if (arrayType->ElementCount() != elements.Count())
745 {
746 throw Exception("error: element " + index + " has " + ToString(elements.Count()) + " elements, " + ToString(arrayType->ElementCount()) + " elements expected");
747 }
748 this->type = arrayType;
749 int i = 0;
750 for (ConstantValue* element : elements)
751 {
752 element->Validate(arrayType->ElementType(), index + "." + ToString(i));
753 ++i;
754 }
755 }
756 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
757 {
758 ArrayType* arrayType = cast<ArrayType*>(type);
759 MachineInstruction* inst = arrayType->ElementType()->GetDataInstruction(machineCode, line);
760 inst->SetLabel(label);
761 for (ConstantValue* element : elements)
762 {
763 inst->AddOperand(element->MakeDataOperand(context));
764 }
765 label.Clear();
766 }
767 public override nothrow string Name() const
768 {
769 string name = "[ ";
770 bool first = true;
771 for (ConstantValue* element : elements)
772 {
773 if (first)
774 {
775 first = false;
776 }
777 else
778 {
779 name.Append(", ");
780 }
781 if (element is AggregateValue*)
782 {
783 name.Append(element->Name());
784 }
785 else
786 {
787 name.Append(element->type->Name()).Append(' ').Append(element->Name());
788 }
789 }
790 name.Append(" ]");
791 return name;
792 }
793 public List<ConstantValue*> elements;
794 }
795
796 public class StructureValue : AggregateValue
797 {
798 public nothrow StructureValue()
799 {
800 }
801 public void AddMember(ConstantValue* member)
802 {
803 members.Add(member);
804 }
805 public override void Validate(Type* type, const string& index)
806 {
807 if (!(type is StructureType*))
808 {
809 throw Exception("error: element " + index + " is not a structure value ('" + type->Name() + "')");
810 }
811 StructureType* structureType = cast<StructureType*>(type);
812 if (structureType->memberTypes.Count() != members.Count())
813 {
814 throw Exception("error: element " + index + " has " + ToString(members.Count()) + " members, " + ToString(structureType->memberTypes.Count()) + " members expected");
815 }
816 this->type = structureType;
817 long n = members.Count();
818 for (long i = 0; i < n; ++i;)
819 {
820 members[i]->Validate(structureType->memberTypes[i], index + "." + ToString(i));
821 }
822 }
823 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
824 {
825 for (ConstantValue* member : members)
826 {
827 member->GenerateCode(machineCode, label, context);
828 }
829 }
830 public override nothrow string Name() const
831 {
832 string name = "{ ";
833 bool first = true;
834 for (ConstantValue* member : members)
835 {
836 if (first)
837 {
838 first = false;
839 }
840 else
841 {
842 name.Append(", ");
843 }
844 if (member is AggregateValue*)
845 {
846 name.Append(member->Name());
847 }
848 else
849 {
850 name.Append(member->type->Name()).Append(' ').Append(member->Name());
851 }
852 }
853 name.Append(" }");
854 return name;
855 }
856 public List<ConstantValue*> members;
857 }
858
859 public class StringValue : ConstantValue
860 {
861 public nothrow StringValue(const string& value_) : base(), value(value_)
862 {
863 }
864 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
865 {
866 MachineInstruction* inst = machineCode.GetInstruction(cmsx.assembly.BYTE, label);
867 int state = 0;
868 string str;
869 string hex;
870 for (char c : value)
871 {
872 switch (state)
873 {
874 case 0:
875 {
876 if (c == '\\')
877 {
878 if (!str.IsEmpty())
879 {
880 inst->AddOperand(context.GetStringOperand(str));
881 str.Clear();
882 }
883 hex.Clear();
884 state = 1;
885 }
886 else
887 {
888 str.Append(c);
889 }
890 break;
891 }
892 case 1:
893 {
894 hex.Append(c);
895 state = 2;
896 break;
897 }
898 case 2:
899 {
900 hex.Append(c);
901 inst->AddOperand(context.GetLiteralOperand(ParseHexByte(hex)));
902 hex.Clear();
903 state = 0;
904 break;
905 }
906 }
907 }
908 if (state == 0)
909 {
910 if (!str.IsEmpty())
911 {
912 inst->AddOperand(context.GetStringOperand(str));
913 }
914 }
915 else if (state == 1)
916 {
917 throw Exception("two hex characters expected (line=" + ToString(line) + ")");
918 }
919 else if (state == 2)
920 {
921 throw Exception("one hex character expected (line=" + ToString(line) + ")");
922 }
923 }
924 public override nothrow string Name() const
925 {
926 string name = "\"";
927 name.Append(value);
928 name.Append("\"");
929 return name;
930 }
931 public string value;
932 }
933
934 public class StringArrayValue : ArrayValue
935 {
936 public nothrow StringArrayValue(char prefix_) : base(), prefix(prefix_)
937 {
938 }
939 public override void Validate(Type* type, const string& index)
940 {
941 if (this->type != type)
942 {
943 Type* thisType = this->type;
944 throw Exception("error: type conflict: element " + index + " has type '" + thisType->Name() + "', type '" + type->Name() + "' expected");
945 }
946 int i = 0;
947 for (ConstantValue* element : elements)
948 {
949 element->Validate(type, index + "." + ToString(i));
950 ++i;
951 }
952 }
953 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
954 {
955 MachineInstruction* inst = type->GetDataInstruction(machineCode, line);
956 inst->SetLabel(label);
957 for (ConstantValue* element : elements)
958 {
959 inst->AddOperand(element->MakeDataOperand(context));
960 }
961 label.Clear();
962 }
963 public override nothrow string Name() const
964 {
965 string name = ToString(prefix) + base->Name();
966 return name;
967 }
968 private char prefix;
969 }
970
971 public class ConversionValue : ConstantValue
972 {
973 public nothrow ConversionValue(Type* targetType_, ConstantValue* from_) : base(), from(from_)
974 {
975 type = targetType_;
976 }
977 public override nothrow string Name() const
978 {
979 return "conv(" + from->type->Name() + " " + from->Name() + ")";
980 }
981 public override Operand* MakeDataOperand(Context& context) const
982 {
983 return from->MakeDataOperand(context);
984 }
985 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
986 {
987 MachineInstruction* inst = type->GetDataInstruction(machineCode, line);
988 inst->AddOperand(from->MakeDataOperand(context));
989 }
990 private ConstantValue* from;
991 }
992
993 public class IdValue : Value
994 {
995 public IdValue(uint id_) : base(), id(id_)
996 {
997 }
998 public override nothrow string Name() const
999 {
1000 return "$" + ToString(id);
1001 }
1002 public uint id;
1003 }
1004
1005 public class SymbolValue : ConstantValue
1006 {
1007 public nothrow SymbolValue(const string& symbol_) : base(), symbol(symbol_)
1008 {
1009 }
1010 public override nothrow string Name() const
1011 {
1012 return symbol;
1013 }
1014 public override nothrow string PrintName() const
1015 {
1016 return "@" + Name();
1017 }
1018 public override Operand* MakeDataOperand(Context& context) const
1019 {
1020 return context.GetSymbolOperand(symbol);
1021 }
1022 public override void GenerateCode(MachineCode& machineCode, string& label, Context& context)
1023 {
1024 MachineInstruction* inst = machineCode.GetInstruction(cmsx.assembly.OCTA, label);
1025 inst->AddOperand(MakeDataOperand(context));
1026 }
1027 public string symbol;
1028 }
1029
1030 public class ClsIdValue : ConstantValue
1031 {
1032 public ClsIdValue(const string& typeId_) : base(), typeId(typeId_)
1033 {
1034 }
1035 public override nothrow string Name() const
1036 {
1037 return "$CLSID(" + typeId + ")";
1038 }
1039 public override Operand* MakeDataOperand(Context& context) const
1040 {
1041 return context.GetClsIdOperand(typeId);
1042 }
1043 private string typeId;
1044 }
1045 }