1 using System;
2 using System.Collections;
3 using CodeFormatter = System.Text.CodeFormatter;
4
5 namespace cmsx.intermediate
6 {
7 public enum Liveness : byte
8 {
9 dead = 0u, live = 1u
10 }
11
12 public enum Operator : byte
13 {
14 add, sub, mul, div, mod, and_, or_, xor_, shl, shr, equal, less
15 }
16
17 public nothrow const char* LivenessStr(Liveness liveness)
18 {
19 switch (liveness)
20 {
21 case Liveness.dead: return "dead";
22 case Liveness.live: return "live";
23 }
24 return "";
25 }
26
27 public abstract class Instruction : Value
28 {
29 public nothrow Instruction(int line_) : base(), parent(null), index(-1), numUses(0)
30 {
31 base->line = line_;
32 }
33 public virtual void Validate(Function& function, int numArgs)
34 {
35 if (line == 0)
36 {
37 throw Exception("internal error : " + OperationName() + " instruction has no line number information");
38 }
39 if (parent == null)
40 {
41 throw Exception("internal error : " + OperationName() + " instruction at line " + ToString(line) + " has no parent");
42 }
43 index = parent->function.GetNextInstructionIndex();
44 }
45 public abstract nothrow string OperationName() const;
46 public virtual void Print(CodeFormatter& formatter)
47 {
48 if (this is ValueInstruction*)
49 {
50 formatter << OperationName();
51 }
52 else
53 {
54 formatter << Format(IndexStr(), 6, FormatJustify.right) << " ";
55 formatter << Format(OperationName(), 7);
56 }
57 }
58 public nothrow void ComputeLivenessAndNextUse()
59 {
60 BeginComputeLivenessAndNextUse();
61 EndComputeLivenessAndNextUse();
62 }
63 public virtual nothrow void BeginComputeLivenessAndNextUse()
64 {
65 }
66 public virtual nothrow void EndComputeLivenessAndNextUse()
67 {
68 }
69 public void PrintLivenessAndNextUse(int fieldPos, CodeFormatter& formatter)
70 {
71 string s(' ', Max(cast<long>(1), fieldPos - formatter.Pos()));
72 formatter << s << "{";
73 bool first = true;
74 for (const Pair<Value*, Pair<Liveness, Value*>>& p : livenessAndNextUse)
75 {
76 if (first)
77 {
78 first = false;
79 }
80 else
81 {
82 formatter << " | ";
83 }
84 Value* value = p.first;
85 const Pair<Liveness, Value*>& q = p.second;
86 Value* use = q.second;
87 string useStr = "";
88 if (use != null)
89 {
90 useStr = ":" + use->IndexStr();
91 }
92 formatter << value->Name() << ":" << LivenessStr(q.first) << useStr;
93 }
94 formatter << "}";
95 }
96 public override nothrow string IndexStr() const
97 {
98 return "(" + ToString(index) + ")";
99 }
100 public virtual void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
101 {
102 this->machineCode = &machineCode;
103 }
104 public void BeginGenerateCode(MachineCode& machineCode)
105 {
106 if (metadata != null)
107 {
108 MDStruct* metadataStruct = machineCode.context.compileUnit.metadata.GetMDStruct(metadata->id);
109 MDItem* nodeTypeItem = metadataStruct->GetItem("nodeType");
110 if (nodeTypeItem is MDLong*)
111 {
112 long nodeType = cast<MDLong*>(nodeTypeItem)->value;
113 if (nodeType == cast<long>(cmsx.assembly.LINEINFO))
114 {
115 MDItem* lineInfoItem = metadataStruct->GetItem("line");
116 if (lineInfoItem is MDLong*)
117 {
118 lineNumber = cast<uint>(cast<MDLong*>(lineInfoItem)->value);
119 if (machineCode.currentLineNumber == 0u)
120 {
121 machineCode.currentLineNumber = lineNumber;
122 }
123 else if (machineCode.currentLineNumber != lineNumber)
124 {
125 machineCode.EmitLineNumberInfo();
126 machineCode.currentLineNumber = lineNumber;
127 }
128 }
129 else
130 {
131 throw Exception("MDLong expected");
132 }
133 }
134 else if (nodeType == cast<long>(cmsx.assembly.BEGINTRY))
135 {
136 MDItem* tryBlockItem = metadataStruct->GetItem("tryBlockId");
137 if (tryBlockItem is MDLong*)
138 {
139 long tryBlockId = cast<MDLong*>(tryBlockItem)->value;
140 MDItem* parentTryBlockItem = metadataStruct->GetItem("parentTryBlockId");
141 if (parentTryBlockItem is MDLong*)
142 {
143 long parentTryBlockId = cast<MDLong*>(parentTryBlockItem)->value;
144 MachineInstruction* bspecInst = machineCode.GetInstruction(cmsx.assembly.BSPEC, this);
145 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTA, null);
146 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cmsx.assembly.BEGINTRY));
147 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(tryBlockId)));
148 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(parentTryBlockId)));
149 MachineInstruction* especInst = machineCode.GetInstruction(cmsx.assembly.ESPEC, null);
150 }
151 else
152 {
153 throw Exception("MDLong expected");
154 }
155 }
156 else
157 {
158 throw Exception("MDLong expected");
159 }
160 }
161 else if (nodeType == cast<long>(cmsx.assembly.ENDTRY))
162 {
163 MDItem* tryBlockItem = metadataStruct->GetItem("tryBlockId");
164 if (tryBlockItem is MDLong*)
165 {
166 long tryBlockId = cast<MDLong*>(tryBlockItem)->value;
167 MachineInstruction* bspecInst = machineCode.GetInstruction(cmsx.assembly.BSPEC, this);
168 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTA, null);
169 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cmsx.assembly.ENDTRY));
170 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(tryBlockId)));
171 MachineInstruction* especInst = machineCode.GetInstruction(cmsx.assembly.ESPEC, null);
172 }
173 else
174 {
175 throw Exception("MDLong expected");
176 }
177 }
178 else if (nodeType == cast<long>(cmsx.assembly.CATCH))
179 {
180 MDItem* catchBlockItem = metadataStruct->GetItem("catchBlockId");
181 if (catchBlockItem is MDLong*)
182 {
183 long catchBlockId = cast<MDLong*>(catchBlockItem)->value;
184 MDItem* tryBlockItem = metadataStruct->GetItem("tryBlockId");
185 if (tryBlockItem is MDLong*)
186 {
187 long tryBlockId = cast<MDLong*>(tryBlockItem)->value;
188 MDItem* catchedTypeIdItem = metadataStruct->GetItem("catchedTypeId");
189 if (catchedTypeIdItem is MDString*)
190 {
191 string catchedTypeId = cast<MDString*>(catchedTypeIdItem)->value;
192 string catchedTypeIdStr1 = catchedTypeId.Substring(0, 16);
193 string catchedTypeIdStr2 = catchedTypeId.Substring(16, 16);
194 ulong catchedTypeId1 = ParseHexULong(catchedTypeIdStr1);
195 ulong catchedTypeId2 = ParseHexULong(catchedTypeIdStr2);
196 MachineInstruction* bspecInst = machineCode.GetInstruction(cmsx.assembly.BSPEC, this);
197 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTA, null);
198 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cmsx.assembly.CATCH));
199 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(catchBlockId)));
200 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(tryBlockId)));
201 octaInst->AddOperand(machineCode.context.GetLiteralOperand(catchedTypeId1));
202 octaInst->AddOperand(machineCode.context.GetLiteralOperand(catchedTypeId2));
203 MachineInstruction* especInst = machineCode.GetInstruction(cmsx.assembly.ESPEC, null);
204 }
205 else
206 {
207 throw Exception("MDString expected");
208 }
209 }
210 else
211 {
212 throw Exception("MDLong expected");
213 }
214 }
215 else
216 {
217 throw Exception("MDLong expected");
218 }
219 }
220 else if (nodeType == cast<long>(cmsx.assembly.BEGINCLEANUP))
221 {
222 MDItem* cleanupBlockItem = metadataStruct->GetItem("cleanupBlockId");
223 if (cleanupBlockItem is MDLong*)
224 {
225 long cleanupBlockId = cast<MDLong*>(cleanupBlockItem)->value;
226 long tryBlockId = -1;
227 if (metadataStruct->HasItem("tryBlockId"))
228 {
229 MDItem* tryBlockIdItem = metadataStruct->GetItem("tryBlockId");
230 if (tryBlockIdItem is MDLong*)
231 {
232 tryBlockId = cast<MDLong*>(tryBlockIdItem)->value;
233 }
234 else
235 {
236 throw Exception("MDLong expected");
237 }
238 }
239 MachineInstruction* bspecInst = machineCode.GetInstruction(cmsx.assembly.BSPEC, this);
240 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTA, null);
241 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cmsx.assembly.BEGINCLEANUP));
242 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(cleanupBlockId)));
243 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(tryBlockId)));
244 MachineInstruction* especInst = machineCode.GetInstruction(cmsx.assembly.ESPEC, null);
245 }
246 else
247 {
248 throw Exception("MDLong expected");
249 }
250 }
251 else if (nodeType == cast<long>(cmsx.assembly.ENDCLEANUP))
252 {
253 MDItem* cleanupBlockItem = metadataStruct->GetItem("cleanupBlockId");
254 if (cleanupBlockItem is MDLong*)
255 {
256 long cleanupBlockId = cast<MDLong*>(cleanupBlockItem)->value;
257 MachineInstruction* bspecInst = machineCode.GetInstruction(cmsx.assembly.BSPEC, this);
258 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTA, null);
259 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cmsx.assembly.ENDCLEANUP));
260 octaInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(cleanupBlockId)));
261 MachineInstruction* especInst = machineCode.GetInstruction(cmsx.assembly.ESPEC, null);
262 }
263 else
264 {
265 throw Exception("MDLong expected");
266 }
267 }
268 else
269 {
270 throw Exception("unknown metadata nodeType");
271 }
272 }
273 else
274 {
275 throw Exception("MDLong expected");
276 }
277 }
278 this->machineCode = &machineCode;
279 startMachineInstructionIndex = machineCode.CurrentIndex();
280 }
281 public void EndGenerateCode()
282 {
283 endMachineInstructionIndex = machineCode->CurrentIndex();
284 }
285 public void PrintMachineCode(CodeFormatter& formatter, bool& printed)
286 {
287 printed = false;
288 if (startMachineInstructionIndex == endMachineInstructionIndex) return;
289 formatter.WriteLine();
290 formatter.IncIndent();
291 machineCode->PrintRange(startMachineInstructionIndex, endMachineInstructionIndex, formatter);
292 formatter.DecIndent();
293 printed = true;
294 }
295 public nothrow bool IsLeader() const
296 {
297 return parent->GetLeader() == this;
298 }
299 public override nothrow void IncNumUses()
300 {
301 ++numUses;
302 }
303 public BasicBlock* parent;
304 public int index;
305 public HashMap<Value*, Pair<Liveness, Value*>> livenessAndNextUse;
306 public MachineCode* machineCode;
307 public long startMachineInstructionIndex;
308 public long endMachineInstructionIndex;
309 public MDStructRef* metadata;
310 public uint lineNumber;
311 public int numUses;
312 }
313
314 public abstract class TerminatorInstruction : Instruction
315 {
316 public nothrow TerminatorInstruction(int line_) : base(line_)
317 {
318 }
319 }
320
321 public abstract class ValueInstruction : Instruction
322 {
323 public nothrow ValueInstruction(int line_) : base(line_), valueNumber(-1)
324 {
325 }
326 public nothrow void SetResult(Value* result_)
327 {
328 result = result_;
329 }
330 public override void Validate(Function& function, int numArgs)
331 {
332 base->Validate(function, numArgs);
333 if (result == null)
334 {
335 throw Exception("internal error : " + OperationName() + " value instruction at line " + ToString(line) + " has no result value");
336 }
337 type = result->type;
338 if (type == null)
339 {
340 throw Exception("internal error : " + OperationName() + " result type of " + OperationName() + " instruction at line " + ToString(line) + " is null");
341 }
342 if (!(type is ScalarType*))
343 {
344 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a scalar type");
345 }
346 if (type is VoidType*)
347 {
348 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must is void");
349 }
350 }
351 public override nothrow string Name() const
352 {
353 return "$" + ToString(valueNumber);
354 }
355 public override void Print(CodeFormatter& formatter)
356 {
357 string s = Format("(" + ToString(index) + ")", 6, FormatJustify.right);
358 string t = Format(type->Name(), 7, FormatWidth.min);
359 formatter << s << " " << t;
360 valueNumber = parent->function.GetNextValueNumber();
361 formatter << " " << Name() << " = ";
362 base->Print(formatter);
363 }
364 public override nothrow void BeginComputeLivenessAndNextUse()
365 {
366 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(result);
367 if (p != null)
368 {
369 livenessAndNextUse[result] = *p;
370 }
371 }
372 public override nothrow void EndComputeLivenessAndNextUse()
373 {
374 base->EndComputeLivenessAndNextUse();
375 parent->SetValueLivenessAndNextUse(this, Liveness.dead, null);
376 }
377 public inline nothrow Value* Result() const
378 {
379 return result;
380 }
381 public int valueNumber;
382 private Value* result;
383 }
384
385 public abstract class UnaryInstruction : ValueInstruction
386 {
387 public nothrow UnaryInstruction(int line_) : base(line_)
388 {
389 }
390 public nothrow void SetOperand(Value* arg_)
391 {
392 arg = arg_;
393 }
394 public override void Validate(Function& function, int numArgs)
395 {
396 base->Validate(function, numArgs);
397 if (arg == null)
398 {
399 throw Exception("internal error : operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
400 }
401 arg = function.ResolveOperand(line, arg);
402 arg->IncNumUses();
403 }
404 public void ValidateTypes()
405 {
406 if (type != arg->type)
407 {
408 throw Exception("error: the operand type '" + arg->type->Name() + " and result type '" + type->Name() + " differ for instruction " + OperationName() + " at line " + ToString(line));
409 }
410 }
411 public override void Print(CodeFormatter& formatter)
412 {
413 base->Print(formatter);
414 formatter << " " << arg->type->Name() << " " << arg->Name();
415 }
416 public override nothrow void BeginComputeLivenessAndNextUse()
417 {
418 base->BeginComputeLivenessAndNextUse();
419 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(arg);
420 if (p != null)
421 {
422 livenessAndNextUse[arg] = *p;
423 }
424 }
425 public override nothrow void EndComputeLivenessAndNextUse()
426 {
427 base->EndComputeLivenessAndNextUse();
428 parent->SetValueLivenessAndNextUse(arg, Liveness.live, this);
429 }
430 public Value* arg;
431 }
432
433 public abstract class BinaryInstruction : ValueInstruction
434 {
435 public nothrow BinaryInstruction(int line_, Operator binOp_) : base(line_), binOp(binOp_)
436 {
437 }
438 public nothrow void SetOperands(Value* left_, Value* right_)
439 {
440 left = left_;
441 right = right_;
442 }
443 public override void Validate(Function& function, int numArgs)
444 {
445 base->Validate(function, numArgs);
446 if (left == null)
447 {
448 throw Exception("internal error : left operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
449 }
450 if (right == null)
451 {
452 throw Exception("internal error : right operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
453 }
454 left = function.ResolveOperand(line, left);
455 left->IncNumUses();
456 right = function.ResolveOperand(line, right);
457 right->IncNumUses();
458 }
459 public void ValidateTypes()
460 {
461 if (type != left->type || type != right->type)
462 {
463 throw Exception("error: the result type '" + type->Name() + "' differs from the operand types '" + left->type->Name() + " in the " + OperationName() + " instruction at line " + ToString(line));
464 }
465 }
466 public override void Print(CodeFormatter& formatter)
467 {
468 base->Print(formatter);
469 formatter << " " << left->type->Name() << " " << left->Name() << ", " << right->type->Name() << " " << right->Name();
470 }
471 public override nothrow void BeginComputeLivenessAndNextUse()
472 {
473 base->BeginComputeLivenessAndNextUse();
474 Pair<Liveness, Value*>* p1 = parent->GetCurrentLivenessAndNextUse(left);
475 if (p1 != null)
476 {
477 livenessAndNextUse[left] = *p1;
478 }
479 Pair<Liveness, Value*>* p2 = parent->GetCurrentLivenessAndNextUse(right);
480 if (p2 != null)
481 {
482 livenessAndNextUse[right] = *p2;
483 }
484 }
485 public override nothrow void EndComputeLivenessAndNextUse()
486 {
487 base->EndComputeLivenessAndNextUse();
488 parent->SetValueLivenessAndNextUse(left, Liveness.live, this);
489 parent->SetValueLivenessAndNextUse(right, Liveness.live, this);
490 }
491 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
492 {
493 BeginGenerateCode(machineCode);
494 int binOpCode = -1;
495 if (type is BoolType*)
496 {
497 if (left->type is BoolType*)
498 {
499 switch (binOp)
500 {
501 case Operator.equal: binOpCode = cmsx.machine.CMPU; break;
502 case Operator.and_: binOpCode = cmsx.machine.AND; break;
503 case Operator.or_: binOpCode = cmsx.machine.OR; break;
504 case Operator.xor_: binOpCode = cmsx.machine.XOR; break;
505 }
506 }
507 else if (left->type is SignedIntegerType*)
508 {
509 switch (binOp)
510 {
511 case Operator.equal: binOpCode = cmsx.machine.CMP; break;
512 case Operator.less: binOpCode = cmsx.machine.CMP; break;
513 }
514 }
515 else if (left->type is UnsignedIntegerType*)
516 {
517 switch (binOp)
518 {
519 case Operator.equal: binOpCode = cmsx.machine.CMPU; break;
520 case Operator.less: binOpCode = cmsx.machine.CMPU; break;
521 }
522 }
523 else if (left->type is FloatingType*)
524 {
525 switch (binOp)
526 {
527 case Operator.equal: binOpCode = cmsx.machine.FCMP; break;
528 case Operator.less: binOpCode = cmsx.machine.FCMP; break;
529 }
530 }
531 else if (left->type is PtrType*)
532 {
533 switch (binOp)
534 {
535 case Operator.equal: binOpCode = cmsx.machine.CMPU; break;
536 case Operator.less: binOpCode = cmsx.machine.CMPU; break;
537 }
538 }
539 }
540 else if (type is SignedIntegerType*)
541 {
542 switch (binOp)
543 {
544 case Operator.add: binOpCode = cmsx.machine.ADD; break;
545 case Operator.sub: binOpCode = cmsx.machine.SUB; break;
546 case Operator.mul: binOpCode = cmsx.machine.MUL; break;
547 case Operator.div: binOpCode = cmsx.machine.DIV; break;
548 case Operator.mod: binOpCode = cmsx.machine.DIV; break;
549 case Operator.and_: binOpCode = cmsx.machine.AND; break;
550 case Operator.or_: binOpCode = cmsx.machine.OR; break;
551 case Operator.xor_: binOpCode = cmsx.machine.XOR; break;
552 case Operator.shl: binOpCode = cmsx.machine.SL; break;
553 case Operator.shr: binOpCode = cmsx.machine.SR; break;
554 }
555 }
556 else if (type is UnsignedIntegerType*)
557 {
558 switch (binOp)
559 {
560 case Operator.add: binOpCode = cmsx.machine.ADDU; break;
561 case Operator.sub: binOpCode = cmsx.machine.SUBU; break;
562 case Operator.mul: binOpCode = cmsx.machine.MULU; break;
563 case Operator.div: binOpCode = cmsx.machine.DIVU; break;
564 case Operator.mod: binOpCode = cmsx.machine.DIVU; break;
565 case Operator.and_: binOpCode = cmsx.machine.AND; break;
566 case Operator.or_: binOpCode = cmsx.machine.OR; break;
567 case Operator.xor_: binOpCode = cmsx.machine.XOR; break;
568 case Operator.shl: binOpCode = cmsx.machine.SLU; break;
569 case Operator.shr: binOpCode = cmsx.machine.SRU; break;
570 }
571 }
572 else if (type is FloatingType*)
573 {
574 switch (binOp)
575 {
576 case Operator.add: binOpCode = cmsx.machine.FADD; break;
577 case Operator.sub: binOpCode = cmsx.machine.FSUB; break;
578 case Operator.mul: binOpCode = cmsx.machine.FMUL; break;
579 case Operator.div: binOpCode = cmsx.machine.FDIV; break;
580 }
581 }
582 else if (type is PtrType*)
583 {
584 switch (binOp)
585 {
586 case Operator.equal: binOpCode = cmsx.machine.CMPU; break;
587 case Operator.less: binOpCode = cmsx.machine.CMPU; break;
588 }
589 }
590 if (binOpCode == -1)
591 {
592 throw Exception("error: tried to generate binary operator instruction for type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line));
593 }
594 Value* x = this;
595 Value* y = left;
596 Value* z = null;
597 byte immediateValue = 0u;
598 if (!right->IsImmediate(immediateValue))
599 {
600 z = right;
601 }
602 RegisterDescriptor* rx = null;
603 RegisterDescriptor* ry = null;
604 RegisterDescriptor* rz = null;
605 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
606 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
607 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
608 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
609 if (y is LiteralValue*)
610 {
611 y->GenerateSetValue(ry->reg, machineCode, line, this);
612 }
613 else
614 {
615 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
616 }
617 if (z != null)
618 {
619 if (z is LiteralValue*)
620 {
621 z->GenerateSetValue(rz->reg, machineCode, line, this);
622 }
623 else
624 {
625 LoadOperandValue(z, rz, addressDescriptors, machineCode, line, this);
626 }
627 }
628 MachineInstruction* machineInstruction = machineCode.GetInstruction(binOpCode, this);
629 machineInstruction->AddOperand(rx->reg);
630 machineInstruction->AddOperand(ry->reg);
631 if (z != null)
632 {
633 machineInstruction->AddOperand(rz->reg);
634 }
635 else
636 {
637 machineInstruction->AddOperand(machineCode.context.GetLiteralOperand(immediateValue));
638 }
639 rx->SetValue(x);
640 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
641 adx->SetLocation(rx->reg);
642 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
643 EndGenerateCode();
644 if (Flags.Get(Flag.debug))
645 {
646 Print(formatter);
647 formatter.WriteLine();
648 formatter.IncIndent();
649 registerDescriptors.DebugPrint(formatter);
650 addressDescriptors.DebugPrint(formatter);
651 formatter.DecIndent();
652 }
653 }
654 public Value* left;
655 public Value* right;
656 public Operator binOp;
657 }
658
659 public class NoOperationInstruction : Instruction
660 {
661 public nothrow NoOperationInstruction(int line_) : base(line_)
662 {
663 }
664 public override nothrow string Name() const
665 {
666 return "nop";
667 }
668 public override nothrow string OperationName() const
669 {
670 return "nop";
671 }
672 public override void Validate(Function& function, int numArgs)
673 {
674 base->Validate(function, numArgs);
675 }
676 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
677 {
678 BeginGenerateCode(machineCode);
679 EndGenerateCode();
680 }
681 }
682
683 public class SaveInstruction : Instruction
684 {
685 public nothrow SaveInstruction(int line_) : base(line_)
686 {
687 }
688 public override nothrow string Name() const
689 {
690 return "save";
691 }
692 public override nothrow string OperationName() const
693 {
694 return "save";
695 }
696 public override void Validate(Function& function, int numArgs)
697 {
698 base->Validate(function, numArgs);
699 }
700 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
701 {
702 BeginGenerateCode(machineCode);
703 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
704 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
705 int numParamRegs = machineCode.context.regs.GetNumParamRegisters();
706 int numParams = cast<int>(parent->function.type->ParamTypes().Count());
707 int numSaveRegs = Min(numParamRegs, numParams);
708 for (int i = 0; i < numSaveRegs; ++i;)
709 {
710 Register* paramReg = machineCode.context.regs.GetParamRegister(cast<byte>(i));
711 Register* saveReg = machineCode.context.regs.GetLocalRegister(cast<byte>(i));
712 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, null);
713 setInst->AddOperand(saveReg);
714 setInst->AddOperand(paramReg);
715 Value* regParam = parent->function.regParams[i];
716 AddressDescriptor* addressDescriptor = addressDescriptors.GetAddressDescriptor(regParam);
717 addressDescriptor->RemoveLocation(paramReg);
718 addressDescriptor->AddLocation(saveReg);
719 RegisterDescriptor* paramRegisterDescriptor = registerDescriptors.GetRegisterDescriptor(paramReg);
720 paramRegisterDescriptor->values.Clear();
721 RegisterDescriptor* saveRegisterDescriptor = registerDescriptors.GetRegisterDescriptor(saveReg);
722 saveRegisterDescriptor->SetValue(regParam);
723 }
724 registerDescriptors.SetNumUsedLocalRegs(cast<byte>(numSaveRegs));
725 EndGenerateCode();
726 if (Flags.Get(Flag.debug))
727 {
728 Print(formatter);
729 formatter.WriteLine();
730 formatter.IncIndent();
731 registerDescriptors.DebugPrint(formatter);
732 addressDescriptors.DebugPrint(formatter);
733 formatter.DecIndent();
734 }
735 }
736 }
737
738 public class NotInstruction : UnaryInstruction
739 {
740 public nothrow NotInstruction(int line_) : base(line_)
741 {
742 }
743 public override nothrow string OperationName() const
744 {
745 return "not";
746 }
747 public override void Validate(Function& function, int numArgs)
748 {
749 base->Validate(function, numArgs);
750 ValidateTypes();
751 }
752 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
753 {
754 BeginGenerateCode(machineCode);
755 Value* x = this;
756 Value* y = arg;
757 Value* z = type->DefaultValue();
758 if (type->Size() == 1)
759 {
760 z = null;
761 }
762 RegisterDescriptor* rx = null;
763 RegisterDescriptor* ry = null;
764 RegisterDescriptor* rz = null;
765 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
766 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
767 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
768 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
769 if (y is LiteralValue*)
770 {
771 y->GenerateSetValue(ry->reg, machineCode, line, this);
772 }
773 else
774 {
775 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
776 }
777 if (z != null)
778 {
779 type->GenerateMinusOne(machineCode, rz->reg, line, this);
780 ConstantValue* constantValue = new ConstantValue();
781 machineCode.context.AddValue(constantValue);
782 rz->SetValue(constantValue);
783 }
784 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.machine.XOR, this);
785 machineInstruction->AddOperand(rx->reg);
786 machineInstruction->AddOperand(ry->reg);
787 if (z != null)
788 {
789 machineInstruction->AddOperand(rz->reg);
790 }
791 else
792 {
793 machineInstruction->AddOperand(type->HexAllOnes(machineCode.context, line));
794 }
795 rx->SetValue(x);
796 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
797 adx->SetLocation(rx->reg);
798 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
799 EndGenerateCode();
800 if (Flags.Get(Flag.debug))
801 {
802 Print(formatter);
803 formatter.WriteLine();
804 formatter.IncIndent();
805 registerDescriptors.DebugPrint(formatter);
806 addressDescriptors.DebugPrint(formatter);
807 formatter.DecIndent();
808 }
809 }
810 }
811
812 public class NegInstruction : UnaryInstruction
813 {
814 public nothrow NegInstruction(int line_) : base(line_)
815 {
816 }
817 public override nothrow string OperationName() const
818 {
819 return "neg";
820 }
821 public override void Validate(Function& function, int numArgs)
822 {
823 base->Validate(function, numArgs);
824 ValidateTypes();
825 }
826 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
827 {
828 BeginGenerateCode(machineCode);
829 Value* x = this;
830 Value* y = arg;
831 Value* z = null;
832 RegisterDescriptor* rx = null;
833 RegisterDescriptor* ry = null;
834 RegisterDescriptor* rz = null;
835 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
836 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
837 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
838 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
839 if (y is LiteralValue*)
840 {
841 y->GenerateSetValue(ry->reg, machineCode, line, this);
842 }
843 else
844 {
845 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
846 }
847 int negOpCode = -1;
848 if (y->type is SignedIntegerType*)
849 {
850 negOpCode = cmsx.machine.NEG;
851 }
852 else if (y->type is UnsignedIntegerType*)
853 {
854 negOpCode = cmsx.machine.NEGU;
855 }
856 else
857 {
858 throw Exception("error: tried to generate negate operator instruction for type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line));
859 }
860 MachineInstruction* machineInstruction = machineCode.GetInstruction(negOpCode, this);
861 machineInstruction->AddOperand(rx->reg);
862 machineInstruction->AddOperand(ry->reg);
863 rx->SetValue(x);
864 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
865 adx->SetLocation(rx->reg);
866 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
867 EndGenerateCode();
868 if (Flags.Get(Flag.debug))
869 {
870 Print(formatter);
871 formatter.WriteLine();
872 formatter.IncIndent();
873 registerDescriptors.DebugPrint(formatter);
874 addressDescriptors.DebugPrint(formatter);
875 formatter.DecIndent();
876 }
877 }
878 }
879
880 public class AddInstruction : BinaryInstruction
881 {
882 public nothrow AddInstruction(int line_) : base(line_, Operator.add)
883 {
884 }
885 public override nothrow string OperationName() const
886 {
887 return "add";
888 }
889 public override void Validate(Function& function, int numArgs)
890 {
891 base->Validate(function, numArgs);
892 ValidateTypes();
893 }
894 }
895
896 public class SubInstruction : BinaryInstruction
897 {
898 public nothrow SubInstruction(int line_) : base(line_, Operator.sub)
899 {
900 }
901 public override nothrow string OperationName() const
902 {
903 return "sub";
904 }
905 public override void Validate(Function& function, int numArgs)
906 {
907 base->Validate(function, numArgs);
908 ValidateTypes();
909 }
910 }
911
912 public class MulInstruction : BinaryInstruction
913 {
914 public nothrow MulInstruction(int line_) : base(line_, Operator.mul)
915 {
916 }
917 public override nothrow string OperationName() const
918 {
919 return "mul";
920 }
921 public override void Validate(Function& function, int numArgs)
922 {
923 base->Validate(function, numArgs);
924 ValidateTypes();
925 }
926 }
927
928 public class DivInstruction : BinaryInstruction
929 {
930 public nothrow DivInstruction(int line_) : base(line_, Operator.div)
931 {
932 }
933 public override nothrow string OperationName() const
934 {
935 return "div";
936 }
937 public override void Validate(Function& function, int numArgs)
938 {
939 base->Validate(function, numArgs);
940 ValidateTypes();
941 }
942 }
943
944 public class ModInstruction : BinaryInstruction
945 {
946 public nothrow ModInstruction(int line_) : base(line_, Operator.mod)
947 {
948 }
949 public override nothrow string OperationName() const
950 {
951 return "mod";
952 }
953 public override void Validate(Function& function, int numArgs)
954 {
955 base->Validate(function, numArgs);
956 ValidateTypes();
957 }
958 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
959 {
960 base->GenerateCode(machineCode, formatter);
961 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
962 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
963 AddressDescriptor* addressDescriptor = addressDescriptors.GetAddressDescriptor(this);
964 Location* resultLoc = addressDescriptor->GetLocation();
965 if (resultLoc is Register*)
966 {
967 Register* resultReg = cast<Register*>(resultLoc);
968 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.machine.GET, this);
969 machineInstruction->AddOperand(resultReg);
970 machineInstruction->AddOperand(machineCode.context.GetSymbolOperand(cmsx.machine.GetMachine().GetRegisters().GetSpecialRegName(cmsx.machine.Registers.rR)));
971 }
972 else
973 {
974 throw Exception("error: result location is not a register (line " + ToString(line) + ")");
975 }
976 EndGenerateCode();
977 }
978 }
979
980 public class AndInstruction : BinaryInstruction
981 {
982 public nothrow AndInstruction(int line_) : base(line_, Operator.and_)
983 {
984 }
985 public override nothrow string OperationName() const
986 {
987 return "and";
988 }
989 public override void Validate(Function& function, int numArgs)
990 {
991 base->Validate(function, numArgs);
992 ValidateTypes();
993 }
994 }
995
996 public class OrInstruction : BinaryInstruction
997 {
998 public nothrow OrInstruction(int line_) : base(line_, Operator.or_)
999 {
1000 }
1001 public override nothrow string OperationName() const
1002 {
1003 return "or";
1004 }
1005 public override void Validate(Function& function, int numArgs)
1006 {
1007 base->Validate(function, numArgs);
1008 ValidateTypes();
1009 }
1010 }
1011
1012 public class XorInstruction : BinaryInstruction
1013 {
1014 public nothrow XorInstruction(int line_) : base(line_, Operator.xor_)
1015 {
1016 }
1017 public override nothrow string OperationName() const
1018 {
1019 return "xor";
1020 }
1021 public override void Validate(Function& function, int numArgs)
1022 {
1023 base->Validate(function, numArgs);
1024 ValidateTypes();
1025 }
1026 }
1027
1028 public class ShlInstruction : BinaryInstruction
1029 {
1030 public nothrow ShlInstruction(int line_) : base(line_, Operator.shl)
1031 {
1032 }
1033 public override nothrow string OperationName() const
1034 {
1035 return "shl";
1036 }
1037 public override void Validate(Function& function, int numArgs)
1038 {
1039 base->Validate(function, numArgs);
1040 ValidateTypes();
1041 }
1042 }
1043
1044 public class ShrInstruction : BinaryInstruction
1045 {
1046 public nothrow ShrInstruction(int line_) : base(line_, Operator.shr)
1047 {
1048 }
1049 public override nothrow string OperationName() const
1050 {
1051 return "shr";
1052 }
1053 public override void Validate(Function& function, int numArgs)
1054 {
1055 base->Validate(function, numArgs);
1056 ValidateTypes();
1057 }
1058 }
1059
1060 public class EqualInstruction : BinaryInstruction
1061 {
1062 public nothrow EqualInstruction(int line_) : base(line_, Operator.equal)
1063 {
1064 }
1065 public override nothrow string OperationName() const
1066 {
1067 return "equal";
1068 }
1069 public override void Validate(Function& function, int numArgs)
1070 {
1071 base->Validate(function, numArgs);
1072 if (left->type != right->type)
1073 {
1074 throw Exception("error: the left operand type '" + left->type->Name() + " differs from the right operand type '" + right->type->Name() + " in the " + OperationName() + " instruction at line " + ToString(line));
1075 }
1076 if (!(type is BoolType*))
1077 {
1078 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " differs from bool");
1079 }
1080 }
1081 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1082 {
1083 base->GenerateCode(machineCode, formatter);
1084 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1085 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1086 AddressDescriptor* addressDecsriptor = addressDescriptors.GetAddressDescriptor(this);
1087 Location* loc = addressDecsriptor->GetLocation();
1088 if (loc is Register*)
1089 {
1090 Register* reg = cast<Register*>(loc);
1091 MachineInstruction* zsz = machineCode.GetInstruction(cmsx.machine.ZSZ, this);
1092 zsz->AddOperand(reg);
1093 zsz->AddOperand(reg);
1094 zsz->AddOperand(machineCode.context.GetLiteralOperand(1u));
1095 }
1096 else
1097 {
1098 throw Exception("error: result not found in register in the " + OperationName() + " instruction at line " + ToString(line));
1099 }
1100 EndGenerateCode();
1101 }
1102 }
1103
1104 public class LessInstruction : BinaryInstruction
1105 {
1106 public nothrow LessInstruction(int line_) : base(line_, Operator.less)
1107 {
1108 }
1109 public override nothrow string OperationName() const
1110 {
1111 return "less";
1112 }
1113 public override void Validate(Function& function, int numArgs)
1114 {
1115 base->Validate(function, numArgs);
1116 if (left->type != right->type)
1117 {
1118 throw Exception("error: the left operand type '" + left->type->Name() + " differs from the right operand type '" + right->type->Name() + " in the " + OperationName() + " instruction at line " + ToString(line));
1119 }
1120 if (!(type is BoolType*))
1121 {
1122 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " differs from bool");
1123 }
1124 }
1125 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1126 {
1127 base->GenerateCode(machineCode, formatter);
1128 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1129 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1130 AddressDescriptor* addressDecsriptor = addressDescriptors.GetAddressDescriptor(this);
1131 Location* loc = addressDecsriptor->GetLocation();
1132 if (loc is Register*)
1133 {
1134 Register* reg = cast<Register*>(loc);
1135 MachineInstruction* zsn = machineCode.GetInstruction(cmsx.machine.ZSN, this);
1136 zsn->AddOperand(reg);
1137 zsn->AddOperand(reg);
1138 zsn->AddOperand(machineCode.context.GetLiteralOperand(1u));
1139 }
1140 else
1141 {
1142 throw Exception("error: result not found in register in the " + OperationName() + " instruction at line " + ToString(line));
1143 }
1144 EndGenerateCode();
1145 }
1146 }
1147
1148 public class SignExtendInstruction : UnaryInstruction
1149 {
1150 public nothrow SignExtendInstruction(int line_) : base(line_)
1151 {
1152 }
1153 public override nothrow string OperationName() const
1154 {
1155 return "signextend";
1156 }
1157 public override void Validate(Function& function, int numArgs)
1158 {
1159 base->Validate(function, numArgs);
1160 if (!(arg->type is IntegerType*) && !(arg->type is BoolType*))
1161 {
1162 throw Exception("error: the operand type '" + arg->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer or bool type");
1163 }
1164 if (!(type is IntegerType*))
1165 {
1166 throw Exception("error: the result type '" + type->Name() + " in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
1167 }
1168 }
1169 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1170 {
1171 BeginGenerateCode(machineCode);
1172 Value* x = this;
1173 Value* y = arg;
1174 Value* z = null;
1175 RegisterDescriptor* rx = null;
1176 RegisterDescriptor* ry = null;
1177 RegisterDescriptor* rz = null;
1178 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1179 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1180 if (y is LiteralValue*)
1181 {
1182 List<Register*> dontUse;
1183 rx = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
1184 Value* value = y->SignExtendTo(type, line);
1185 machineCode.context.AddValue(value);
1186 value->GenerateSetValue(rx->reg, machineCode, line, this);
1187 }
1188 else
1189 {
1190 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
1191 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
1192 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
1193 ulong numShiftBits = 64u - 8u * cast<ulong>(y->type->Size());
1194 Operand* numShiftBitsOperand = machineCode.context.GetLiteralOperand(numShiftBits);
1195 MachineInstruction* shiftLeftInst = machineCode.GetInstruction(cmsx.machine.SLU, this);
1196 shiftLeftInst->AddOperand(rx->reg);
1197 shiftLeftInst->AddOperand(ry->reg);
1198 shiftLeftInst->AddOperand(numShiftBitsOperand);
1199 MachineInstruction* shiftRightInst = machineCode.GetInstruction(cmsx.machine.SR, this);
1200 shiftRightInst->AddOperand(rx->reg);
1201 shiftRightInst->AddOperand(rx->reg);
1202 shiftRightInst->AddOperand(numShiftBitsOperand);
1203 }
1204 rx->SetValue(x);
1205 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
1206 adx->SetLocation(rx->reg);
1207 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
1208 EndGenerateCode();
1209 if (Flags.Get(Flag.debug))
1210 {
1211 Print(formatter);
1212 formatter.WriteLine();
1213 formatter.IncIndent();
1214 registerDescriptors.DebugPrint(formatter);
1215 addressDescriptors.DebugPrint(formatter);
1216 formatter.DecIndent();
1217 }
1218 }
1219 }
1220
1221 public class ZeroExtendInstruction : UnaryInstruction
1222 {
1223 public nothrow ZeroExtendInstruction(int line_) : base(line_)
1224 {
1225 }
1226 public override nothrow string OperationName() const
1227 {
1228 return "zeroextend";
1229 }
1230 public override void Validate(Function& function, int numArgs)
1231 {
1232 base->Validate(function, numArgs);
1233 if (!(arg->type is IntegerType*) && !(arg->type is BoolType*))
1234 {
1235 throw Exception("error: the operand type '" + arg->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer or bool type");
1236 }
1237 if (!(type is IntegerType*))
1238 {
1239 throw Exception("error: the result type '" + type->Name() + " in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
1240 }
1241 }
1242 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1243 {
1244 BeginGenerateCode(machineCode);
1245 Value* x = this;
1246 Value* y = arg;
1247 Value* z = null;
1248 RegisterDescriptor* rx = null;
1249 RegisterDescriptor* ry = null;
1250 RegisterDescriptor* rz = null;
1251 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1252 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1253 if (y is LiteralValue*)
1254 {
1255 List<Register*> dontUse;
1256 rx = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
1257 Value* value = y->ZeroExtendTo(type, line);
1258 machineCode.context.AddValue(value);
1259 value->GenerateSetValue(rx->reg, machineCode, line, this);
1260 }
1261 else
1262 {
1263 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
1264 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
1265 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
1266 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.SET, this);
1267 machineInstruction->AddOperand(rx->reg);
1268 machineInstruction->AddOperand(ry->reg);
1269 }
1270 rx->SetValue(x);
1271 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
1272 adx->SetLocation(rx->reg);
1273 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
1274 EndGenerateCode();
1275 if (Flags.Get(Flag.debug))
1276 {
1277 Print(formatter);
1278 formatter.WriteLine();
1279 formatter.IncIndent();
1280 registerDescriptors.DebugPrint(formatter);
1281 addressDescriptors.DebugPrint(formatter);
1282 formatter.DecIndent();
1283 }
1284 }
1285 }
1286
1287 public class TruncateInstruction : UnaryInstruction
1288 {
1289 public nothrow TruncateInstruction(int line_) : base(line_)
1290 {
1291 }
1292 public override nothrow string OperationName() const
1293 {
1294 return "truncate";
1295 }
1296 public override void Validate(Function& function, int numArgs)
1297 {
1298 base->Validate(function, numArgs);
1299 if (!(arg->type is IntegerType*))
1300 {
1301 throw Exception("error: the operand type '" + arg->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
1302 }
1303 if (!((type is IntegerType*) || (type is BoolType*)))
1304 {
1305 throw Exception("error: the result type '" + type->Name() + "' for the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer or Boolean type");
1306 }
1307 }
1308 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1309 {
1310 BeginGenerateCode(machineCode);
1311 Value* x = this;
1312 Value* y = arg;
1313 Value* z = null;
1314 RegisterDescriptor* rx = null;
1315 RegisterDescriptor* ry = null;
1316 RegisterDescriptor* rz = null;
1317 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1318 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1319 if (y is LiteralValue*)
1320 {
1321 List<Register*> dontUse;
1322 rx = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
1323 Value* value = y->TruncateTo(type, line);
1324 machineCode.context.AddValue(value);
1325 value->GenerateSetValue(rx->reg, machineCode, line, this);
1326 }
1327 else
1328 {
1329 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
1330 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
1331 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
1332 List<Register*> dontUse;
1333 dontUse.Add(rx->reg);
1334 dontUse.Add(ry->reg);
1335 rz = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
1336 type->GenerateMinusOne(machineCode, rz->reg, line, this);
1337 ConstantValue* constantValue = new ConstantValue();
1338 machineCode.context.AddValue(constantValue);
1339 rz->SetValue(constantValue);
1340 MachineInstruction* andInst = machineCode.GetInstruction(cmsx.machine.AND, this);
1341 andInst->AddOperand(rx->reg);
1342 andInst->AddOperand(ry->reg);
1343 andInst->AddOperand(rz->reg);
1344 if (x->type is SignedIntegerType*)
1345 {
1346 ulong numShiftBits = 64u - 8u * cast<ulong>(x->type->Size());
1347 Operand* numShiftBitsOperand = machineCode.context.GetLiteralOperand(numShiftBits);
1348 MachineInstruction* shiftLeftInst = machineCode.GetInstruction(cmsx.machine.SLU, this);
1349 shiftLeftInst->AddOperand(rx->reg);
1350 shiftLeftInst->AddOperand(rx->reg);
1351 shiftLeftInst->AddOperand(numShiftBitsOperand);
1352 MachineInstruction* shiftRightInst = machineCode.GetInstruction(cmsx.machine.SR, this);
1353 shiftRightInst->AddOperand(rx->reg);
1354 shiftRightInst->AddOperand(rx->reg);
1355 shiftRightInst->AddOperand(numShiftBitsOperand);
1356 }
1357 }
1358 rx->SetValue(x);
1359 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
1360 adx->SetLocation(rx->reg);
1361 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
1362 EndGenerateCode();
1363 if (Flags.Get(Flag.debug))
1364 {
1365 Print(formatter);
1366 formatter.WriteLine();
1367 formatter.IncIndent();
1368 registerDescriptors.DebugPrint(formatter);
1369 addressDescriptors.DebugPrint(formatter);
1370 formatter.DecIndent();
1371 }
1372 }
1373 }
1374
1375 public class BitCastInstruction : UnaryInstruction
1376 {
1377 public nothrow BitCastInstruction(int line_) : base(line_)
1378 {
1379 }
1380 public override nothrow string OperationName() const
1381 {
1382 return "bitcast";
1383 }
1384 public override void Validate(Function& function, int numArgs)
1385 {
1386 base->Validate(function, numArgs);
1387 if (!((arg->type is ScalarType*) || (arg->type is FunctionType*)))
1388 {
1389 throw Exception("error: the operand type '" + arg->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a scalar or function type");
1390 }
1391 if (!(type is ScalarType*))
1392 {
1393 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a scalar type");
1394 }
1395 if (arg is SymbolValue*)
1396 {
1397 string addrValueName = arg->Name() + "_addr";
1398 GlobalVariable* addrVar = function.context.GetGlobalVariableNothrow(addrValueName);
1399 if (addrVar == null)
1400 {
1401 function.context.AddGlobalVariable(function.context.GetPtrType(function.context.GetVoidType()), addrValueName, cast<SymbolValue*>(arg), 0, true);
1402 }
1403 }
1404 }
1405 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1406 {
1407 BeginGenerateCode(machineCode);
1408 Value* x = this;
1409 Value* y = arg;
1410 Value* z = null;
1411 RegisterDescriptor* rx = null;
1412 RegisterDescriptor* ry = null;
1413 RegisterDescriptor* rz = null;
1414 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1415 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1416 bool loaded = false;
1417 if (y is LiteralValue*)
1418 {
1419 List<Register*> dontUse;
1420 rx = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
1421 y->GenerateSetValue(rx->reg, machineCode, line, this);
1422 loaded = true;
1423 }
1424 else if (y is LocalInstruction*)
1425 {
1426 List<Register*> dontUse;
1427 rx = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
1428 LoadOperandAddress(y, rx, addressDescriptors, machineCode, line, this);
1429 loaded = true;
1430 }
1431 else if (y is PtrValue*)
1432 {
1433 PtrValue* ptrValue = cast<PtrValue*>(y);
1434 Type* type = ptrValue->globalVariable->type;
1435 if (type is ArrayType* || type is StructureType*)
1436 {
1437 List<Register*> dontUse;
1438 rx = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
1439 LoadOperandAddress(y, rx, addressDescriptors, machineCode, line, this);
1440 loaded = true;
1441 }
1442 }
1443 else if (y is SymbolValue*)
1444 {
1445 string addrValueName = y->Name() + "_addr";
1446 MachineInstruction* loadAddrInstruction = machineCode.GetInstruction(cmsx.machine.LDOU, this);
1447 List<Register*> dontUse;
1448 rx = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
1449 loadAddrInstruction->AddOperand(rx->reg);
1450 loadAddrInstruction->AddOperand(machineCode.context.GetSymbolOperand(addrValueName));
1451 MachineInstruction* loadInstruction = machineCode.GetInstruction(cmsx.machine.LDOU, this);
1452 loadInstruction->AddOperand(rx->reg);
1453 loadInstruction->AddOperand(rx->reg);
1454 loadInstruction->AddOperand(machineCode.context.GetLiteralOperand(0u));
1455 loaded = true;
1456 }
1457 if (!loaded)
1458 {
1459 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
1460 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
1461 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
1462 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.SET, this);
1463 machineInstruction->AddOperand(rx->reg);
1464 machineInstruction->AddOperand(ry->reg);
1465 }
1466 rx->SetValue(x);
1467 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
1468 adx->SetLocation(rx->reg);
1469 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
1470 EndGenerateCode();
1471 if (Flags.Get(Flag.debug))
1472 {
1473 Print(formatter);
1474 formatter.WriteLine();
1475 formatter.IncIndent();
1476 registerDescriptors.DebugPrint(formatter);
1477 addressDescriptors.DebugPrint(formatter);
1478 formatter.DecIndent();
1479 }
1480 }
1481 }
1482
1483 public class IntToFloatInstruction : UnaryInstruction
1484 {
1485 public nothrow IntToFloatInstruction(int line_) : base(line_)
1486 {
1487 }
1488 public override nothrow string OperationName() const
1489 {
1490 return "inttofloat";
1491 }
1492 public override void Validate(Function& function, int numArgs)
1493 {
1494 base->Validate(function, numArgs);
1495 if (!(arg->type is IntegerType*))
1496 {
1497 throw Exception("error: the operand type '" + arg->type->Name() + " in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
1498 }
1499 if (!(type is FloatingType*))
1500 {
1501 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a floating type");
1502 }
1503 }
1504 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1505 {
1506 BeginGenerateCode(machineCode);
1507 Value* x = this;
1508 Value* y = arg;
1509 Value* z = null;
1510 RegisterDescriptor* rx = null;
1511 RegisterDescriptor* ry = null;
1512 RegisterDescriptor* rz = null;
1513 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1514 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1515 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
1516 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
1517 if (y is LiteralValue*)
1518 {
1519 y->GenerateSetValue(ry->reg, machineCode, line, this);
1520 }
1521 else
1522 {
1523 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
1524 }
1525 int flotInst = -1;
1526 if (y->type is SignedIntegerType*)
1527 {
1528 if (type is DoubleType*)
1529 {
1530 flotInst = cmsx.machine.FLOT;
1531 }
1532 else if (type is FloatType*)
1533 {
1534 flotInst = cmsx.machine.SFLOT;
1535 }
1536 }
1537 else if (y->type is UnsignedIntegerType*)
1538 {
1539 if (type is DoubleType*)
1540 {
1541 flotInst = cmsx.machine.FLOTU;
1542 }
1543 else if (type is FloatType*)
1544 {
1545 flotInst = cmsx.machine.SFLOTU;
1546 }
1547 }
1548 else
1549 {
1550 throw Exception("error: tried to generate fixed to floating conversion for type '" + y->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line));
1551 }
1552 MachineInstruction* machineInstruction = machineCode.GetInstruction(flotInst, this);
1553 machineInstruction->AddOperand(rx->reg);
1554 machineInstruction->AddOperand(ry->reg);
1555 rx->SetValue(x);
1556 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
1557 adx->SetLocation(rx->reg);
1558 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
1559 EndGenerateCode();
1560 if (Flags.Get(Flag.debug))
1561 {
1562 Print(formatter);
1563 formatter.WriteLine();
1564 formatter.IncIndent();
1565 registerDescriptors.DebugPrint(formatter);
1566 addressDescriptors.DebugPrint(formatter);
1567 formatter.DecIndent();
1568 }
1569 }
1570 }
1571
1572 public class FloatToIntInstruction : UnaryInstruction
1573 {
1574 public nothrow FloatToIntInstruction(int line_) : base(line_)
1575 {
1576 }
1577 public override nothrow string OperationName() const
1578 {
1579 return "floattoint";
1580 }
1581 public override void Validate(Function& function, int numArgs)
1582 {
1583 base->Validate(function, numArgs);
1584 if (!(arg->type is FloatingType*))
1585 {
1586 throw Exception("error: the operand type '" + arg->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a floating type");
1587 }
1588 if (!(type is IntegerType*))
1589 {
1590 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
1591 }
1592 }
1593 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1594 {
1595 BeginGenerateCode(machineCode);
1596 Value* x = this;
1597 Value* y = arg;
1598 Value* z = null;
1599 RegisterDescriptor* rx = null;
1600 RegisterDescriptor* ry = null;
1601 RegisterDescriptor* rz = null;
1602 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1603 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1604 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
1605 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
1606 if (y is LiteralValue*)
1607 {
1608 y->GenerateSetValue(ry->reg, machineCode, line, this);
1609 }
1610 else
1611 {
1612 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
1613 }
1614 int fixInst = -1;
1615 if (type is SignedIntegerType*)
1616 {
1617 fixInst = cmsx.machine.FIX;
1618 }
1619 else if (type is UnsignedIntegerType*)
1620 {
1621 fixInst = cmsx.machine.FIXU;
1622 }
1623 else
1624 {
1625 throw Exception("error: tried to generate floating to fixed conversion for type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line));
1626 }
1627 MachineInstruction* machineInstruction = machineCode.GetInstruction(fixInst, this);
1628 machineInstruction->AddOperand(rx->reg);
1629 machineInstruction->AddOperand(ry->reg);
1630 rx->SetValue(x);
1631 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
1632 adx->SetLocation(rx->reg);
1633 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
1634 EndGenerateCode();
1635 if (Flags.Get(Flag.debug))
1636 {
1637 Print(formatter);
1638 formatter.WriteLine();
1639 formatter.IncIndent();
1640 registerDescriptors.DebugPrint(formatter);
1641 addressDescriptors.DebugPrint(formatter);
1642 formatter.DecIndent();
1643 }
1644 }
1645 }
1646
1647 public class IntToPtrInstruction : UnaryInstruction
1648 {
1649 public nothrow IntToPtrInstruction(int line_) : base(line_)
1650 {
1651 }
1652 public override nothrow string OperationName() const
1653 {
1654 return "inttoptr";
1655 }
1656 public override void Validate(Function& function, int numArgs)
1657 {
1658 base->Validate(function, numArgs);
1659 if (!(arg->type is IntegerType*))
1660 {
1661 throw Exception("error: the operand type '" + arg->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
1662 }
1663 if (!(type is PtrType*))
1664 {
1665 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
1666 }
1667 }
1668 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1669 {
1670 BeginGenerateCode(machineCode);
1671 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1672 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1673 Value* x = this;
1674 Value* y = arg;
1675 Value* z = null;
1676 RegisterDescriptor* rx = null;
1677 RegisterDescriptor* ry = null;
1678 RegisterDescriptor* rz = null;
1679 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
1680 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
1681 if (y is LiteralValue*)
1682 {
1683 y->GenerateSetValue(ry->reg, machineCode, line, this);
1684 }
1685 else
1686 {
1687 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
1688 }
1689 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.SET, this);
1690 machineInstruction->AddOperand(rx->reg);
1691 machineInstruction->AddOperand(ry->reg);
1692 rx->SetValue(x);
1693 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
1694 adx->SetLocation(rx->reg);
1695 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
1696 EndGenerateCode();
1697 if (Flags.Get(Flag.debug))
1698 {
1699 Print(formatter);
1700 formatter.WriteLine();
1701 formatter.IncIndent();
1702 registerDescriptors.DebugPrint(formatter);
1703 addressDescriptors.DebugPrint(formatter);
1704 formatter.DecIndent();
1705 }
1706 }
1707 }
1708
1709 public class PtrToIntInstruction : UnaryInstruction
1710 {
1711 public nothrow PtrToIntInstruction(int line_) : base(line_)
1712 {
1713 }
1714 public override nothrow string OperationName() const
1715 {
1716 return "ptrtoint";
1717 }
1718 public override void Validate(Function& function, int numArgs)
1719 {
1720 base->Validate(function, numArgs);
1721 if (!(arg->type is PtrType*))
1722 {
1723 throw Exception("error: the operand type '" + arg->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
1724 }
1725 if (!(type is IntegerType*))
1726 {
1727 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
1728 }
1729 }
1730 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1731 {
1732 BeginGenerateCode(machineCode);
1733 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1734 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1735 Value* x = this;
1736 Value* y = arg;
1737 Value* z = null;
1738 RegisterDescriptor* rx = null;
1739 RegisterDescriptor* ry = null;
1740 RegisterDescriptor* rz = null;
1741 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
1742 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
1743 if (y is LiteralValue*)
1744 {
1745 y->GenerateSetValue(ry->reg, machineCode, line, this);
1746 }
1747 else
1748 {
1749 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
1750 }
1751 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.SET, this);
1752 machineInstruction->AddOperand(rx->reg);
1753 machineInstruction->AddOperand(ry->reg);
1754 rx->SetValue(x);
1755 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
1756 adx->SetLocation(rx->reg);
1757 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
1758 EndGenerateCode();
1759 if (Flags.Get(Flag.debug))
1760 {
1761 Print(formatter);
1762 formatter.WriteLine();
1763 formatter.IncIndent();
1764 registerDescriptors.DebugPrint(formatter);
1765 addressDescriptors.DebugPrint(formatter);
1766 formatter.DecIndent();
1767 }
1768 }
1769 }
1770
1771 public class ParamInstruction : ValueInstruction
1772 {
1773 public nothrow ParamInstruction(Value* result_, int line_) : base(line_), homeLocation(null)
1774 {
1775 SetResult(result_);
1776 }
1777 public override nothrow string OperationName() const
1778 {
1779 return "param";
1780 }
1781 public override void Validate(Function& function, int numArgs)
1782 {
1783 base->Validate(function, numArgs);
1784 }
1785 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1786 {
1787 BeginGenerateCode(machineCode);
1788 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1789 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1790 homeLocation = parent->function.frameLocations.GetFrameLocation(type->Size());
1791 Registers& regs = parent->function.context.regs;
1792 if (index < regs.GetNumParamRegisters())
1793 {
1794 Register* paramReg = regs.GetParamRegister(cast<byte>(index));
1795 RegisterDescriptor* registerDescriptor = registerDescriptors.GetRegisterDescriptor(paramReg);
1796 registerDescriptor->SetValue(this);
1797 AddressDescriptor* addressDescriptor = addressDescriptors.GetAddressDescriptor(this);
1798 addressDescriptor->AddLocation(paramReg);
1799 parent->function.regParams.Add(this);
1800 }
1801 else
1802 {
1803 AddressDescriptor* addressDescriptor = addressDescriptors.GetAddressDescriptor(this);
1804 addressDescriptor->AddLocation(homeLocation);
1805 }
1806 EndGenerateCode();
1807 if (Flags.Get(Flag.debug))
1808 {
1809 Print(formatter);
1810 formatter.WriteLine();
1811 formatter.IncIndent();
1812 registerDescriptors.DebugPrint(formatter);
1813 addressDescriptors.DebugPrint(formatter);
1814 formatter.DecIndent();
1815 }
1816 }
1817 public override nothrow Location* HomeLocation() const
1818 {
1819 return homeLocation;
1820 }
1821 public Location* homeLocation;
1822 }
1823
1824 public class LocalInstruction : ValueInstruction
1825 {
1826 public nothrow LocalInstruction(Value* result_, Type* localType_, int line_) : base(line_), localType(localType_), homeLocation(null)
1827 {
1828 SetResult(result_);
1829 }
1830 public override nothrow string OperationName() const
1831 {
1832 return "local";
1833 }
1834 public override void Validate(Function& function, int numArgs)
1835 {
1836 base->Validate(function, numArgs);
1837 if (localType == null)
1838 {
1839 throw Exception("internal error : local type operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
1840 }
1841 if (!(type is PtrType*))
1842 {
1843 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
1844 }
1845 PtrType* ptrType = cast<PtrType*>(type);
1846 if (ptrType->BaseType() != localType)
1847 {
1848 throw Exception("error: the base type of result pointer type for the " + OperationName() + " instruction at line " + ToString(line) + " must be same as the local type '" + localType->Name() + "'");
1849 }
1850 }
1851 public override void Print(CodeFormatter& formatter)
1852 {
1853 base->Print(formatter);
1854 formatter << " " << localType->Name();
1855 }
1856 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1857 {
1858 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1859 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1860 BeginGenerateCode(machineCode);
1861 homeLocation = parent->function.frameLocations.GetFrameLocation(localType->Size());
1862 EndGenerateCode();
1863 if (Flags.Get(Flag.debug))
1864 {
1865 Print(formatter);
1866 formatter.WriteLine();
1867 formatter.IncIndent();
1868 registerDescriptors.DebugPrint(formatter);
1869 addressDescriptors.DebugPrint(formatter);
1870 formatter.DecIndent();
1871 }
1872 }
1873 public override nothrow Location* HomeLocation() const
1874 {
1875 return homeLocation;
1876 }
1877 public Type* localType;
1878 public Location* homeLocation;
1879 }
1880
1881 public class LoadInstruction : ValueInstruction
1882 {
1883 public nothrow LoadInstruction(Value* result_, Value* ptr_, int line_) : base(line_), ptr(ptr_)
1884 {
1885 SetResult(result_);
1886 }
1887 public override nothrow string OperationName() const
1888 {
1889 return "load";
1890 }
1891 public override void Validate(Function& function, int numArgs)
1892 {
1893 base->Validate(function, numArgs);
1894 ptr = function.ResolveOperand(line, ptr);
1895 if (ptr == null)
1896 {
1897 throw Exception("internal error : ptr operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
1898 }
1899 if (!(ptr->type is PtrType*))
1900 {
1901 throw Exception("error: the operand type '" + ptr->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
1902 }
1903 PtrType* ptrType = cast<PtrType*>(ptr->type);
1904 if (ptrType->BaseType() != type)
1905 {
1906 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be same as the base type of the operand pointer type");
1907 }
1908 }
1909 public override void Print(CodeFormatter& formatter)
1910 {
1911 base->Print(formatter);
1912 formatter << " " << ptr->type->Name() << " " << ptr->Name();
1913 }
1914 public override nothrow void BeginComputeLivenessAndNextUse()
1915 {
1916 base->BeginComputeLivenessAndNextUse();
1917 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(ptr);
1918 if (p != null)
1919 {
1920 livenessAndNextUse[ptr] = *p;
1921 }
1922 }
1923 public override nothrow void EndComputeLivenessAndNextUse()
1924 {
1925 base->EndComputeLivenessAndNextUse();
1926 parent->SetValueLivenessAndNextUse(ptr, Liveness.live, this);
1927 }
1928 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
1929 {
1930 BeginGenerateCode(machineCode);
1931 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
1932 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
1933 List<Register*> dontUse;
1934 RegisterDescriptor* destinationRegisterDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
1935 AddressDescriptor* ptrAddressDescriptor = addressDescriptors.GetAddressDescriptor(ptr);
1936 Location* location = null;
1937 if (ptr is LoadInstruction*)
1938 {
1939 location = ptrAddressDescriptor->GetLocation();
1940 }
1941 else
1942 {
1943 location = ptr->HomeLocation();
1944 }
1945 if (location == null)
1946 {
1947 location = ptrAddressDescriptor->GetMemoryLocation();
1948 }
1949 if (location != null)
1950 {
1951 int loadOpCode = type->GetLoadOp(line);
1952 location->GenerateLoad(loadOpCode, destinationRegisterDescriptor->reg, machineCode, this);
1953 destinationRegisterDescriptor->SetValue(this);
1954 destinationRegisterDescriptor->loaded = true;
1955 addressDescriptors.RemoveRegisterFromAllBut(this, destinationRegisterDescriptor->reg);
1956 AddressDescriptor* resultAddressDescriptor = addressDescriptors.GetAddressDescriptor(this);
1957 resultAddressDescriptor->AddLocation(destinationRegisterDescriptor->reg);
1958 }
1959 else
1960 {
1961 throw Exception("location for '" + ptr->Name() + "' not found (line " + ToString(line) + ")");
1962 }
1963 EndGenerateCode();
1964 if (Flags.Get(Flag.debug))
1965 {
1966 Print(formatter);
1967 formatter.WriteLine();
1968 formatter.IncIndent();
1969 registerDescriptors.DebugPrint(formatter);
1970 addressDescriptors.DebugPrint(formatter);
1971 formatter.DecIndent();
1972 }
1973 }
1974 public Value* ptr;
1975 }
1976
1977 public class StoreInstruction : Instruction
1978 {
1979 public nothrow StoreInstruction(Value* value_, Value* ptr_, int line_) : base(line_), value(value_), ptr(ptr_)
1980 {
1981 }
1982 public override nothrow string Name() const
1983 {
1984 return "store";
1985 }
1986 public override nothrow string OperationName() const
1987 {
1988 return "store";
1989 }
1990 public override void Validate(Function& function, int numArgs)
1991 {
1992 base->Validate(function, numArgs);
1993 value = function.ResolveOperand(line, value);
1994 ptr = function.ResolveOperand(line, ptr);
1995 if (value == null)
1996 {
1997 throw Exception("internal error: value operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
1998 }
1999 if (ptr == null)
2000 {
2001 throw Exception("internal error: ptr operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
2002 }
2003 if (!(ptr->type is PtrType*))
2004 {
2005 throw Exception("error: the second operand type '" + ptr->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
2006 }
2007 PtrType* ptrType = cast<PtrType*>(ptr->type);
2008 Type* baseType = ptrType->BaseType();
2009 Type* valueType = value->type;
2010 if (!(((valueType is FloatType*) && (baseType is DoubleType*) || (valueType is DoubleType*) && (baseType is FloatType*)) || baseType == valueType))
2011 {
2012 throw Exception("error: the first operand type '" + value->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be same as the base type of the second operand pointer type");
2013 }
2014 }
2015 public override void Print(CodeFormatter& formatter)
2016 {
2017 base->Print(formatter);
2018 formatter << " " << value->type->Name() << " " << value->Name() << ", " << ptr->type->Name() << " " << ptr->Name();
2019 }
2020 public override nothrow void BeginComputeLivenessAndNextUse()
2021 {
2022 base->BeginComputeLivenessAndNextUse();
2023 Pair<Liveness, Value*>* p1 = parent->GetCurrentLivenessAndNextUse(value);
2024 if (p1 != null)
2025 {
2026 livenessAndNextUse[value] = *p1;
2027 }
2028 Pair<Liveness, Value*>* p2 = parent->GetCurrentLivenessAndNextUse(ptr);
2029 if (p2 != null)
2030 {
2031 livenessAndNextUse[ptr] = *p2;
2032 }
2033 }
2034 public override nothrow void EndComputeLivenessAndNextUse()
2035 {
2036 parent->SetValueLivenessAndNextUse(ptr, Liveness.dead, null);
2037 base->EndComputeLivenessAndNextUse();
2038 parent->SetValueLivenessAndNextUse(value, Liveness.live, this);
2039 }
2040 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
2041 {
2042 BeginGenerateCode(machineCode);
2043 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
2044 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
2045 Register* valueReg = null;
2046 bool loaded = false;
2047 if (value is LiteralValue*)
2048 {
2049 List<Register*> dontUse;
2050 RegisterDescriptor* valueRegisterDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
2051 valueReg = valueRegisterDescriptor->reg;
2052 value->GenerateSetValue(valueRegisterDescriptor->reg, machineCode, line, this);
2053 loaded = true;
2054 }
2055 else if (value is LocalInstruction*)
2056 {
2057 List<Register*> dontUse;
2058 RegisterDescriptor* valueRegisterDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
2059 LoadOperandAddress(value, valueRegisterDescriptor, addressDescriptors, machineCode, line, this);
2060 valueReg = valueRegisterDescriptor->reg;
2061 loaded = true;
2062 }
2063 else if (value is PtrValue*)
2064 {
2065 PtrValue* ptrValue = cast<PtrValue*>(value);
2066 ConstantValue* initializer = ptrValue->globalVariable->initializer;
2067 if (initializer != null && ((initializer is StringValue*) || (initializer is StringArrayValue*)))
2068 {
2069 List<Register*> dontUse;
2070 RegisterDescriptor* valueRegisterDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
2071 valueReg = valueRegisterDescriptor->reg;
2072 LoadOperandAddress(value, valueRegisterDescriptor, addressDescriptors, machineCode, line, this);
2073 loaded = true;
2074 }
2075 }
2076 if (!loaded)
2077 {
2078 AddressDescriptor* valueAddressDescriptor = addressDescriptors.GetAddressDescriptor(value);
2079 Location* valueLoc = valueAddressDescriptor->GetLocation();
2080 if (valueLoc == null)
2081 {
2082 valueLoc = value->HomeLocation();
2083 }
2084 if (valueLoc != null)
2085 {
2086 if ((valueLoc is Register*))
2087 {
2088 valueReg = cast<Register*>(valueLoc);
2089 }
2090 else
2091 {
2092 List<Register*> dontUse;
2093 RegisterDescriptor* destinationRegisterDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
2094 int loadOpCode = value->type->GetLoadOp(line);
2095 valueLoc->GenerateLoad(loadOpCode, destinationRegisterDescriptor->reg, machineCode, this);
2096 valueReg = destinationRegisterDescriptor->reg;
2097 destinationRegisterDescriptor->SetValue(value);
2098 valueAddressDescriptor->AddLocation(valueReg);
2099 }
2100 }
2101 else
2102 {
2103 throw Exception("value location is null in the " + OperationName() + " instruction at line " + ToString(line));
2104 }
2105 }
2106 AddressDescriptor* ptrAddressDescriptor = addressDescriptors.GetAddressDescriptor(ptr);
2107 Location* ptrLoc = null;
2108 if (ptr is LoadInstruction*)
2109 {
2110 ptrLoc = ptrAddressDescriptor->GetLocation();
2111 }
2112 else
2113 {
2114 ptrLoc = ptr->HomeLocation();
2115 }
2116 if (ptrLoc == null)
2117 {
2118 ptrLoc = ptrAddressDescriptor->GetMemoryLocation();
2119 }
2120 if (ptrLoc != null)
2121 {
2122 int storeOpCode = 0;
2123 if ((value->type is DoubleType*) && (ptr->type->BaseType() is FloatType*))
2124 {
2125 storeOpCode = ptr->type->BaseType()->GetStoreOp(line);
2126 }
2127 else if ((value->type is FloatType*) && (ptr->type->BaseType() is DoubleType*))
2128 {
2129 storeOpCode = ptr->type->BaseType()->GetStoreOp(line);
2130 }
2131 else
2132 {
2133 storeOpCode = value->type->GetStoreOp(line);
2134 }
2135 ptrLoc->GenerateStore(storeOpCode, valueReg, machineCode, this);
2136 ptrAddressDescriptor->AddLocation(ptrLoc);
2137 }
2138 else
2139 {
2140 throw Exception("location for '" + ptr->Name() + "' not found (line " + ToString(line) + ")");
2141 }
2142 EndGenerateCode();
2143 if (Flags.Get(Flag.debug))
2144 {
2145 Print(formatter);
2146 formatter.WriteLine();
2147 formatter.IncIndent();
2148 registerDescriptors.DebugPrint(formatter);
2149 addressDescriptors.DebugPrint(formatter);
2150 formatter.DecIndent();
2151 }
2152 }
2153 public Value* value;
2154 public Value* ptr;
2155 }
2156
2157 public class ElemAddrInstruction : ValueInstruction
2158 {
2159 public nothrow ElemAddrInstruction(Value* result_, Value* ptr_, Value* index_, int line_) : base(line_), ptr(ptr_), index(index_)
2160 {
2161 SetResult(result_);
2162 }
2163 public override nothrow string OperationName() const
2164 {
2165 return "elemaddr";
2166 }
2167 public override void Validate(Function& function, int numArgs)
2168 {
2169 base->Validate(function, numArgs);
2170 ptr = function.ResolveOperand(line, ptr);
2171 if (ptr == null)
2172 {
2173 throw Exception("internal error : ptr operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
2174 }
2175 index = function.ResolveOperand(line, index);
2176 if (index == null)
2177 {
2178 throw Exception("internal error : index operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
2179 }
2180 if (!(ptr->type is PtrType*))
2181 {
2182 throw Exception("error: the first operand type '" + ptr->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
2183 }
2184 PtrType* ptrType = cast<PtrType*>(ptr->type);
2185 Type* baseType = ptrType->BaseType();
2186 if (!(baseType is ArrayType* || baseType is StructureType*))
2187 {
2188 throw Exception("error: the first operand type '" + ptr->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) +
2189 " must be a pointer-to-array or pointer-to-structure type");
2190 }
2191 if (!(type is PtrType*))
2192 {
2193 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
2194 }
2195 if (!(index->type is LongType*))
2196 {
2197 throw Exception("error: the second operand type '" + index->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be of long type");
2198 }
2199 }
2200 public override void Print(CodeFormatter& formatter)
2201 {
2202 base->Print(formatter);
2203 formatter << " " << ptr->type->Name() << " " << ptr->Name() << ", " << index->type->Name() << " " << index->Name();
2204 }
2205 public override nothrow void BeginComputeLivenessAndNextUse()
2206 {
2207 base->BeginComputeLivenessAndNextUse();
2208 Pair<Liveness, Value*>* p1 = parent->GetCurrentLivenessAndNextUse(ptr);
2209 if (p1 != null)
2210 {
2211 livenessAndNextUse[ptr] = *p1;
2212 }
2213 Pair<Liveness, Value*>* p2 = parent->GetCurrentLivenessAndNextUse(index);
2214 if (p2 != null)
2215 {
2216 livenessAndNextUse[index] = *p2;
2217 }
2218 }
2219 public override nothrow void EndComputeLivenessAndNextUse()
2220 {
2221 base->EndComputeLivenessAndNextUse();
2222 parent->SetValueLivenessAndNextUse(ptr, Liveness.live, this);
2223 parent->SetValueLivenessAndNextUse(index, Liveness.live, this);
2224 }
2225 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
2226 {
2227 BeginGenerateCode(machineCode);
2228 Value* x = this;
2229 Value* y = ptr;
2230 Value* z = null;
2231 PtrType* ptrType = cast<PtrType*>(ptr->type);
2232 Type* baseType = ptrType->BaseType();
2233 #assert((baseType is ArrayType*) || (baseType is StructureType*));
2234 #assert(index->type is LongType*);
2235 if (baseType is StructureType*)
2236 {
2237 StructureType* structureType = cast<StructureType*>(baseType);
2238 if (index is LongValue*)
2239 {
2240 LongValue* longValue = cast<LongValue*>(index);
2241 long offset = structureType->GetMemberOffset(longValue->value);
2242 z = new LongValue(offset);
2243 machineCode.context.AddValue(z);
2244 }
2245 else
2246 {
2247 throw Exception("error: when the base type of the first operand is a structure type, the second operand in the " + OperationName() + " instruction at line " + ToString(line) + " must be a long constant");
2248 }
2249 }
2250 else if (baseType is ArrayType*)
2251 {
2252 z = index;
2253 }
2254 else
2255 {
2256 throw Exception("error: the base type of the first operand must be a pointer-to-array type or a pointer-to-structure type in the " + OperationName() + " instruction at line " + ToString(line));
2257 }
2258 RegisterDescriptor* rx = null;
2259 RegisterDescriptor* ry = null;
2260 RegisterDescriptor* rz = null;
2261 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
2262 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
2263 bool useRegYForX = false;
2264 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
2265 if (y is LiteralValue*)
2266 {
2267 y->GenerateSetValue(ry->reg, machineCode, line, this);
2268 }
2269 else
2270 {
2271 bool operandLoaded = false;
2272 if (ptr is LocalInstruction*)
2273 {
2274 LocalInstruction* local = cast<LocalInstruction*>(ptr);
2275 if ((local->localType is ArrayType*) || (local->localType is StructureType*))
2276 {
2277 LoadOperandAddress(y, ry, addressDescriptors, machineCode, line, this);
2278 operandLoaded = true;
2279 }
2280 }
2281 else if (ptr is PtrValue*)
2282 {
2283 LoadOperandAddress(y, ry, addressDescriptors, machineCode, line, this);
2284 operandLoaded = true;
2285 }
2286 if (!operandLoaded)
2287 {
2288 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
2289 }
2290 }
2291 if (z is LiteralValue*)
2292 {
2293 z->GenerateSetValue(rz->reg, machineCode, line, this);
2294 }
2295 else
2296 {
2297 LoadOperandValue(z, rz, addressDescriptors, machineCode, line, this);
2298 }
2299 Register* ix = null;
2300 if (baseType is ArrayType*)
2301 {
2302 ArrayType* arrayType = cast<ArrayType*>(baseType);
2303 Type* elementType = arrayType->ElementType();
2304 long size = elementType->Size();
2305 LongValue* sizeValue = new LongValue(size);
2306 machineCode.context.AddValue(sizeValue);
2307 ix = machineCode.context.regs.GetIx();
2308 sizeValue->GenerateSetValue(ix, machineCode, line, this);
2309 MachineInstruction* mulInstruction = machineCode.GetInstruction(cmsx.machine.MUL, this);
2310 mulInstruction->AddOperand(ix);
2311 mulInstruction->AddOperand(rz->reg);
2312 mulInstruction->AddOperand(ix);
2313 }
2314 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.LDA, this);
2315 machineInstruction->AddOperand(rx->reg);
2316 machineInstruction->AddOperand(ry->reg);
2317 if (ix != null)
2318 {
2319 machineInstruction->AddOperand(ix);
2320 }
2321 else
2322 {
2323 machineInstruction->AddOperand(rz->reg);
2324 }
2325 rx->SetValue(x);
2326 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
2327 adx->SetLocation(rx->reg);
2328 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
2329 EndGenerateCode();
2330 if (Flags.Get(Flag.debug))
2331 {
2332 Print(formatter);
2333 formatter.WriteLine();
2334 formatter.IncIndent();
2335 registerDescriptors.DebugPrint(formatter);
2336 addressDescriptors.DebugPrint(formatter);
2337 formatter.DecIndent();
2338 }
2339 }
2340 public Value* ptr;
2341 public Value* index;
2342 }
2343
2344 public class PtrOffsetInstruction : ValueInstruction
2345 {
2346 public nothrow PtrOffsetInstruction(Value* result_, Value* ptr_, Value* offset_, int line_) : base(line_), ptr(ptr_), offset(offset_)
2347 {
2348 SetResult(result_);
2349 }
2350 public override nothrow string OperationName() const
2351 {
2352 return "ptroffset";
2353 }
2354 public override void Validate(Function& function, int numArgs)
2355 {
2356 base->Validate(function, numArgs);
2357 ptr = function.ResolveOperand(line, ptr);
2358 offset = function.ResolveOperand(line, offset);
2359 if (ptr == null)
2360 {
2361 throw Exception("internal error : ptr operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
2362 }
2363 if (offset == null)
2364 {
2365 throw Exception("internal error : offset operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
2366 }
2367 if (!(ptr->type is PtrType*))
2368 {
2369 throw Exception("error: the first operand type '" + ptr->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
2370 }
2371 if (!(type is PtrType*))
2372 {
2373 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
2374 }
2375 if (ptr->type != type)
2376 {
2377 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be same as the first operand type");
2378 }
2379 if (!(offset->type is IntegerType*))
2380 {
2381 throw Exception("error: the second operand type '" + offset->type->Name() + " in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
2382 }
2383 }
2384 public override void Print(CodeFormatter& formatter)
2385 {
2386 base->Print(formatter);
2387 formatter << " " << ptr->type->Name() << " " << ptr->Name() << ", " << offset->type->Name() << " " << offset->Name();
2388 }
2389 public override nothrow void BeginComputeLivenessAndNextUse()
2390 {
2391 base->BeginComputeLivenessAndNextUse();
2392 Pair<Liveness, Value*>* p1 = parent->GetCurrentLivenessAndNextUse(ptr);
2393 if (p1 != null)
2394 {
2395 livenessAndNextUse[ptr] = *p1;
2396 }
2397 Pair<Liveness, Value*>* p2 = parent->GetCurrentLivenessAndNextUse(offset);
2398 if (p2 != null)
2399 {
2400 livenessAndNextUse[offset] = *p2;
2401 }
2402 }
2403 public override nothrow void EndComputeLivenessAndNextUse()
2404 {
2405 base->EndComputeLivenessAndNextUse();
2406 parent->SetValueLivenessAndNextUse(ptr, Liveness.live, this);
2407 parent->SetValueLivenessAndNextUse(offset, Liveness.live, this);
2408 }
2409 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
2410 {
2411 BeginGenerateCode(machineCode);
2412 Value* x = this;
2413 Value* y = ptr;
2414 Value* z = null;
2415 #assert(type is PtrType*);
2416 #assert(offset->type is LongType*);
2417 PtrType* ptrType = cast<PtrType*>(type);
2418 long size = ptrType->BaseType()->Size();
2419 byte immediateValue = 0u;
2420 bool isImmediate = offset->IsImmediate(immediateValue);
2421 long immediateSizeProduct = cast<long>(immediateValue) * size;
2422 if (isImmediate && immediateSizeProduct < MaxValue<byte>())
2423 {
2424 immediateValue = cast<byte>(immediateSizeProduct);
2425 }
2426 else
2427 {
2428 z = offset;
2429 }
2430 RegisterDescriptor* rx = null;
2431 RegisterDescriptor* ry = null;
2432 RegisterDescriptor* rz = null;
2433 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
2434 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
2435 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
2436 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
2437 if (y is LiteralValue*)
2438 {
2439 y->GenerateSetValue(ry->reg, machineCode, line, this);
2440 }
2441 else
2442 {
2443 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
2444 }
2445 if (z != null)
2446 {
2447 if (z is LiteralValue*)
2448 {
2449 #assert(z is LongValue*);
2450 LongValue* offsetValue = cast<LongValue*>(z);
2451 LongValue* sizedOffsetValue = new LongValue(offsetValue->value * size);
2452 machineCode.context.AddValue(sizedOffsetValue);
2453 sizedOffsetValue->GenerateSetValue(rz->reg, machineCode, line, this);
2454 }
2455 else
2456 {
2457 LoadOperandValue(z, rz, addressDescriptors, machineCode, line, this);
2458 if (size <= MaxValue<byte>())
2459 {
2460 MachineInstruction* mulInst = machineCode.GetInstruction(cmsx.machine.MUL, this);
2461 mulInst->AddOperand(rz->reg);
2462 mulInst->AddOperand(rz->reg);
2463 mulInst->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(size)));
2464 }
2465 else
2466 {
2467 LongValue* sizeValue = new LongValue(size);
2468 machineCode.context.AddValue(sizeValue);
2469 Register* ix = machineCode.context.regs.GetIx();
2470 sizeValue->GenerateSetValue(ix, machineCode, line, this);
2471 MachineInstruction* mulInst = machineCode.GetInstruction(cmsx.machine.MUL, this);
2472 mulInst->AddOperand(rz->reg);
2473 mulInst->AddOperand(rz->reg);
2474 mulInst->AddOperand(ix);
2475 }
2476 }
2477 }
2478 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.LDA, this);
2479 machineInstruction->AddOperand(rx->reg);
2480 machineInstruction->AddOperand(ry->reg);
2481 if (z != null)
2482 {
2483 machineInstruction->AddOperand(rz->reg);
2484 }
2485 else
2486 {
2487 machineInstruction->AddOperand(machineCode.context.GetLiteralOperand(immediateValue));
2488 }
2489 rx->SetValue(x);
2490 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
2491 adx->SetLocation(rx->reg);
2492 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
2493 EndGenerateCode();
2494 if (Flags.Get(Flag.debug))
2495 {
2496 Print(formatter);
2497 formatter.WriteLine();
2498 formatter.IncIndent();
2499 registerDescriptors.DebugPrint(formatter);
2500 addressDescriptors.DebugPrint(formatter);
2501 formatter.DecIndent();
2502 }
2503 }
2504 public Value* ptr;
2505 public Value* offset;
2506 }
2507
2508 public class PtrDiffInstruction : ValueInstruction
2509 {
2510 public nothrow PtrDiffInstruction(Value* result_, Value* leftPtr_, Value* rightPtr_, int line_) : base(line_), leftPtr(leftPtr_), rightPtr(rightPtr_)
2511 {
2512 SetResult(result_);
2513 }
2514 public override nothrow string OperationName() const
2515 {
2516 return "ptrdiff";
2517 }
2518 public override void Validate(Function& function, int numArgs)
2519 {
2520 base->Validate(function, numArgs);
2521 leftPtr = function.ResolveOperand(line, leftPtr);
2522 if (leftPtr == null)
2523 {
2524 throw Exception("internal error : left operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
2525 }
2526 rightPtr = function.ResolveOperand(line, rightPtr);
2527 if (rightPtr == null)
2528 {
2529 throw Exception("internal error : right operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
2530 }
2531 if (!(leftPtr->type is PtrType*))
2532 {
2533 throw Exception("error: the first operand type '" + leftPtr->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
2534 }
2535 if (!(rightPtr->type is PtrType*))
2536 {
2537 throw Exception("error: the second operand type '" + rightPtr->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a pointer type");
2538 }
2539 if (leftPtr->type != rightPtr->type)
2540 {
2541 throw Exception("error: the first operand type '" + leftPtr->type->Name() + "' and second operand type '" + rightPtr->type->Name() + " in the " + OperationName() + " instruction at line " + ToString(line) + " must be the same pointer type");
2542 }
2543 if (!(type is IntegerType*))
2544 {
2545 throw Exception("error: the result type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
2546 }
2547 }
2548 public override void Print(CodeFormatter& formatter)
2549 {
2550 base->Print(formatter);
2551 formatter << " " << leftPtr->type->Name() << " " << leftPtr->Name() << ", " << rightPtr->type->Name() << " " << rightPtr->Name();
2552 }
2553 public override nothrow void BeginComputeLivenessAndNextUse()
2554 {
2555 base->BeginComputeLivenessAndNextUse();
2556 Pair<Liveness, Value*>* p1 = parent->GetCurrentLivenessAndNextUse(leftPtr);
2557 if (p1 != null)
2558 {
2559 livenessAndNextUse[leftPtr] = *p1;
2560 }
2561 Pair<Liveness, Value*>* p2 = parent->GetCurrentLivenessAndNextUse(rightPtr);
2562 if (p2 != null)
2563 {
2564 livenessAndNextUse[rightPtr] = *p2;
2565 }
2566 }
2567 public override nothrow void EndComputeLivenessAndNextUse()
2568 {
2569 base->EndComputeLivenessAndNextUse();
2570 parent->SetValueLivenessAndNextUse(leftPtr, Liveness.live, this);
2571 parent->SetValueLivenessAndNextUse(rightPtr, Liveness.live, this);
2572 }
2573 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
2574 {
2575 BeginGenerateCode(machineCode);
2576 Value* x = this;
2577 Value* y = leftPtr;
2578 Value* z = rightPtr;
2579 #assert(y->type is PtrType*);
2580 PtrType* ptrType = cast<PtrType*>(y->type);
2581 long size = ptrType->BaseType()->Size();
2582 RegisterDescriptor* rx = null;
2583 RegisterDescriptor* ry = null;
2584 RegisterDescriptor* rz = null;
2585 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
2586 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
2587 bool useRegYForX = CanUseRegYForX(y, registerDescriptors, addressDescriptors);
2588 GetReg(x, y, z, useRegYForX, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
2589 if (y is LiteralValue*)
2590 {
2591 y->GenerateSetValue(ry->reg, machineCode, line, this);
2592 }
2593 else
2594 {
2595 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
2596 }
2597 if (z is LiteralValue*)
2598 {
2599 z->GenerateSetValue(rz->reg, machineCode, line, this);
2600 }
2601 else
2602 {
2603 LoadOperandValue(z, rz, addressDescriptors, machineCode, line, this);
2604 }
2605 MachineInstruction* subInstruction = machineCode.GetInstruction(cmsx.machine.SUBU, this);
2606 subInstruction->AddOperand(rx->reg);
2607 subInstruction->AddOperand(ry->reg);
2608 subInstruction->AddOperand(rz->reg);
2609 MachineInstruction* divInstruction = machineCode.GetInstruction(cmsx.machine.DIVU, this);
2610 divInstruction->AddOperand(rx->reg);
2611 divInstruction->AddOperand(rx->reg);
2612 if (size <= MaxValue<byte>())
2613 {
2614 divInstruction->AddOperand(machineCode.context.GetLiteralOperand(cast<ulong>(size)));
2615 }
2616 else
2617 {
2618 LongValue* sizeValue = new LongValue(size);
2619 machineCode.context.AddValue(sizeValue);
2620 Register* ix = machineCode.context.regs.GetIx();
2621 sizeValue->GenerateSetValue(ix, machineCode, line, this);
2622 divInstruction->AddOperand(ix);
2623 }
2624 rx->SetValue(x);
2625 AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
2626 adx->SetLocation(rx->reg);
2627 addressDescriptors.RemoveRegisterFromAllBut(x, rx->reg);
2628 EndGenerateCode();
2629 if (Flags.Get(Flag.debug))
2630 {
2631 Print(formatter);
2632 formatter.WriteLine();
2633 formatter.IncIndent();
2634 registerDescriptors.DebugPrint(formatter);
2635 addressDescriptors.DebugPrint(formatter);
2636 formatter.DecIndent();
2637 }
2638 }
2639 public Value* leftPtr;
2640 public Value* rightPtr;
2641 }
2642
2643 public class ArgInstruction : Instruction
2644 {
2645 public nothrow ArgInstruction(Value* arg_, int line_) : base(line_), arg(arg_), numArgs(0), argIndex(-1)
2646 {
2647 }
2648 public override nothrow string Name() const
2649 {
2650 return "arg";
2651 }
2652 public override nothrow string OperationName() const
2653 {
2654 return "arg";
2655 }
2656 public override void Validate(Function& function, int numArgs)
2657 {
2658 base->Validate(function, numArgs);
2659 arg = function.ResolveOperand(line, arg);
2660 if (arg == null)
2661 {
2662 throw Exception("internal error : operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
2663 }
2664 arg->IncNumUses();
2665 if (!(arg->type is ScalarType*))
2666 {
2667 throw Exception("error: the operand type '" + arg->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a scalar type");
2668 }
2669 argIndex = parent->function.GetNextArgIndex();
2670 }
2671 public override void Print(CodeFormatter& formatter)
2672 {
2673 base->Print(formatter);
2674 formatter << " " << arg->type->Name() << " " << arg->Name();
2675 }
2676 public override nothrow void BeginComputeLivenessAndNextUse()
2677 {
2678 base->BeginComputeLivenessAndNextUse();
2679 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(arg);
2680 if (p != null)
2681 {
2682 livenessAndNextUse[arg] = *p;
2683 }
2684 }
2685 public override nothrow void EndComputeLivenessAndNextUse()
2686 {
2687 base->EndComputeLivenessAndNextUse();
2688 parent->SetValueLivenessAndNextUse(arg, Liveness.live, this);
2689 }
2690 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
2691 {
2692 BeginGenerateCode(machineCode);
2693 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
2694 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
2695 #assert(argIndex >= 0 && numArgs >= 0);
2696 int numParamRegs = machineCode.context.regs.GetNumParamRegisters();
2697 Register* ix = machineCode.context.regs.GetIx();
2698 Register* sp = machineCode.context.regs.GetSP();
2699 if (argIndex == 0 && numArgs > numParamRegs)
2700 {
2701 if (trap)
2702 {
2703 throw Exception("too many arguments for trap at line " + ToString(line));
2704 }
2705 byte numUsedLocalRegs = registerDescriptors.GetNumUsedLocalRegs();
2706 ulong spOffset = 8u * (numUsedLocalRegs + 4u);
2707 ULongValue* spOffsetValue = new ULongValue(spOffset);
2708 spOffsetValue->GenerateSetValue(ix, machineCode, line, this);
2709 MachineInstruction* ldaInst = machineCode.GetInstruction(cmsx.assembly.LDA, this);
2710 ldaInst->AddOperand(sp);
2711 ldaInst->AddOperand(sp);
2712 ldaInst->AddOperand(ix);
2713 MachineInstruction* storeInst = machineCode.GetInstruction(cmsx.machine.STOU, this);
2714 storeInst->AddOperand(ix);
2715 storeInst->AddOperand(sp);
2716 storeInst->AddOperand(machineCode.context.GetLiteralOperand(0u));
2717 }
2718 Location* argLocation = parent->function.frameLocations.GetArgLocation();
2719 Register* argReg = null;
2720 if (argIndex < numParamRegs)
2721 {
2722 argReg = machineCode.context.regs.GetParamRegister(cast<byte>(argIndex));
2723 }
2724 else
2725 {
2726 argReg = machineCode.context.regs.GetLocalRegister(registerDescriptors.GetNumUsedLocalRegs());
2727 }
2728 RegisterDescriptor* argRegDescriptor = registerDescriptors.GetRegisterDescriptor(argReg);
2729 bool loaded = false;
2730 if (arg is LocalInstruction*)
2731 {
2732 LoadOperandAddress(arg, argRegDescriptor, addressDescriptors, machineCode, line, this);
2733 loaded = true;
2734 }
2735 else if (arg is LiteralValue*)
2736 {
2737 arg->GenerateSetValue(argRegDescriptor->reg, machineCode, line, this);
2738 loaded = true;
2739 }
2740 if (!loaded)
2741 {
2742 AddressDescriptor* addressDescriptor = addressDescriptors.GetAddressDescriptor(arg);
2743 Location* loc = addressDescriptor->GetLocation();
2744 if (loc == null)
2745 {
2746 loc = arg->HomeLocation();
2747 }
2748 if (loc != null && (loc is Register*))
2749 {
2750 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, this);
2751 setInst->AddOperand(argRegDescriptor->reg);
2752 setInst->AddOperand(loc);
2753 }
2754 else if (arg is PtrValue*)
2755 {
2756 PtrValue* ptrValue = cast<PtrValue*>(arg);
2757 ConstantValue* initializer = ptrValue->globalVariable->initializer;
2758 if (initializer != null && ((initializer is StringValue*) || (initializer is StringArrayValue*)))
2759 {
2760 LoadOperandAddress(arg, argRegDescriptor, addressDescriptors, machineCode, line, this);
2761 }
2762 else
2763 {
2764 Type* type = ptrValue->globalVariable->type;
2765 if (type is ArrayType* || type is StructureType*)
2766 {
2767 LoadOperandAddress(arg, argRegDescriptor, addressDescriptors, machineCode, line, this);
2768 }
2769 else
2770 {
2771 LoadOperandValue(arg, argRegDescriptor, addressDescriptors, machineCode, line, this);
2772 }
2773 }
2774 }
2775 else
2776 {
2777 LoadOperandValue(arg, argRegDescriptor, addressDescriptors, machineCode, line, this);
2778 }
2779 }
2780 if (argIndex >= numParamRegs)
2781 {
2782 argLocation->GenerateStore(arg->type->GetStoreOp(line), argReg, machineCode, this);
2783 }
2784 EndGenerateCode();
2785 if (Flags.Get(Flag.debug))
2786 {
2787 Print(formatter);
2788 formatter.WriteLine();
2789 formatter.IncIndent();
2790 registerDescriptors.DebugPrint(formatter);
2791 addressDescriptors.DebugPrint(formatter);
2792 formatter.DecIndent();
2793 }
2794 }
2795 public Value* arg;
2796 public int numArgs;
2797 public bool trap;
2798 private int argIndex;
2799 }
2800
2801 public class JumpInstruction : TerminatorInstruction
2802 {
2803 public nothrow JumpInstruction(uint target_, int line_) : base(line_), target(target_), targetBlock(null)
2804 {
2805 }
2806 public override nothrow string Name() const
2807 {
2808 return "jmp";
2809 }
2810 public override nothrow string OperationName() const
2811 {
2812 return "jmp";
2813 }
2814 public override void Validate(Function& function, int numArgs)
2815 {
2816 base->Validate(function, numArgs);
2817 targetBlock = function.GetBasicBlock(target);
2818 targetBlock->AddPredecessor(parent);
2819 if (targetBlock == null)
2820 {
2821 throw Exception("error: the target block for the " + OperationName() + " instruction at line " + ToString(line) + " not found");
2822 }
2823 }
2824 public override void Print(CodeFormatter& formatter)
2825 {
2826 base->Print(formatter);
2827 formatter << " " << targetBlock->Name();
2828 }
2829 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
2830 {
2831 BeginGenerateCode(machineCode);
2832 MachineInstruction* jumpInst = machineCode.GetInstruction(cmsx.machine.JMP, this);
2833 jumpInst->AddOperand(machineCode.context.GetSymbolOperand("@" + ToString(targetBlock->Id())));
2834 EndGenerateCode();
2835 }
2836 public uint target;
2837 public BasicBlock* targetBlock;
2838 }
2839
2840 public class BranchInstruction : TerminatorInstruction
2841 {
2842 public nothrow BranchInstruction(Value* cond_, uint trueTarget_, uint falseTarget_, int line_) :
2843 base(line_), cond(cond_), trueTarget(trueTarget_), trueTargetBlock(null), falseTarget(falseTarget_), falseTargetBlock(null)
2844 {
2845 }
2846 public override nothrow string Name() const
2847 {
2848 return "branch";
2849 }
2850 public override nothrow string OperationName() const
2851 {
2852 return "branch";
2853 }
2854 public override void Validate(Function& function, int numArgs)
2855 {
2856 base->Validate(function, numArgs);
2857 cond = function.ResolveOperand(line, cond);
2858 trueTargetBlock = function.GetBasicBlock(trueTarget);
2859 trueTargetBlock->AddPredecessor(parent);
2860 if (trueTargetBlock == null)
2861 {
2862 throw Exception("error: the true target block for the " + OperationName() + " instruction at line " + ToString(line) + " not found");
2863 }
2864 falseTargetBlock = function.GetBasicBlock(falseTarget);
2865 falseTargetBlock->AddPredecessor(parent);
2866 if (trueTargetBlock == null)
2867 {
2868 throw Exception("error: the false target block for the " + OperationName() + " instruction at line " + ToString(line) + " not found");
2869 }
2870 }
2871 public override void Print(CodeFormatter& formatter)
2872 {
2873 base->Print(formatter);
2874 formatter << " " << cond->type->Name() << " " << cond->Name() << ", " << trueTargetBlock->Name() << ", " << falseTargetBlock->Name();
2875 }
2876 public override nothrow void BeginComputeLivenessAndNextUse()
2877 {
2878 base->BeginComputeLivenessAndNextUse();
2879 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(cond);
2880 if (p != null)
2881 {
2882 livenessAndNextUse[cond] = *p;
2883 }
2884 }
2885 public override nothrow void EndComputeLivenessAndNextUse()
2886 {
2887 base->EndComputeLivenessAndNextUse();
2888 parent->SetValueLivenessAndNextUse(cond, Liveness.live, this);
2889 }
2890 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
2891 {
2892 BeginGenerateCode(machineCode);
2893 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
2894 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
2895 Register* reg = null;
2896 if (cond is LiteralValue*)
2897 {
2898 List<Register*> dontUse;
2899 RegisterDescriptor* condRegDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
2900 reg = condRegDescriptor->reg;
2901 cond->GenerateSetValue(reg, machineCode, line, this);
2902 }
2903 else
2904 {
2905 AddressDescriptor* condAddressDescriptor = addressDescriptors.GetAddressDescriptor(cond);
2906 Location* location = condAddressDescriptor->GetLocation();
2907 if (location == null)
2908 {
2909 location = cond->HomeLocation();
2910 }
2911 if (location != null)
2912 {
2913 if (location is Register*)
2914 {
2915 reg = cast<Register*>(location);
2916 }
2917 else
2918 {
2919 List<Register*> dontUse;
2920 RegisterDescriptor* condRegDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
2921 reg = condRegDescriptor->reg;
2922 int loadOpCode = cond->type->GetLoadOp(line);
2923 location->GenerateLoad(loadOpCode, reg, machineCode, this);
2924 }
2925 }
2926 }
2927 MachineInstruction* branchInst = machineCode.GetInstruction(cmsx.machine.BP, this);
2928 if (reg != null)
2929 {
2930 branchInst->AddOperand(reg);
2931 branchInst->AddOperand(machineCode.context.GetSymbolOperand("@" + ToString(trueTargetBlock->Id())));
2932 MachineInstruction* jumpInst = machineCode.GetInstruction(cmsx.machine.JMP, this);
2933 jumpInst->AddOperand(machineCode.context.GetSymbolOperand("@" + ToString(falseTargetBlock->Id())));
2934 EndGenerateCode();
2935 }
2936 else
2937 {
2938 throw Exception("error: could not load condition into register in " + OperationName() + " instruction at line " + ToString(line));
2939 }
2940 }
2941 public Value* cond;
2942 public uint trueTarget;
2943 public BasicBlock* trueTargetBlock;
2944 public uint falseTarget;
2945 public BasicBlock* falseTargetBlock;
2946 }
2947
2948 public class ProcedureCallInstruction : Instruction
2949 {
2950 public nothrow ProcedureCallInstruction(Value* callee_, int line_) : base(line_), callee(callee_)
2951 {
2952 }
2953 public override nothrow string Name() const
2954 {
2955 return "call void";
2956 }
2957 public override nothrow string OperationName() const
2958 {
2959 return "call";
2960 }
2961 public override void Validate(Function& function, int numArgs)
2962 {
2963 base->Validate(function, numArgs);
2964 callee = function.ResolveOperand(line, callee);
2965 if (callee == null)
2966 {
2967 throw Exception("internal error : callee operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
2968 }
2969 Type* calleeType = callee->type;
2970 if (calleeType is PtrType*)
2971 {
2972 PtrType* ptrType = cast<PtrType*>(calleeType);
2973 calleeType = ptrType->BaseType();
2974 }
2975 if (!(calleeType is FunctionType*))
2976 {
2977 throw Exception("error: the type of the callee in the " + OperationName() + " instruction at line " + ToString(line) + " must be a function type or a pointer-to-function type");
2978 }
2979 FunctionType* functionType = cast<FunctionType*>(calleeType);
2980 if (functionType->ParamTypes().Count() != numArgs)
2981 {
2982 throw Exception("error: wrong number of preceding arg instructions for " + OperationName() + " instruction at line " + ToString(line));
2983 }
2984 parent->function.ResetNextArgIndex();
2985 }
2986 public override void Print(CodeFormatter& formatter)
2987 {
2988 base->Print(formatter);
2989 formatter << " " << callee->type->Name() << " " << callee->PrintName();
2990 }
2991 public override nothrow void BeginComputeLivenessAndNextUse()
2992 {
2993 base->BeginComputeLivenessAndNextUse();
2994 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(callee);
2995 if (p != null)
2996 {
2997 livenessAndNextUse[callee] = *p;
2998 }
2999 }
3000 public override nothrow void EndComputeLivenessAndNextUse()
3001 {
3002 base->EndComputeLivenessAndNextUse();
3003 parent->SetValueLivenessAndNextUse(callee, Liveness.live, this);
3004 }
3005 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
3006 {
3007 BeginGenerateCode(machineCode);
3008 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
3009 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
3010 Type* calleeType = callee->type;
3011 if (calleeType is PtrType*)
3012 {
3013 PtrType* ptrType = cast<PtrType*>(calleeType);
3014 calleeType = ptrType->BaseType();
3015 }
3016 if (!(calleeType is FunctionType*))
3017 {
3018 throw Exception("error: the type of the callee in the " + OperationName() + " instruction at line " + ToString(line) + " must be a function type or a pointer-to-function type");
3019 }
3020 FunctionType* functionType = cast<FunctionType*>(calleeType);
3021 int numParamRegs = machineCode.context.regs.GetNumParamRegisters();
3022 if (functionType->ParamTypes().Count() > numParamRegs)
3023 {
3024 Register* ix = machineCode.context.regs.GetIx();
3025 Register* sp = machineCode.context.regs.GetSP();
3026 MachineInstruction* loadInst = machineCode.GetInstruction(cmsx.machine.LDOU, this);
3027 loadInst->AddOperand(ix);
3028 loadInst->AddOperand(sp);
3029 loadInst->AddOperand(machineCode.context.GetLiteralOperand(0u));
3030 MachineInstruction* subInst = machineCode.GetInstruction(cmsx.machine.SUBU, this);
3031 subInst->AddOperand(sp);
3032 subInst->AddOperand(sp);
3033 subInst->AddOperand(ix);
3034 }
3035 parent->function.frameLocations.ResetArgLocations();
3036 int x = registerDescriptors.GetNumUsedLocalRegs();
3037 Register* xReg = machineCode.context.regs.GetLocalRegister(registerDescriptors.GetNumUsedLocalRegs());
3038 Operand* calleeOperand = null;
3039 Operand* zOperand = null;
3040 if (callee is SymbolValue*)
3041 {
3042 calleeOperand = machineCode.context.GetSymbolOperand(callee->Name());
3043 }
3044 else
3045 {
3046 AddressDescriptor* calleeAddressDescriptor = addressDescriptors.GetAddressDescriptor(callee);
3047 Location* loc = calleeAddressDescriptor->GetLocation();
3048 if (loc != null && loc is Register*)
3049 {
3050 calleeOperand = loc;
3051 }
3052 else
3053 {
3054 LoadOperandValue(callee, registerDescriptors.GetRegisterDescriptor(xReg), addressDescriptors, machineCode, line, this);
3055 calleeOperand = xReg;
3056 }
3057 zOperand = machineCode.context.GetLiteralOperand(0u);
3058 }
3059 MachineInstruction* callInst = machineCode.GetInstruction(cmsx.machine.CALL, this);
3060 callInst->AddOperand(xReg);
3061 callInst->AddOperand(calleeOperand);
3062 if (zOperand != null)
3063 {
3064 callInst->AddOperand(zOperand);
3065 }
3066 EndGenerateCode();
3067 if (Flags.Get(Flag.debug))
3068 {
3069 Print(formatter);
3070 formatter.WriteLine();
3071 formatter.IncIndent();
3072 registerDescriptors.DebugPrint(formatter);
3073 addressDescriptors.DebugPrint(formatter);
3074 formatter.DecIndent();
3075 }
3076 }
3077 public Value* callee;
3078 }
3079
3080 public class FunctionCallInstruction : ValueInstruction
3081 {
3082 public nothrow FunctionCallInstruction(Value* result_, Value* callee_, int line_) : base(line_), callee(callee_)
3083 {
3084 SetResult(result_);
3085 }
3086 public override nothrow string OperationName() const
3087 {
3088 return "call";
3089 }
3090 public override void Validate(Function& function, int numArgs)
3091 {
3092 base->Validate(function, numArgs);
3093 callee = function.ResolveOperand(line, callee);
3094 if (callee == null)
3095 {
3096 throw Exception("internal error : callee operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
3097 }
3098 Type* calleeType = callee->type;
3099 if (calleeType is PtrType*)
3100 {
3101 PtrType* ptrType = cast<PtrType*>(calleeType);
3102 calleeType = ptrType->BaseType();
3103 }
3104 if (!(calleeType is FunctionType*))
3105 {
3106 throw Exception("error: the type of the callee in the " + OperationName() + " instruction at line " + ToString(line) + " must be a function type or a pointer-to-function type");
3107 }
3108 FunctionType* functionType = cast<FunctionType*>(calleeType);
3109 if (functionType->ParamTypes().Count() != numArgs)
3110 {
3111 throw Exception("error: wrong number of preceding arg instructions for " + OperationName() + " instruction at line " + ToString(line));
3112 }
3113 parent->function.ResetNextArgIndex();
3114 }
3115 public override void Print(CodeFormatter& formatter)
3116 {
3117 base->Print(formatter);
3118 formatter << " " << callee->type->Name() << " " << callee->PrintName();
3119 }
3120 public override nothrow void BeginComputeLivenessAndNextUse()
3121 {
3122 base->BeginComputeLivenessAndNextUse();
3123 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(callee);
3124 if (p != null)
3125 {
3126 livenessAndNextUse[callee] = *p;
3127 }
3128 }
3129 public override nothrow void EndComputeLivenessAndNextUse()
3130 {
3131 base->EndComputeLivenessAndNextUse();
3132 parent->SetValueLivenessAndNextUse(callee, Liveness.live, this);
3133 }
3134 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
3135 {
3136 BeginGenerateCode(machineCode);
3137 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
3138 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
3139 Type* calleeType = callee->type;
3140 if (calleeType is PtrType*)
3141 {
3142 PtrType* ptrType = cast<PtrType*>(calleeType);
3143 calleeType = ptrType->BaseType();
3144 }
3145 if (!(calleeType is FunctionType*))
3146 {
3147 throw Exception("error: the type of the callee in the " + OperationName() + " instruction at line " + ToString(line) + " must be a function type or a pointer-to-function type");
3148 }
3149 FunctionType* functionType = cast<FunctionType*>(calleeType);
3150 int numParamRegs = machineCode.context.regs.GetNumParamRegisters();
3151 if (functionType->ParamTypes().Count() > numParamRegs)
3152 {
3153 Register* ix = machineCode.context.regs.GetIx();
3154 Register* sp = machineCode.context.regs.GetSP();
3155 MachineInstruction* loadInst = machineCode.GetInstruction(cmsx.machine.LDOU, this);
3156 loadInst->AddOperand(ix);
3157 loadInst->AddOperand(sp);
3158 loadInst->AddOperand(machineCode.context.GetLiteralOperand(0u));
3159 MachineInstruction* subInst = machineCode.GetInstruction(cmsx.machine.SUBU, this);
3160 subInst->AddOperand(sp);
3161 subInst->AddOperand(sp);
3162 subInst->AddOperand(ix);
3163 }
3164 parent->function.frameLocations.ResetArgLocations();
3165 Register* xReg = machineCode.context.regs.GetLocalRegister(registerDescriptors.GetNumUsedLocalRegs());
3166 Operand* calleeOperand = null;
3167 Operand* zOperand = null;
3168 if (callee is SymbolValue*)
3169 {
3170 calleeOperand = machineCode.context.GetSymbolOperand(callee->Name());
3171 }
3172 else
3173 {
3174 AddressDescriptor* calleeAddressDescriptor = addressDescriptors.GetAddressDescriptor(callee);
3175 Location* loc = calleeAddressDescriptor->GetLocation();
3176 if (loc != null && loc is Register*)
3177 {
3178 calleeOperand = loc;
3179 }
3180 else
3181 {
3182 LoadOperandValue(callee, registerDescriptors.GetRegisterDescriptor(xReg), addressDescriptors, machineCode, line, this);
3183 calleeOperand = xReg;
3184 }
3185 zOperand = machineCode.context.GetLiteralOperand(0u);
3186 }
3187 MachineInstruction* callInst = machineCode.GetInstruction(cmsx.machine.CALL, this);
3188 callInst->AddOperand(xReg);
3189 callInst->AddOperand(calleeOperand);
3190 if (zOperand != null)
3191 {
3192 callInst->AddOperand(zOperand);
3193 }
3194 List<Register*> dontUse;
3195 RegisterDescriptor* resultRegDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
3196 Register* resultReg = resultRegDescriptor->reg;
3197 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, this);
3198 Registers& regs = machineCode.context.regs;
3199 Register* ax = regs.GetParamRegister(0u);
3200 setInst->AddOperand(resultReg);
3201 setInst->AddOperand(ax);
3202 resultRegDescriptor->SetValue(this);
3203 AddressDescriptor* resultAddressDescriptor = addressDescriptors.GetAddressDescriptor(this);
3204 resultAddressDescriptor->SetLocation(resultReg);
3205 addressDescriptors.RemoveRegisterFromAllBut(this, resultReg);
3206 EndGenerateCode();
3207 if (Flags.Get(Flag.debug))
3208 {
3209 Print(formatter);
3210 formatter.WriteLine();
3211 formatter.IncIndent();
3212 registerDescriptors.DebugPrint(formatter);
3213 addressDescriptors.DebugPrint(formatter);
3214 formatter.DecIndent();
3215 }
3216 }
3217 public Value* callee;
3218 }
3219
3220 public class TrapInstruction : ValueInstruction
3221 {
3222 public nothrow TrapInstruction(Value* result_, Value* b0_, Value* b1_, Value* b2_, int line_) : base(line_), b0(b0_), b1(b1_), b2(b2_)
3223 {
3224 SetResult(result_);
3225 }
3226 public override nothrow string OperationName() const
3227 {
3228 return "trap";
3229 }
3230 public override void Validate(Function& function, int numArgs)
3231 {
3232 base->Validate(function, numArgs);
3233 b0 = function.ResolveOperand(line, b0);
3234 if (b0 == null)
3235 {
3236 throw Exception("error: parameter 0 in the " + OperationName() + " instruction at line " + ToString(line) + " is null");
3237 }
3238 if (!(b0->type is ByteType*))
3239 {
3240 throw Exception("error: type of parameter 0 in the " + OperationName() + " instruction at line " + ToString(line) + " must be byte");
3241 }
3242 if (!(b0 is ByteValue*))
3243 {
3244 throw Exception("error: parameter 0 in the " + OperationName() + " instruction at line " + ToString(line) + " must be literal byte");
3245 }
3246 b1 = function.ResolveOperand(line, b1);
3247 if (b1 == null)
3248 {
3249 throw Exception("error: parameter 1 in the " + OperationName() + " instruction at line " + ToString(line) + " is null");
3250 }
3251 if (!(b1->type is ByteType*))
3252 {
3253 throw Exception("error: type of parameter 1 in the " + OperationName() + " instruction at line " + ToString(line) + " must be byte");
3254 }
3255 if (!(b1 is ByteValue*))
3256 {
3257 throw Exception("error: parameter 1 in the " + OperationName() + " instruction at line " + ToString(line) + " must be a literal byte");
3258 }
3259 b2 = function.ResolveOperand(line, b2);
3260 if (b2 == null)
3261 {
3262 throw Exception("error: parameter 2 in the " + OperationName() + " instruction at line " + ToString(line) + " is null");
3263 }
3264 if (!(b2->type is ByteType*))
3265 {
3266 throw Exception("error: type of parameter 2 in the " + OperationName() + " instruction at line " + ToString(line) + " must be byte");
3267 }
3268 if (!(b2 is ByteValue*))
3269 {
3270 throw Exception("error: parameter 2 in the " + OperationName() + " instruction at line " + ToString(line) + " must be a literal byte");
3271 }
3272 parent->function.ResetNextArgIndex();
3273 }
3274 public override void Print(CodeFormatter& formatter)
3275 {
3276 base->Print(formatter);
3277 formatter << " " << b0->type->Name() << " " << b0->Name() << "," << b1->type->Name() << " " << b1->Name() << "," << b2->type->Name() << " " << b2->Name();
3278 }
3279 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
3280 {
3281 BeginGenerateCode(machineCode);
3282 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
3283 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
3284 MachineInstruction* trapInst = machineCode.GetInstruction(cmsx.machine.TRAP, this);
3285 byte byte0 = 0u;
3286 #assert(b0 is ByteValue*);
3287 byte0 = cast<ByteValue*>(b0)->value;
3288 trapInst->AddOperand(machineCode.context.GetLiteralOperand(byte0));
3289 byte byte1 = 0u;
3290 #assert(b1 is ByteValue*);
3291 byte1 = cast<ByteValue*>(b1)->value;
3292 trapInst->AddOperand(machineCode.context.GetLiteralOperand(byte1));
3293 byte byte2 = 0u;
3294 #assert(b2 is ByteValue*);
3295 byte2 = cast<ByteValue*>(b2)->value;
3296 trapInst->AddOperand(machineCode.context.GetLiteralOperand(byte2));
3297 List<Register*> dontUse;
3298 RegisterDescriptor* resultRegDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUse, addressDescriptors, machineCode, line, this);
3299 Register* resultReg = resultRegDescriptor->reg;
3300 Registers& regs = machineCode.context.regs;
3301 Register* ax = regs.GetParamRegister(0u);
3302 MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SET, this);
3303 setInst->AddOperand(resultReg);
3304 setInst->AddOperand(ax);
3305 resultRegDescriptor->SetValue(this);
3306 AddressDescriptor* resultAddressDescriptor = addressDescriptors.GetAddressDescriptor(this);
3307 resultAddressDescriptor->SetLocation(resultReg);
3308 addressDescriptors.RemoveRegisterFromAllBut(this, resultReg);
3309 EndGenerateCode();
3310 if (Flags.Get(Flag.debug))
3311 {
3312 Print(formatter);
3313 formatter.WriteLine();
3314 formatter.IncIndent();
3315 registerDescriptors.DebugPrint(formatter);
3316 addressDescriptors.DebugPrint(formatter);
3317 formatter.DecIndent();
3318 }
3319 }
3320 public Value* b0;
3321 public Value* b1;
3322 public Value* b2;
3323 }
3324
3325 public class RetInstruction : TerminatorInstruction
3326 {
3327 public nothrow RetInstruction(Value* value_, int line_) : base(line_), value(value_)
3328 {
3329 }
3330 public override nothrow string Name() const
3331 {
3332 return "ret";
3333 }
3334 public override nothrow string OperationName() const
3335 {
3336 return "ret";
3337 }
3338 public override void Validate(Function& function, int numArgs)
3339 {
3340 base->Validate(function, numArgs);
3341 if (value != null)
3342 {
3343 value = function.ResolveOperand(line, value);
3344 if (!(value->type is ScalarType*))
3345 {
3346 throw Exception("error: the value type '" + value->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be a scalar type");
3347 }
3348 }
3349 }
3350 public override void Print(CodeFormatter& formatter)
3351 {
3352 base->Print(formatter);
3353 if (value == null)
3354 {
3355 formatter << " void";
3356 }
3357 else
3358 {
3359 formatter << " " << value->type->Name() << " " << value->Name();
3360 }
3361 }
3362 public override nothrow void BeginComputeLivenessAndNextUse()
3363 {
3364 base->BeginComputeLivenessAndNextUse();
3365 if (value != null)
3366 {
3367 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(value);
3368 if (p != null)
3369 {
3370 livenessAndNextUse[value] = *p;
3371 }
3372 }
3373 }
3374 public override nothrow void EndComputeLivenessAndNextUse()
3375 {
3376 base->EndComputeLivenessAndNextUse();
3377 if (value != null)
3378 {
3379 parent->SetValueLivenessAndNextUse(value, Liveness.live, this);
3380 }
3381 }
3382 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
3383 {
3384 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
3385 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
3386 BeginGenerateCode(machineCode);
3387 if (value != null)
3388 {
3389 Registers& regs = machineCode.context.regs;
3390 Register* ax = regs.GetParamRegister(0u);
3391 if (value is LiteralValue*)
3392 {
3393 value->GenerateSetValue(ax, machineCode, line, this);
3394 }
3395 else
3396 {
3397 AddressDescriptor* valueAddressDescriptor = addressDescriptors.GetAddressDescriptor(value);
3398 if (!valueAddressDescriptor->HasLocation(ax))
3399 {
3400 Location* loc = valueAddressDescriptor->GetLocation();
3401 if (loc == null)
3402 {
3403 loc = value->HomeLocation();
3404 }
3405 if (loc != null)
3406 {
3407 if (loc is Register*)
3408 {
3409 MachineInstruction* setInstruction = machineCode.GetInstruction(cmsx.assembly.SET, this);
3410 setInstruction->AddOperand(ax);
3411 setInstruction->AddOperand(loc);
3412 }
3413 else
3414 {
3415 loc->GenerateLoad(value->type->GetLoadOp(line), ax, machineCode, this);
3416 }
3417 }
3418 else
3419 {
3420 throw Exception("location for value not found in the " + OperationName() + " instruction at line " + ToString(line));
3421 }
3422 }
3423 }
3424 }
3425 if (parent->Instructions().Count() == 1 || parent != parent->function.basicBlocks.Back().Get())
3426 {
3427 MachineInstruction* jumpInst = machineCode.GetInstruction(cmsx.machine.JMP, this);
3428 jumpInst->AddOperand(machineCode.context.GetSymbolOperand("@" + ToString(parent->function.epilog.Id())));
3429 }
3430 EndGenerateCode();
3431 if (Flags.Get(Flag.debug))
3432 {
3433 Print(formatter);
3434 formatter.WriteLine();
3435 formatter.IncIndent();
3436 registerDescriptors.DebugPrint(formatter);
3437 addressDescriptors.DebugPrint(formatter);
3438 formatter.DecIndent();
3439 }
3440 }
3441 public Value* value;
3442 }
3443
3444 public class SwitchInstruction : TerminatorInstruction
3445 {
3446 public nothrow SwitchInstruction(Value* cond_, uint defaultTarget_, int line_) : base(line_), cond(cond_), defaultTarget(defaultTarget_)
3447 {
3448 }
3449 public nothrow void AddCase(Value* caseValue, uint caseTarget)
3450 {
3451 destinations.Add(MakePair(caseValue, caseTarget));
3452 }
3453 public override nothrow string Name() const
3454 {
3455 return "switch";
3456 }
3457 public override nothrow string OperationName() const
3458 {
3459 return "switch";
3460 }
3461 public override void Validate(Function& function, int numArgs)
3462 {
3463 base->Validate(function, numArgs);
3464 cond = function.ResolveOperand(line, cond);
3465 if (cond == null)
3466 {
3467 throw Exception("internal error : cond operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
3468 }
3469 if (!(cond->type is IntegerType*))
3470 {
3471 throw Exception("error: the condition type '" + cond->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
3472 }
3473 defaultDestination = function.GetBasicBlock(defaultTarget);
3474 if (defaultDestination != null)
3475 {
3476 defaultDestination->AddPredecessor(parent);
3477 }
3478 else
3479 {
3480 throw Exception("error: the default target block " + ToString(defaultTarget) + " for the " + OperationName() + " instruction at line " + ToString(line) + " not found");
3481 }
3482 for (const Pair<Value*, uint>& p : destinations)
3483 {
3484 Value* value = p.first;
3485 value = function.ResolveOperand(line, value);
3486 if (value == null)
3487 {
3488 throw Exception("internal error : value operand of " + OperationName() + " instruction at line " + ToString(line) + " is null");
3489 }
3490 uint dest = p.second;
3491 if (!(value->type is IntegerType*))
3492 {
3493 throw Exception("error: the " + ToString(dest) + "'th case expression type '" + value->type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line) + " must be an integer type");
3494 }
3495 BasicBlock* bb = function.GetBasicBlock(dest);
3496 if (bb != null)
3497 {
3498 bb->AddPredecessor(parent);
3499 destinationBlocks.Add(MakePair(value, bb));
3500 }
3501 else
3502 {
3503 throw Exception("error: the case target block " + ToString(dest) + " for the " + OperationName() + " instruction at line " + ToString(line) + " not found");
3504 }
3505 }
3506 }
3507 public override void Print(CodeFormatter& formatter)
3508 {
3509 base->Print(formatter);
3510 formatter << " " << cond->type->Name() << " " << cond->Name() << " " << defaultDestination->Name() << ", [";
3511 bool first = true;
3512 for (const Pair<Value*, BasicBlock*>& p : destinationBlocks)
3513 {
3514 Value* value = p.first;
3515 BasicBlock* bb = p.second;
3516 if (first)
3517 {
3518 first = false;
3519 }
3520 else
3521 {
3522 formatter << " : ";
3523 }
3524 formatter << value->type->Name() << " " << value->Name() << ", " << bb->Name();
3525 }
3526 formatter << "]";
3527 }
3528 public override nothrow void BeginComputeLivenessAndNextUse()
3529 {
3530 base->BeginComputeLivenessAndNextUse();
3531 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(cond);
3532 if (p != null)
3533 {
3534 livenessAndNextUse[cond] = *p;
3535 }
3536 for (const Pair<Value*, BasicBlock*>& d : destinationBlocks)
3537 {
3538 Value* value = d.first;
3539 Pair<Liveness, Value*>* p = parent->GetCurrentLivenessAndNextUse(value);
3540 if (p != null)
3541 {
3542 livenessAndNextUse[value] = *p;
3543 }
3544 }
3545 }
3546 public override nothrow void EndComputeLivenessAndNextUse()
3547 {
3548 base->EndComputeLivenessAndNextUse();
3549 parent->SetValueLivenessAndNextUse(cond, Liveness.live, this);
3550 for (const Pair<Value*, BasicBlock*>& d : destinationBlocks)
3551 {
3552 Value* value = d.first;
3553 parent->SetValueLivenessAndNextUse(value, Liveness.live, this);
3554 }
3555 }
3556 public override void GenerateCode(MachineCode& machineCode, CodeFormatter& formatter)
3557 {
3558 BeginGenerateCode(machineCode);
3559 int binOpCode = -1;
3560 if (cond->type is SignedIntegerType*)
3561 {
3562 binOpCode = cmsx.machine.CMP;
3563 }
3564 else if (cond->type is UnsignedIntegerType*)
3565 {
3566 binOpCode = cmsx.machine.CMPU;
3567 }
3568 if (binOpCode == -1)
3569 {
3570 throw Exception("error: tried to generate switch condition comparison instruction for type '" + type->Name() + "' in the " + OperationName() + " instruction at line " + ToString(line));
3571 }
3572 Value* x = this;
3573 Value* y = cond;
3574 Value* z = cond->type->DefaultValue();
3575 RegisterDescriptor* rx = null;
3576 RegisterDescriptor* ry = null;
3577 RegisterDescriptor* rz = null;
3578 RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
3579 AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
3580 GetReg(x, y, z, false, registerDescriptors, addressDescriptors, machineCode, line, rx, ry, rz, this);
3581 if (y is LiteralValue*)
3582 {
3583 y->GenerateSetValue(ry->reg, machineCode, line, this);
3584 }
3585 else
3586 {
3587 LoadOperandValue(y, ry, addressDescriptors, machineCode, line, this);
3588 }
3589 for (const Pair<Value*, BasicBlock*>& destinationBlock : destinationBlocks)
3590 {
3591 Value* caseValue = destinationBlock.first;
3592 BasicBlock* caseTargetBlock = destinationBlock.second;
3593 caseValue->GenerateSetValue(rz->reg, machineCode, line, this);
3594 MachineInstruction* comparisonInstruction = machineCode.GetInstruction(binOpCode, this);
3595 comparisonInstruction->AddOperand(rx->reg);
3596 comparisonInstruction->AddOperand(ry->reg);
3597 comparisonInstruction->AddOperand(rz->reg);
3598 MachineInstruction* branchInstruction = machineCode.GetInstruction(cmsx.machine.BZ, this);
3599 branchInstruction->AddOperand(rx->reg);
3600 branchInstruction->AddOperand(machineCode.context.GetSymbolOperand("@" + ToString(caseTargetBlock->Id())));
3601 }
3602 MachineInstruction* jumpInstruction = machineCode.GetInstruction(cmsx.machine.JMP, this);
3603 jumpInstruction->AddOperand(machineCode.context.GetSymbolOperand("@" + ToString(defaultDestination->Id())));
3604 EndGenerateCode();
3605 if (Flags.Get(Flag.debug))
3606 {
3607 Print(formatter);
3608 formatter.WriteLine();
3609 formatter.IncIndent();
3610 registerDescriptors.DebugPrint(formatter);
3611 addressDescriptors.DebugPrint(formatter);
3612 formatter.DecIndent();
3613 }
3614 }
3615 public Value* cond;
3616 public uint defaultTarget;
3617 public BasicBlock* defaultDestination;
3618 public List<Pair<Value*, uint>> destinations;
3619 public List<Pair<Value*, BasicBlock*>> destinationBlocks;
3620 }
3621 }