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 = 0ulive = 1u
  10     }
  11 
  12     public enum Operator : byte
  13     {
  14         addsubmuldivmodand_or_xor_shlshrequalless
  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& functionint 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()6FormatJustify.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 fieldPosCodeFormatter& 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<LivenessValue*>>& 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<LivenessValue*>& 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& machineCodeCodeFormatter& 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.BSPECthis);
 145                                 MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTAnull);
 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.ESPECnull);
 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.BSPECthis);
 168                             MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTAnull);
 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.ESPECnull);
 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(016);
 193                                     string catchedTypeIdStr2 = catchedTypeId.Substring(1616);
 194                                     ulong catchedTypeId1 = ParseHexULong(catchedTypeIdStr1);
 195                                     ulong catchedTypeId2 = ParseHexULong(catchedTypeIdStr2);
 196                                     MachineInstruction* bspecInst = machineCode.GetInstruction(cmsx.assembly.BSPECthis);
 197                                     MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTAnull);
 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.ESPECnull);
 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.BSPECthis);
 240                             MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTAnull);
 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.ESPECnull);
 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.BSPECthis);
 258                             MachineInstruction* octaInst = machineCode.GetInstruction(cmsx.assembly.OCTAnull);
 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.ESPECnull);
 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& formatterbool& printed)
 286         {
 287             printed = false;
 288             if (startMachineInstructionIndex == endMachineInstructionIndex) return;
 289             formatter.WriteLine();
 290             formatter.IncIndent();
 291             machineCode->PrintRange(startMachineInstructionIndexendMachineInstructionIndexformatter);
 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<LivenessValue*>> 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& functionint numArgs)
 331         {
 332             base->Validate(functionnumArgs);
 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) + ")"6FormatJustify.right);
 358             string t = Format(type->Name()7FormatWidth.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<LivenessValue*>* 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(thisLiveness.deadnull);
 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& functionint numArgs)
 395         {
 396             base->Validate(functionnumArgs);
 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(linearg);
 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<LivenessValue*>* 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(argLiveness.livethis);
 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& functionint numArgs)
 444         {
 445             base->Validate(functionnumArgs);
 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(lineleft);
 455             left->IncNumUses();
 456             right = function.ResolveOperand(lineright);
 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<LivenessValue*>* p1 = parent->GetCurrentLivenessAndNextUse(left);
 475             if (p1 != null)
 476             {
 477                 livenessAndNextUse[left] = *p1;
 478             }
 479             Pair<LivenessValue*>* 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(leftLiveness.livethis);
 489             parent->SetValueLivenessAndNextUse(rightLiveness.livethis);
 490         }
 491         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(yregisterDescriptorsaddressDescriptors);
 608             GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
 609             if (y is LiteralValue*)
 610             {
 611                 y->GenerateSetValue(ry->regmachineCodelinethis);
 612             }
 613             else
 614             {
 615                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
 616             }
 617             if (z != null)
 618             {
 619                 if (z is LiteralValue*)
 620                 {
 621                     z->GenerateSetValue(rz->regmachineCodelinethis);
 622                 }
 623                 else
 624                 {
 625                     LoadOperandValue(zrzaddressDescriptorsmachineCodelinethis);
 626                 }
 627             }
 628             MachineInstruction* machineInstruction = machineCode.GetInstruction(binOpCodethis);
 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(xrx->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& functionint numArgs)
 673         {
 674             base->Validate(functionnumArgs);
 675         }
 676         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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& functionint numArgs)
 697         {
 698             base->Validate(functionnumArgs);
 699         }
 700         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(numParamRegsnumParams);
 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.SETnull);
 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& functionint numArgs)
 748         {
 749             base->Validate(functionnumArgs);
 750             ValidateTypes();
 751         }
 752         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(yregisterDescriptorsaddressDescriptors);
 768             GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
 769             if (y is LiteralValue*)
 770             {
 771                 y->GenerateSetValue(ry->regmachineCodelinethis);
 772             }
 773             else
 774             {
 775                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
 776             }
 777             if (z != null)
 778             {
 779                 type->GenerateMinusOne(machineCoderz->reglinethis);
 780                 ConstantValue* constantValue = new ConstantValue();
 781                 machineCode.context.AddValue(constantValue);
 782                 rz->SetValue(constantValue);
 783             }
 784             MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.machine.XORthis);
 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.contextline));
 794             }
 795             rx->SetValue(x);
 796             AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
 797             adx->SetLocation(rx->reg);
 798             addressDescriptors.RemoveRegisterFromAllBut(xrx->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& functionint numArgs)
 822         {
 823             base->Validate(functionnumArgs);
 824             ValidateTypes();
 825         }
 826         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(yregisterDescriptorsaddressDescriptors);
 838             GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
 839             if (y is LiteralValue*)
 840             {
 841                 y->GenerateSetValue(ry->regmachineCodelinethis);
 842             }
 843             else
 844             {
 845                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
 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(negOpCodethis);
 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(xrx->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& functionint numArgs)
 890         {
 891             base->Validate(functionnumArgs);
 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& functionint numArgs)
 906         {
 907             base->Validate(functionnumArgs);
 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& functionint numArgs)
 922         {
 923             base->Validate(functionnumArgs);
 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& functionint numArgs)
 938         {
 939             base->Validate(functionnumArgs);
 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& functionint numArgs)
 954         {
 955             base->Validate(functionnumArgs);
 956             ValidateTypes();
 957         }
 958         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& formatter)
 959         {
 960             base->GenerateCode(machineCodeformatter);
 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.GETthis);
 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& functionint numArgs)
 990         {
 991             base->Validate(functionnumArgs);
 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& functionint numArgs)
1006         {
1007             base->Validate(functionnumArgs);
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& functionint numArgs)
1022         {
1023             base->Validate(functionnumArgs);
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& functionint numArgs)
1038         {
1039             base->Validate(functionnumArgs);
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& functionint numArgs)
1054         {
1055             base->Validate(functionnumArgs);
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& functionint numArgs)
1070         {
1071             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& formatter)
1082         {
1083             base->GenerateCode(machineCodeformatter);
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.ZSZthis);
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& functionint numArgs)
1114         {
1115             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& formatter)
1126         {
1127             base->GenerateCode(machineCodeformatter);
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.ZSNthis);
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& functionint numArgs)
1158         {
1159             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& 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(dontUseaddressDescriptorsmachineCodelinethis);
1184                 Value* value = y->SignExtendTo(typeline);
1185                 machineCode.context.AddValue(value);
1186                 value->GenerateSetValue(rx->regmachineCodelinethis);
1187             }
1188             else
1189             {
1190                 bool useRegYForX = CanUseRegYForX(yregisterDescriptorsaddressDescriptors);
1191                 GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
1192                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
1193                 ulong numShiftBits = 64u - 8u * cast<ulong>(y->type->Size());
1194                 Operand* numShiftBitsOperand = machineCode.context.GetLiteralOperand(numShiftBits);
1195                 MachineInstruction* shiftLeftInst = machineCode.GetInstruction(cmsx.machine.SLUthis);
1196                 shiftLeftInst->AddOperand(rx->reg);
1197                 shiftLeftInst->AddOperand(ry->reg);
1198                 shiftLeftInst->AddOperand(numShiftBitsOperand);
1199                 MachineInstruction* shiftRightInst = machineCode.GetInstruction(cmsx.machine.SRthis);
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(xrx->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& functionint numArgs)
1231         {
1232             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& 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(dontUseaddressDescriptorsmachineCodelinethis);
1257                 Value* value = y->ZeroExtendTo(typeline);
1258                 machineCode.context.AddValue(value);
1259                 value->GenerateSetValue(rx->regmachineCodelinethis);
1260             }
1261             else
1262             {
1263                 bool useRegYForX = CanUseRegYForX(yregisterDescriptorsaddressDescriptors);
1264                 GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
1265                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
1266                 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.SETthis);
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(xrx->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& functionint numArgs)
1297         {
1298             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& 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(dontUseaddressDescriptorsmachineCodelinethis);
1323                 Value* value = y->TruncateTo(typeline);
1324                 machineCode.context.AddValue(value);
1325                 value->GenerateSetValue(rx->regmachineCodelinethis);
1326             }
1327             else
1328             {
1329                 bool useRegYForX = CanUseRegYForX(yregisterDescriptorsaddressDescriptors);
1330                 GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
1331                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
1332                 List<Register*> dontUse;
1333                 dontUse.Add(rx->reg);
1334                 dontUse.Add(ry->reg);
1335                 rz = registerDescriptors.GetLocalRegDescriptor(dontUseaddressDescriptorsmachineCodelinethis);
1336                 type->GenerateMinusOne(machineCoderz->reglinethis);
1337                 ConstantValue* constantValue = new ConstantValue();
1338                 machineCode.context.AddValue(constantValue);
1339                 rz->SetValue(constantValue);
1340                 MachineInstruction* andInst = machineCode.GetInstruction(cmsx.machine.ANDthis);
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.SLUthis);
1349                     shiftLeftInst->AddOperand(rx->reg);
1350                     shiftLeftInst->AddOperand(rx->reg);
1351                     shiftLeftInst->AddOperand(numShiftBitsOperand);
1352                     MachineInstruction* shiftRightInst = machineCode.GetInstruction(cmsx.machine.SRthis);
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(xrx->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& functionint numArgs)
1385         {
1386             base->Validate(functionnumArgs);
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())addrValueNamecast<SymbolValue*>(arg)0true);
1402                 }
1403             }
1404         }
1405         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(dontUseaddressDescriptorsmachineCodelinethis);
1421                 y->GenerateSetValue(rx->regmachineCodelinethis);
1422                 loaded = true;
1423             }
1424             else if (y is LocalInstruction*)
1425             {
1426                 List<Register*> dontUse;
1427                 rx = registerDescriptors.GetLocalRegDescriptor(dontUseaddressDescriptorsmachineCodelinethis);
1428                 LoadOperandAddress(yrxaddressDescriptorsmachineCodelinethis);
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(dontUseaddressDescriptorsmachineCodelinethis);
1439                     LoadOperandAddress(yrxaddressDescriptorsmachineCodelinethis);
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.LDOUthis);
1447                 List<Register*> dontUse;
1448                 rx = registerDescriptors.GetLocalRegDescriptor(dontUseaddressDescriptorsmachineCodelinethis);
1449                 loadAddrInstruction->AddOperand(rx->reg);
1450                 loadAddrInstruction->AddOperand(machineCode.context.GetSymbolOperand(addrValueName));
1451                 MachineInstruction* loadInstruction = machineCode.GetInstruction(cmsx.machine.LDOUthis);
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(yregisterDescriptorsaddressDescriptors);
1460                 GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
1461                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
1462                 MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.SETthis);
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(xrx->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& functionint numArgs)
1493         {
1494             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& 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(yregisterDescriptorsaddressDescriptors);
1516             GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
1517             if (y is LiteralValue*)
1518             {
1519                 y->GenerateSetValue(ry->regmachineCodelinethis);
1520             }
1521             else
1522             {
1523                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
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(flotInstthis);
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(xrx->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& functionint numArgs)
1582         {
1583             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& 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(yregisterDescriptorsaddressDescriptors);
1605             GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
1606             if (y is LiteralValue*)
1607             {
1608                 y->GenerateSetValue(ry->regmachineCodelinethis);
1609             }
1610             else
1611             {
1612                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
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(fixInstthis);
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(xrx->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& functionint numArgs)
1657         {
1658             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& 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(yregisterDescriptorsaddressDescriptors);
1680             GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
1681             if (y is LiteralValue*)
1682             {
1683                 y->GenerateSetValue(ry->regmachineCodelinethis);
1684             }
1685             else
1686             {
1687                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
1688             }
1689             MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.SETthis);
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(xrx->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& functionint numArgs)
1719         {
1720             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& 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(yregisterDescriptorsaddressDescriptors);
1742             GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
1743             if (y is LiteralValue*)
1744             {
1745                 y->GenerateSetValue(ry->regmachineCodelinethis);
1746             }
1747             else
1748             {
1749                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
1750             }
1751             MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.SETthis);
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(xrx->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& functionint numArgs)
1782         {
1783             base->Validate(functionnumArgs);
1784         }
1785         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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& functionint numArgs)
1835         {
1836             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& 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& functionint numArgs)
1892         {
1893             base->Validate(functionnumArgs);
1894             ptr = function.ResolveOperand(lineptr);
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<LivenessValue*>* 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(ptrLiveness.livethis);
1927         }
1928         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(dontUseaddressDescriptorsmachineCodelinethis);
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(loadOpCodedestinationRegisterDescriptor->regmachineCodethis);
1953                 destinationRegisterDescriptor->SetValue(this);
1954                 destinationRegisterDescriptor->loaded = true;
1955                 addressDescriptors.RemoveRegisterFromAllBut(thisdestinationRegisterDescriptor->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& functionint numArgs)
1991         {
1992             base->Validate(functionnumArgs);
1993             value = function.ResolveOperand(linevalue);
1994             ptr = function.ResolveOperand(lineptr);
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<LivenessValue*>* p1 = parent->GetCurrentLivenessAndNextUse(value);
2024             if (p1 != null)
2025             {
2026                 livenessAndNextUse[value] = *p1;
2027             }
2028             Pair<LivenessValue*>* 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(ptrLiveness.deadnull);
2037             base->EndComputeLivenessAndNextUse();
2038             parent->SetValueLivenessAndNextUse(valueLiveness.livethis);
2039         }
2040         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(dontUseaddressDescriptorsmachineCodelinethis);
2051                 valueReg = valueRegisterDescriptor->reg;
2052                 value->GenerateSetValue(valueRegisterDescriptor->regmachineCodelinethis);
2053                 loaded = true;
2054             }
2055             else if (value is LocalInstruction*)
2056             {
2057                 List<Register*> dontUse;
2058                 RegisterDescriptor* valueRegisterDescriptor = registerDescriptors.GetLocalRegDescriptor(dontUseaddressDescriptorsmachineCodelinethis);
2059                 LoadOperandAddress(valuevalueRegisterDescriptoraddressDescriptorsmachineCodelinethis);
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(dontUseaddressDescriptorsmachineCodelinethis);
2071                     valueReg = valueRegisterDescriptor->reg;
2072                     LoadOperandAddress(valuevalueRegisterDescriptoraddressDescriptorsmachineCodelinethis);
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(dontUseaddressDescriptorsmachineCodelinethis);
2094                         int loadOpCode = value->type->GetLoadOp(line);
2095                         valueLoc->GenerateLoad(loadOpCodedestinationRegisterDescriptor->regmachineCodethis);
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(storeOpCodevalueRegmachineCodethis);
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& functionint numArgs)
2168         {
2169             base->Validate(functionnumArgs);
2170             ptr = function.ResolveOperand(lineptr);
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(lineindex);
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<LivenessValue*>* p1 = parent->GetCurrentLivenessAndNextUse(ptr);
2209             if (p1 != null)
2210             {
2211                 livenessAndNextUse[ptr] = *p1;
2212             }
2213             Pair<LivenessValue*>* 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(ptrLiveness.livethis);
2223             parent->SetValueLivenessAndNextUse(indexLiveness.livethis);
2224         }
2225         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
2265             if (y is LiteralValue*)
2266             {
2267                 y->GenerateSetValue(ry->regmachineCodelinethis);
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(yryaddressDescriptorsmachineCodelinethis);
2278                         operandLoaded = true;
2279                     }
2280                 }
2281                 else if (ptr is PtrValue*)
2282                 {
2283                     LoadOperandAddress(yryaddressDescriptorsmachineCodelinethis);
2284                     operandLoaded = true;
2285                 }
2286                 if (!operandLoaded)
2287                 {
2288                     LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
2289                 }
2290             }
2291             if (z is LiteralValue*)
2292             {
2293                 z->GenerateSetValue(rz->regmachineCodelinethis);
2294             }
2295             else
2296             {
2297                 LoadOperandValue(zrzaddressDescriptorsmachineCodelinethis);
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(ixmachineCodelinethis);
2309                 MachineInstruction* mulInstruction = machineCode.GetInstruction(cmsx.machine.MULthis);
2310                 mulInstruction->AddOperand(ix);
2311                 mulInstruction->AddOperand(rz->reg);
2312                 mulInstruction->AddOperand(ix);
2313             }
2314             MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.LDAthis);
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(xrx->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& functionint numArgs)
2355         {
2356             base->Validate(functionnumArgs);
2357             ptr = function.ResolveOperand(lineptr);
2358             offset = function.ResolveOperand(lineoffset);
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<LivenessValue*>* p1 = parent->GetCurrentLivenessAndNextUse(ptr);
2393             if (p1 != null)
2394             {
2395                 livenessAndNextUse[ptr] = *p1;
2396             }
2397             Pair<LivenessValue*>* 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(ptrLiveness.livethis);
2407             parent->SetValueLivenessAndNextUse(offsetLiveness.livethis);
2408         }
2409         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(yregisterDescriptorsaddressDescriptors);
2436             GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
2437             if (y is LiteralValue*)
2438             {
2439                 y->GenerateSetValue(ry->regmachineCodelinethis);
2440             }
2441             else
2442             {
2443                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
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->regmachineCodelinethis);
2454                 }
2455                 else
2456                 {
2457                     LoadOperandValue(zrzaddressDescriptorsmachineCodelinethis);
2458                     if (size <= MaxValue<byte>())
2459                     {
2460                         MachineInstruction* mulInst = machineCode.GetInstruction(cmsx.machine.MULthis);
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(ixmachineCodelinethis);
2471                         MachineInstruction* mulInst = machineCode.GetInstruction(cmsx.machine.MULthis);
2472                         mulInst->AddOperand(rz->reg);
2473                         mulInst->AddOperand(rz->reg);
2474                         mulInst->AddOperand(ix);
2475                     }
2476                 }
2477             }
2478             MachineInstruction* machineInstruction = machineCode.GetInstruction(cmsx.assembly.LDAthis);
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(xrx->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& functionint numArgs)
2519         {
2520             base->Validate(functionnumArgs);
2521             leftPtr = function.ResolveOperand(lineleftPtr);
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(linerightPtr);
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<LivenessValue*>* p1 = parent->GetCurrentLivenessAndNextUse(leftPtr);
2557             if (p1 != null)
2558             {
2559                 livenessAndNextUse[leftPtr] = *p1;
2560             }
2561             Pair<LivenessValue*>* 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(leftPtrLiveness.livethis);
2571             parent->SetValueLivenessAndNextUse(rightPtrLiveness.livethis);
2572         }
2573         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(yregisterDescriptorsaddressDescriptors);
2588             GetReg(xyzuseRegYForXregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
2589             if (y is LiteralValue*)
2590             {
2591                 y->GenerateSetValue(ry->regmachineCodelinethis);
2592             }
2593             else
2594             {
2595                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
2596             }
2597             if (z is LiteralValue*)
2598             {
2599                 z->GenerateSetValue(rz->regmachineCodelinethis);
2600             }
2601             else
2602             {
2603                 LoadOperandValue(zrzaddressDescriptorsmachineCodelinethis);
2604             }
2605             MachineInstruction* subInstruction = machineCode.GetInstruction(cmsx.machine.SUBUthis);
2606             subInstruction->AddOperand(rx->reg);
2607             subInstruction->AddOperand(ry->reg);
2608             subInstruction->AddOperand(rz->reg);
2609             MachineInstruction* divInstruction = machineCode.GetInstruction(cmsx.machine.DIVUthis);
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(ixmachineCodelinethis);
2622                 divInstruction->AddOperand(ix);
2623             }
2624             rx->SetValue(x);
2625             AddressDescriptor* adx = addressDescriptors.GetAddressDescriptor(x);
2626             adx->SetLocation(rx->reg);
2627             addressDescriptors.RemoveRegisterFromAllBut(xrx->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& functionint numArgs)
2657         {
2658             base->Validate(functionnumArgs);
2659             arg = function.ResolveOperand(linearg);
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<LivenessValue*>* 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(argLiveness.livethis);
2689         }
2690         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(ixmachineCodelinethis);
2709                 MachineInstruction* ldaInst = machineCode.GetInstruction(cmsx.assembly.LDAthis);
2710                 ldaInst->AddOperand(sp);
2711                 ldaInst->AddOperand(sp);
2712                 ldaInst->AddOperand(ix);
2713                 MachineInstruction* storeInst = machineCode.GetInstruction(cmsx.machine.STOUthis);
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(argargRegDescriptoraddressDescriptorsmachineCodelinethis);
2733                 loaded = true;
2734             }
2735             else if (arg is LiteralValue*)
2736             {
2737                 arg->GenerateSetValue(argRegDescriptor->regmachineCodelinethis);
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.SETthis);
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(argargRegDescriptoraddressDescriptorsmachineCodelinethis);
2761                     }
2762                     else
2763                     {
2764                         Type* type = ptrValue->globalVariable->type;
2765                         if (type is ArrayType* || type is StructureType*)
2766                         {
2767                             LoadOperandAddress(argargRegDescriptoraddressDescriptorsmachineCodelinethis);
2768                         }
2769                         else
2770                         {
2771                             LoadOperandValue(argargRegDescriptoraddressDescriptorsmachineCodelinethis);
2772                         }
2773                     }
2774                 }
2775                 else
2776                 {
2777                     LoadOperandValue(argargRegDescriptoraddressDescriptorsmachineCodelinethis);
2778                 }
2779             }
2780             if (argIndex >= numParamRegs)
2781             {
2782                 argLocation->GenerateStore(arg->type->GetStoreOp(line)argRegmachineCodethis);
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& functionint numArgs)
2815         {
2816             base->Validate(functionnumArgs);
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& machineCodeCodeFormatter& formatter)
2830         {
2831             BeginGenerateCode(machineCode);
2832             MachineInstruction* jumpInst = machineCode.GetInstruction(cmsx.machine.JMPthis);
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& functionint numArgs)
2855         {
2856             base->Validate(functionnumArgs);
2857             cond = function.ResolveOperand(linecond);
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<LivenessValue*>* 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(condLiveness.livethis);
2889         }
2890         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(dontUseaddressDescriptorsmachineCodelinethis);
2900                 reg = condRegDescriptor->reg;
2901                 cond->GenerateSetValue(regmachineCodelinethis);
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(dontUseaddressDescriptorsmachineCodelinethis);
2921                         reg = condRegDescriptor->reg;
2922                         int loadOpCode = cond->type->GetLoadOp(line);
2923                         location->GenerateLoad(loadOpCoderegmachineCodethis);
2924                     }
2925                 }
2926             }
2927             MachineInstruction* branchInst = machineCode.GetInstruction(cmsx.machine.BPthis);
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.JMPthis);
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& functionint numArgs)
2962         {
2963             base->Validate(functionnumArgs);
2964             callee = function.ResolveOperand(linecallee);
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<LivenessValue*>* 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(calleeLiveness.livethis);
3004         }
3005         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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.LDOUthis);
3027                 loadInst->AddOperand(ix);
3028                 loadInst->AddOperand(sp);
3029                 loadInst->AddOperand(machineCode.context.GetLiteralOperand(0u));
3030                 MachineInstruction* subInst = machineCode.GetInstruction(cmsx.machine.SUBUthis);
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(calleeregisterDescriptors.GetRegisterDescriptor(xReg)addressDescriptorsmachineCodelinethis);
3055                     calleeOperand = xReg;
3056                 }
3057                 zOperand = machineCode.context.GetLiteralOperand(0u);
3058             }
3059             MachineInstruction* callInst = machineCode.GetInstruction(cmsx.machine.CALLthis);
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& functionint numArgs)
3091         {
3092             base->Validate(functionnumArgs);
3093             callee = function.ResolveOperand(linecallee);
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<LivenessValue*>* 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(calleeLiveness.livethis);
3133         }
3134         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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.LDOUthis);
3156                 loadInst->AddOperand(ix);
3157                 loadInst->AddOperand(sp);
3158                 loadInst->AddOperand(machineCode.context.GetLiteralOperand(0u));
3159                 MachineInstruction* subInst = machineCode.GetInstruction(cmsx.machine.SUBUthis);
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(calleeregisterDescriptors.GetRegisterDescriptor(xReg)addressDescriptorsmachineCodelinethis);
3183                     calleeOperand = xReg;
3184                 }
3185                 zOperand = machineCode.context.GetLiteralOperand(0u);
3186             }
3187             MachineInstruction* callInst = machineCode.GetInstruction(cmsx.machine.CALLthis);
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(dontUseaddressDescriptorsmachineCodelinethis);
3196             Register* resultReg = resultRegDescriptor->reg;
3197             MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SETthis);
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(thisresultReg);
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& functionint numArgs)
3231         {
3232             base->Validate(functionnumArgs);
3233             b0 = function.ResolveOperand(lineb0);
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(lineb1);
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(lineb2);
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& machineCodeCodeFormatter& formatter)
3280         {
3281             BeginGenerateCode(machineCode);
3282             RegisterDescriptors& registerDescriptors = parent->registerDescriptors;
3283             AddressDescriptors& addressDescriptors = parent->function.addressDescriptors;
3284             MachineInstruction* trapInst = machineCode.GetInstruction(cmsx.machine.TRAPthis);
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(dontUseaddressDescriptorsmachineCodelinethis);
3299             Register* resultReg = resultRegDescriptor->reg;
3300             Registers& regs = machineCode.context.regs;
3301             Register* ax = regs.GetParamRegister(0u);
3302             MachineInstruction* setInst = machineCode.GetInstruction(cmsx.assembly.SETthis);
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(thisresultReg);
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& functionint numArgs)
3339         {
3340             base->Validate(functionnumArgs);
3341             if (value != null)
3342             {
3343                 value = function.ResolveOperand(linevalue);
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<LivenessValue*>* 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(valueLiveness.livethis);
3380             }
3381         }
3382         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(axmachineCodelinethis);
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.SETthis);
3410                                 setInstruction->AddOperand(ax);
3411                                 setInstruction->AddOperand(loc);
3412                             }
3413                             else
3414                             {
3415                                 loc->GenerateLoad(value->type->GetLoadOp(line)axmachineCodethis);
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.JMPthis);
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* caseValueuint caseTarget)
3450         {
3451             destinations.Add(MakePair(caseValuecaseTarget));
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& functionint numArgs)
3462         {
3463             base->Validate(functionnumArgs);
3464             cond = function.ResolveOperand(linecond);
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(linevalue);
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(valuebb));
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<LivenessValue*>* 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<LivenessValue*>* 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(condLiveness.livethis);
3550             for (const Pair<Value*BasicBlock*>& d : destinationBlocks)
3551             {
3552                 Value* value = d.first;
3553                 parent->SetValueLivenessAndNextUse(valueLiveness.livethis);
3554             }
3555         }
3556         public override void GenerateCode(MachineCode& machineCodeCodeFormatter& 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(xyzfalseregisterDescriptorsaddressDescriptorsmachineCodelinerxryrzthis);
3581             if (y is LiteralValue*)
3582             {
3583                 y->GenerateSetValue(ry->regmachineCodelinethis);
3584             }
3585             else
3586             {
3587                 LoadOperandValue(yryaddressDescriptorsmachineCodelinethis);
3588             }
3589             for (const Pair<Value*BasicBlock*>& destinationBlock : destinationBlocks)
3590             {
3591                 Value* caseValue = destinationBlock.first;
3592                 BasicBlock* caseTargetBlock = destinationBlock.second;
3593                 caseValue->GenerateSetValue(rz->regmachineCodelinethis);
3594                 MachineInstruction* comparisonInstruction = machineCode.GetInstruction(binOpCodethis);
3595                 comparisonInstruction->AddOperand(rx->reg);
3596                 comparisonInstruction->AddOperand(ry->reg);
3597                 comparisonInstruction->AddOperand(rz->reg);
3598                 MachineInstruction* branchInstruction = machineCode.GetInstruction(cmsx.machine.BZthis);
3599                 branchInstruction->AddOperand(rx->reg);
3600                 branchInstruction->AddOperand(machineCode.context.GetSymbolOperand("@" + ToString(caseTargetBlock->Id())));
3601             }
3602             MachineInstruction* jumpInstruction = machineCode.GetInstruction(cmsx.machine.JMPthis);
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 }