1 using System;
2 using System.IO;
3 using System.Collections;
4 using CodeFormatter = System.Text.CodeFormatter;
5
6 namespace cmsx.intermediate
7 {
8 public const int separatorInstructionOpCode = -1;
9
10 public class MachineInstruction
11 {
12 public nothrow MachineInstruction(int opCode_) : opCode(opCode_)
13 {
14 }
15 public nothrow void SetLabel(const string& label_)
16 {
17 label = label_;
18 }
19 public nothrow void AddOperand(Operand* operand)
20 {
21 operands.Add(operand);
22 }
23 public nothrow void Print(CodeFormatter& formatter, int labelWidth)
24 {
25 if (opCode == separatorInstructionOpCode) return;
26 formatter << Format(label, labelWidth, FormatWidth.min) << " " << Format(cmsx.assembly.GetOpCodeStr(opCode),
27 Max(cmsx.machine.OpCodeMap.Instance().MaxOpCodeNameLength(), cmsx.assembly.PseudoOpMap.Instance().MaxOpCodeNameLength()), FormatWidth.min) << " ";
28 long n = operands.Count();
29 for (long i = 0; i < n; ++i;)
30 {
31 if (i > 0)
32 {
33 formatter << ",";
34 }
35 Operand* operand = operands[i];
36 operand->Print(formatter);
37 }
38 }
39 private string label;
40 private int opCode;
41 private List<Operand*> operands;
42 }
43
44 public class MachineCode
45 {
46 public nothrow MachineCode(Context& context_) : context(context_), prevInst(null)
47 {
48 }
49 public inline nothrow long CurrentIndex() const
50 {
51 return machineInstructions.Count();
52 }
53 public nothrow MachineInstruction* GetInstruction(int opCode, const string& label)
54 {
55 MachineInstruction* inst = GetInstruction(opCode, null);
56 inst->SetLabel(label);
57 return inst;
58 }
59 public nothrow MachineInstruction* GetInstruction(int opCode, Instruction* inst)
60 {
61 MachineInstruction* machineInstruction = new MachineInstruction(opCode);
62 if (inst != null && inst != prevInst && inst->IsLeader())
63 {
64 machineInstruction->SetLabel(inst->parent->Name());
65 prevInst = inst;
66 }
67 machineInstructions.Add(UniquePtr<MachineInstruction>(machineInstruction));
68 return machineInstruction;
69 }
70 public nothrow void EmitLineNumberInfo()
71 {
72 MachineInstruction* bspecInst = GetInstruction(cmsx.assembly.BSPEC, null);
73 MachineInstruction* octaInst = GetInstruction(cmsx.assembly.OCTA, null);
74 octaInst->AddOperand(context.GetLiteralOperand(cmsx.assembly.LINEINFO));
75 octaInst->AddOperand(context.GetLiteralOperand(currentLineNumber));
76 MachineInstruction* especInst = GetInstruction(cmsx.assembly.ESPEC, null);
77 }
78 public nothrow void PrintRange(long startIndex, long endIndex, CodeFormatter& formatter)
79 {
80 PrintRange(startIndex, endIndex, formatter, 6);
81 }
82 public nothrow void PrintRange(long startIndex, long endIndex, CodeFormatter& formatter, int labelWidth)
83 {
84 for (long i = startIndex; i < endIndex; ++i;)
85 {
86 MachineInstruction* inst = machineInstructions[i].Get();
87 inst->Print(formatter, labelWidth);
88 formatter.WriteLine();
89 }
90 }
91 public nothrow void Print(CodeFormatter& formatter)
92 {
93 PrintRange(0, machineInstructions.Count(), formatter, 80);
94 }
95 public nothrow void Print(const string& filePath)
96 {
97 StreamWriter writer = File.CreateText(filePath);
98 CodeFormatter formatter(writer);
99 Print(formatter);
100 }
101 public Context& context;
102 public uint currentLineNumber;
103 private List<UniquePtr<MachineInstruction>> machineInstructions;
104 private Instruction* prevInst;
105 }
106 }