1 using System;
   2 using System.Collections;
   3 using Span = System.Lex.Span;
   4 using cmsx.object;
   5 
   6 namespace cmsx.assembly
   7 {
   8     public enum Stage : byte
   9     {
  10         resolve = 0uassemble = 1uis_ = 2usetExternal = 3usetLinkOnce = 4ubytes = 5uwydes = 6utetras = 7uoctas = 8uclsid = 9uspec = 10ufuncInfo = 11ufileInfo = 12ulineInfo = 13u
  11         exceptionInfo = 14u
  12     }
  13 
  14     private AssemblyLexer* currentAssemblyLexer = null;
  15 
  16     public class ScopedAssemblyLexerPtr
  17     {
  18         public nothrow ScopedAssemblyLexerPtr(AssemblyLexer* lexer)
  19         {
  20             currentAssemblyLexer = lexer;
  21         }
  22         public ~ScopedAssemblyLexerPtr()
  23         {
  24             currentAssemblyLexer = null;
  25         }
  26     }
  27 
  28     public void Error(const string& messageconst Span& span)
  29     {
  30         if (currentAssemblyLexer != null)
  31         {
  32             throw Exception(message + ":\n" + ToUtf8(currentAssemblyLexer->ErrorLines(span)));
  33         }
  34         else
  35         {
  36             throw Exception(message);
  37         }
  38     }
  39 
  40     public class Assembler : Visitor
  41     {
  42         public Assembler(const string& objectFileName) : 
  43             objectFile(objectFileNametrue)stage(Stage.resolve)currentSegment(Segment.text)currentSection(objectFile.codeSection)currentInstruction(null)currentSymbol(null)currentValue()
  44             currentFunctionSymbol(null)currentStructureSymbol(null)externalLinkCommandOffset(0)
  45         {
  46         }
  47         public void Assemble(List<UniquePtr<Instruction>>& instructions)
  48         {
  49             currentSegment = Segment.text;
  50             currentSection = objectFile.codeSection;
  51             stage = Stage.resolve;
  52             long n = instructions.Count();
  53             for (long i = 0; i < n; ++i;)
  54             {
  55                 Instruction* inst = instructions[i].Get();
  56                 inst->Accept(*this);
  57             }
  58             currentSegment = Segment.text;
  59             currentSection = objectFile.codeSection;
  60             stage = Stage.assemble;
  61             for (long i = 0; i < n; ++i;)
  62             {
  63                 Instruction* inst = instructions[i].Get();
  64                 inst->Accept(*this);
  65             }
  66         }
  67         public void WriteObjectFile()
  68         {
  69             objectFile.Write();
  70         }
  71         public Value Evaluate(Node* node)
  72         {
  73             currentValue = Value();
  74             currentSymbol = null;
  75             node->Accept(*this);
  76             Value value = currentValue;
  77             currentValue = Value();
  78             return value;
  79         }
  80         public void EmitOpCode(byte opCode)
  81         {
  82             if (currentSegment != Segment.text)
  83             {
  84                 Error(currentInstruction->opCode->name + " instruction can appear only in .CODE section"currentInstruction->opCode->span);
  85             }
  86             currentSection->EmitByte(opCode);
  87         }
  88         public void EmitRegisterValue(const string& paramNameconst Value& v)
  89         {
  90             if (v.flags == Value.Flag.register)
  91             {
  92                 if (v.value < 256u)
  93                 {
  94                     currentSection->EmitByte(cast<byte>(v.value));
  95                 }
  96                 else
  97                 {
  98                     Error("invalid " + currentInstruction->opCode->name + " " + paramName + " register operand"currentInstruction->span);
  99                 }
 100             }
 101             else
 102             {
 103                 Error(currentInstruction->opCode->name + " instruction " + paramName + " operand must be a register"currentInstruction->span);
 104             }
 105         }
 106         public void EmitPureByteValue(const string& paramNameconst Value& v)
 107         {
 108             if (v.GetFlag(Value.Flag.pure))
 109             {
 110                 if (v.value < 256u)
 111                 {
 112                     currentSection->EmitByte(cast<byte>(v.value));
 113                 }
 114                 else
 115                 {
 116                     Error("invalid " + currentInstruction->opCode->name + " " + paramName + " byte operand"currentInstruction->span);
 117                 }
 118             }
 119             else
 120             {
 121                 Error(currentInstruction->opCode->name + " instruction " + paramName + " operand must be pure byte value"currentInstruction->span);
 122             }
 123         }
 124         public void EmitSetReg255Value(ulong value)
 125         {
 126             if (value <= MaxValue<ushort>())
 127             {
 128                 byte b0 = cast<byte>(value);
 129                 value = value >> 8u;
 130                 byte b1 = cast<byte>(value);
 131                 value = value >> 8u;
 132                 EmitOpCode(cmsx.machine.SETL);
 133                 currentSection->EmitByte(255u);
 134                 currentSection->EmitByte(b1);
 135                 currentSection->EmitByte(b0);
 136             }
 137             else if (value <= MaxValue<uint>())
 138             {
 139                 byte b0 = cast<byte>(value);
 140                 value = value >> 8u;
 141                 byte b1 = cast<byte>(value);
 142                 value = value >> 8u;
 143                 byte b2 = cast<byte>(value);
 144                 value = value >> 8u;
 145                 byte b3 = cast<byte>(value);
 146                 value = value >> 8u;
 147                 EmitOpCode(cmsx.machine.SETML);
 148                 currentSection->EmitByte(255u);
 149                 currentSection->EmitByte(b3);
 150                 currentSection->EmitByte(b2);
 151                 EmitOpCode(cmsx.machine.ORL);
 152                 currentSection->EmitByte(255u);
 153                 currentSection->EmitByte(b1);
 154                 currentSection->EmitByte(b0);
 155             }
 156             else
 157             {
 158                 byte b0 = cast<byte>(value);
 159                 value = value >> 8u;
 160                 byte b1 = cast<byte>(value);
 161                 value = value >> 8u;
 162                 byte b2 = cast<byte>(value);
 163                 value = value >> 8u;
 164                 byte b3 = cast<byte>(value);
 165                 value = value >> 8u;
 166                 byte b4 = cast<byte>(value);
 167                 value = value >> 8u;
 168                 byte b5 = cast<byte>(value);
 169                 value = value >> 8u;
 170                 byte b6 = cast<byte>(value);
 171                 value = value >> 8u;
 172                 byte b7 = cast<byte>(value);
 173                 value = value >> 8u;
 174                 EmitOpCode(cmsx.machine.SETH);
 175                 currentSection->EmitByte(255u);
 176                 currentSection->EmitByte(b7);
 177                 currentSection->EmitByte(b6);
 178                 EmitOpCode(cmsx.machine.ORMH);
 179                 currentSection->EmitByte(255u);
 180                 currentSection->EmitByte(b5);
 181                 currentSection->EmitByte(b4);
 182                 EmitOpCode(cmsx.machine.ORML);
 183                 currentSection->EmitByte(255u);
 184                 currentSection->EmitByte(b3);
 185                 currentSection->EmitByte(b2);
 186                 EmitOpCode(cmsx.machine.ORL);
 187                 currentSection->EmitByte(255u);
 188                 currentSection->EmitByte(b1);
 189                 currentSection->EmitByte(b0);
 190             }
 191         }
 192         public void EmitAbsoluteRegisterValue(const Value& registerNumberconst string& paramNameSymbol* symbol)
 193         {
 194             #assert(symbol->index != -1);
 195             byte reg = 0u;
 196             if (registerNumber.flags == Value.Flag.register)
 197             {
 198                 if (registerNumber.value < 256u)
 199                 {
 200                     reg = cast<byte>(registerNumber.value);
 201                 }
 202                 else
 203                 {
 204                     Error("invalid " + currentInstruction->opCode->name + " " + paramName + " register operand"currentInstruction->span);
 205                 }
 206             }
 207             else
 208             {
 209                 Error(currentInstruction->opCode->name + " instruction " + paramName + " operand must be a register"currentInstruction->span);
 210             }
 211             if (currentSegment != Segment.text)
 212             {
 213                 Error(currentInstruction->opCode->name + " instruction can appear only in .CODE section"currentInstruction->opCode->span);
 214             }
 215             objectFile.linkSection->EmitByte(LinkCode.absoluteAddrValue);
 216             objectFile.linkSection->EmitUInt(cast<uint>(symbol->index));
 217             objectFile.linkSection->EmitULong(objectFile.codeSection->Address());
 218             externalLinkCommandOffset = externalLinkCommandOffset + cast<int>(sizeof(byte) + sizeof(uint) + sizeof(ulong));
 219             objectFile.codeSection->EmitByte(cmsx.machine.SETH);
 220             objectFile.codeSection->EmitByte(reg);
 221             objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
 222             objectFile.codeSection->EmitByte(cmsx.machine.ORMH);
 223             objectFile.codeSection->EmitByte(reg);
 224             objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
 225             objectFile.codeSection->EmitByte(cmsx.machine.ORML);
 226             objectFile.codeSection->EmitByte(reg);
 227             objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
 228             objectFile.codeSection->EmitByte(cmsx.machine.ORL);
 229             objectFile.codeSection->EmitByte(reg);
 230             objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
 231         }
 232         public void EmitForwardLongJump(Symbol* symbol)
 233         {
 234             #assert(symbol->index != -1);
 235             if (currentSegment != Segment.text)
 236             {
 237                 Error(currentInstruction->opCode->name + " instruction can appear only in .CODE section"currentInstruction->opCode->span);
 238             }
 239             objectFile.linkSection->EmitByte(LinkCode.forwardLongJump);
 240             objectFile.linkSection->EmitUInt(cast<uint>(symbol->index));
 241             objectFile.linkSection->EmitULong(objectFile.codeSection->Address());
 242             objectFile.codeSection->EmitByte(cmsx.machine.JMP);
 243             objectFile.codeSection->EmitLongOffset(cast<uint>(-1));
 244         }
 245         public void EmitForwardShortJump(const string& paramNamebyte opCodeconst Value& registerNumberSymbol* symbol)
 246         {
 247             byte reg = 0u;
 248             if (registerNumber.flags == Value.Flag.register)
 249             {
 250                 if (registerNumber.value < 256u)
 251                 {
 252                     reg = cast<byte>(registerNumber.value);
 253                 }
 254                 else
 255                 {
 256                     Error("invalid " + currentInstruction->opCode->name + " " + paramName + " register operand"currentInstruction->span);
 257                 }
 258             }
 259             else
 260             {
 261                 Error(currentInstruction->opCode->name + " instruction " + paramName + " operand must be a register"currentInstruction->span);
 262             }
 263             #assert(symbol->index != -1);
 264             if (currentSegment != Segment.text)
 265             {
 266                 Error(currentInstruction->opCode->name + " instruction can appear only in .CODE section"currentInstruction->opCode->span);
 267             }
 268             objectFile.linkSection->EmitByte(LinkCode.forwardShortJump);
 269             objectFile.linkSection->EmitUInt(cast<uint>(symbol->index));
 270             objectFile.linkSection->EmitULong(objectFile.codeSection->Address());
 271             objectFile.codeSection->EmitByte(opCode);
 272             objectFile.codeSection->EmitByte(reg);
 273             objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
 274         }
 275         public void EmitLinkClsIdCommand(const Uuid& typeId)
 276         {
 277             objectFile.linkSection->EmitByte(LinkCode.clsid);
 278             objectFile.linkSection->EmitULong(objectFile.dataSection->Address());
 279             objectFile.linkSection->EmitULong(typeId.LeftHalf());
 280             objectFile.linkSection->EmitULong(typeId.RightHalf());
 281             externalLinkCommandOffset = externalLinkCommandOffset + cast<int>(sizeof(byte) + sizeof(ulong) + sizeof(ulong) + sizeof(ulong));
 282             objectFile.dataSection->EmitULong(cast<ulong>(-1));
 283         }
 284         public void EmitLongOffset(uint offset)
 285         {
 286             currentSection->EmitLongOffset(offset);
 287         }
 288         public void EmitShortOffset(ushort offset)
 289         {
 290             currentSection->EmitShortOffset(offset);
 291         }
 292         public override void Visit(Instruction& inst)
 293         {
 294             currentInstruction = &inst;
 295             if (stage == Stage.resolve)
 296             {
 297                 inst.opCode->Accept(*this);
 298                 if (currentInstruction->opCode->value == CODE)
 299                 {
 300                     currentSegment = Segment.text;
 301                     currentSection = objectFile.codeSection;
 302                     return;
 303                 }
 304                 else if (currentInstruction->opCode->value == DATA)
 305                 {
 306                     currentSegment = Segment.data;
 307                     currentSection = objectFile.dataSection;
 308                     return;
 309                 }
 310                 else if (currentInstruction->opCode->value == DEBUG)
 311                 {
 312                     currentSegment = Segment.data;
 313                     currentSection = objectFile.debugSection;
 314                     return;
 315                 }
 316                 if (!inst.label.IsNull())
 317                 {
 318                     int opc = currentInstruction->opCode->value;
 319                     if (opc == EXTERN || opc == LINKONCE)
 320                     {
 321                         Error("no label field allowed for EXTERN or LINKONCE instruction"inst.label->span);
 322                     }
 323                     else if (opc != IS)
 324                     {
 325                         inst.label->Accept(*this);
 326                     }
 327                 }
 328             }
 329             else if (stage == Stage.assemble)
 330             {
 331                 int opc = currentInstruction->opCode->value;
 332                 if (opc == CODE)
 333                 {
 334                     currentSegment = Segment.text;
 335                     currentSection = objectFile.codeSection;
 336                     return;
 337                 }
 338                 else if (opc == DATA)
 339                 {
 340                     currentSegment = Segment.data;
 341                     currentSection = objectFile.dataSection;
 342                     return;
 343                 }
 344                 else if (opc == DEBUG)
 345                 {
 346                     currentSegment = Segment.data;
 347                     currentSection = objectFile.debugSection;
 348                     return;
 349                 }
 350                 currentSymbol = null;
 351                 currentAlignment = 1u;
 352                 if (currentSection != objectFile.debugSection && !inSpec)
 353                 {
 354                     AlignAt();
 355                 }
 356                 if (!inst.label.IsNull())
 357                 {
 358                     if (opc == EXTERN || opc == LINKONCE)
 359                     {
 360                         Error("no label field allowed for EXTERN or LINKONCE instruction"inst.label->span);
 361                     }
 362                     else if (opc != IS)
 363                     {
 364                         currentInstruction->label->Accept(*this);
 365                         if (currentSymbol != null)
 366                         {
 367                             if (opc == FUNC)
 368                             {
 369                                 currentSymbol->value = Value(cast<Value.Flag>(Value.Flag.definition | Value.Flag.pure | Value.Flag.address | Value.Flag.function)currentSection->Address()currentSymbol);
 370                                 currentFunctionSymbol = currentSymbol;
 371                                 currentSymbol->start = currentSection->BaseAddress() + currentSection->Address();
 372                                 parentSymbolIndex = currentSymbol->index;
 373                                 currentSymbol->linkStart = externalLinkCommandOffset;
 374                                 currentSymbol->alignment = 4u;
 375                                 if (objectFile.debugSection is DebugSection*)
 376                                 {
 377                                     DebugSection* debugSection = cast<DebugSection*>(objectFile.debugSection);
 378                                     debugSection->EmitStartFunc(cast<uint>(currentSymbol->index));
 379                                 }
 380                                 else
 381                                 {
 382                                     throw Exception("debug section expected");
 383                                 }
 384                             }
 385                             else if (opc == STRUCT)
 386                             {
 387                                 currentSection->Align(8u);
 388                                 currentSymbol->value = Value(cast<Value.Flag>(Value.Flag.definition | Value.Flag.pure | Value.Flag.address | Value.Flag.structure)currentSection->Address()currentSymbol);
 389                                 currentStructureSymbol = currentSymbol;
 390                                 currentSymbol->start = currentSection->BaseAddress() + currentSection->Address();
 391                                 parentSymbolIndex = currentSymbol->index;
 392                                 currentSymbol->linkStart = externalLinkCommandOffset;
 393                                 currentSymbol->alignment = 8u;
 394                             }
 395                             else if (opc == ENDF)
 396                             {
 397                                 currentSymbol->length = currentSection->BaseAddress() + currentSection->Address() - currentSymbol->start;
 398                                 parentSymbolIndex = -1;
 399                                 currentSymbol->linkEnd = externalLinkCommandOffset;
 400                                 if (objectFile.debugSection is DebugSection*)
 401                                 {
 402                                     DebugSection* debugSection = cast<DebugSection*>(objectFile.debugSection);
 403                                     debugSection->EmitEndFunc(cast<uint>(currentSymbol->index));
 404                                 }
 405                                 else
 406                                 {
 407                                     throw Exception("debug section expected");
 408                                 }
 409                             }
 410                             else if (opc == ENDS)
 411                             {
 412                                 currentSymbol->length = cast<ulong>(Align(cast<long>(currentSection->BaseAddress() + currentSection->Address() - currentSymbol->start)currentSymbol->alignment));
 413                                 currentSection->Align(currentSymbol->alignment);
 414                                 parentSymbolIndex = -1;
 415                                 currentSymbol->linkEnd = externalLinkCommandOffset;
 416                             }
 417                             else
 418                             {
 419                                 currentSymbol->value = Value(cast<Value.Flag>(Value.Flag.pure | Value.Flag.address)currentSection->Address()currentSymbol);
 420                                 currentSymbol->start = currentSection->BaseAddress() + currentSection->Address();
 421                                 currentSymbol->alignment = currentAlignment;
 422                                 if (parentSymbolIndex != -1)
 423                                 {
 424                                     currentSymbol->parentIndex = parentSymbolIndex;
 425                                 }
 426                             }
 427                             objectFile.GetSymbolTable().AddSymbolToAddressMap(currentSymbol);
 428                         }
 429                         else
 430                         {
 431                             Error("label not found"currentInstruction->label->span);
 432                         }
 433                     }
 434                 }
 435                 if (opc != FUNC && opc != ENDF && opc != STRUCT && opc != ENDS)
 436                 {
 437                     AssemblyInstruction* assemblyInstruction = AssemblyInstructionMap.Instance().GetAssemblyInstruction(opccurrentInstruction->span);
 438                     assemblyInstruction->Assemble(*thiscurrentInstruction);
 439                 }
 440             }
 441         }
 442         public override void Visit(ClsIdConstant& clsIdConstant)
 443         {
 444             Uuid typeId = ParseUuid(clsIdConstant.typeId);
 445             EmitLinkClsIdCommand(typeId);
 446         }
 447         public override void Visit(OpCode& opCode)
 448         {
 449             const string& opCodeName = opCode.name;
 450             opCode.value = cmsx.machine.GetOpCode(opCodeName);
 451             if (opCode.value == -1)
 452             {
 453                 opCode.value = PseudoOpMap.Instance().GetCode(opCodeName);
 454             }
 455             if (opCode.value == -1)
 456             {
 457                 Error("unknown opcode '" + opCodeName + "'"opCode.span);
 458             }
 459         }
 460         public override void Visit(SymbolNode& node)
 461         {
 462             int opc = currentInstruction->opCode->value;
 463             if (stage == Stage.resolve)
 464             {
 465                 Symbol* symbol = objectFile.GetSymbolTable().GetSymbol(node.name);
 466                 if (symbol != null)
 467                 {
 468                     if (opc == ENDF)
 469                     {
 470                         currentFunctionSymbol = null;
 471                     }
 472                     else if (opc == ENDS)
 473                     {
 474                         currentStructureSymbol = null;
 475                     }
 476                     else
 477                     {
 478                         Error("symbol '" + node.name + "' already defined"node.span);
 479                     }
 480                 }
 481                 else
 482                 {
 483                     if (opc == ENDF)
 484                     {
 485                         Error("no corresponding FUNC '" + node.name + "' seen"node.span);
 486                     }
 487                     else if (opc == ENDS)
 488                     {
 489                         Error("no corresponding STRUCT '" + node.name + "' seen"node.span);
 490                     }
 491                     symbol = new Symbol();
 492                     if (node.local)
 493                     {
 494                         if (currentFunctionSymbol != null)
 495                         {
 496                             symbol->name = currentFunctionSymbol->name + node.name;
 497                             symbol->localName = node.name;
 498                         }
 499                         else
 500                         {
 501                             Error("local symbols can be used only inside FUNC"node.span);
 502                         }
 503                     }
 504                     else
 505                     {
 506                         symbol->name = node.name;
 507                     }
 508                     symbol->segment = currentSegment;
 509                     symbol->linkage = Linkage.internal_;
 510                     symbol->value = Value(Value.Flag.undefinedundefinedValuesymbol);
 511                     if (opc == FUNC)
 512                     {
 513                         currentFunctionSymbol = symbol;
 514                     }
 515                     else if (opc == STRUCT)
 516                     {
 517                         currentStructureSymbol = symbol;
 518                     }
 519                     symbol->start = 0u;
 520                     symbol->length = 0u;
 521                     symbol->section = currentSection;
 522                     objectFile.GetSymbolTable().AddSymbol(symbol);
 523                     if (currentSegment == Segment.data)
 524                     {
 525                         currentSection->AddSymbol(symbol);
 526                     }
 527                 }
 528             }
 529             else if (stage == Stage.assemble)
 530             {
 531                 if (opc == ENDF)
 532                 {
 533                     currentFunctionSymbol = null;
 534                 }
 535                 if (opc == ENDS)
 536                 {
 537                     currentStructureSymbol = null;
 538                 }
 539                 if (node.local)
 540                 {
 541                     if (currentFunctionSymbol != null)
 542                     {
 543                         currentSymbol = objectFile.GetSymbolTable().GetSymbol(currentFunctionSymbol->name + node.name);
 544                     }
 545                     else
 546                     {
 547                         Error("local symbols can be used only inside FUNC"node.span);
 548                     }
 549                 }
 550                 else
 551                 {
 552                     currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
 553                 }
 554                 if (currentSymbol == null)
 555                 {
 556                     currentSymbol = new Symbol();
 557                     currentSymbol->name = node.name;
 558                     currentSymbol->linkage = Linkage.undefined;
 559                     currentSymbol->value = Value(Value.Flag.undefinedundefinedValuecurrentSymbol);
 560                     currentSymbol->start = 0u;
 561                     currentSymbol->length = 0u;
 562                     currentSymbol->section = currentSection;
 563                     objectFile.GetSymbolTable().AddSymbol(currentSymbol);
 564                 }
 565                 currentValue = currentSymbol->value;
 566             }
 567             else if (stage == Stage.is_)
 568             {
 569                 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
 570                 if (currentSymbol != null)
 571                 {
 572                     Error("symbol '" + node.name + "' already defined"node.span);
 573                 }
 574                 else
 575                 {
 576                     currentSymbol = new Symbol();
 577                     currentSymbol->name = node.name;
 578                     currentSymbol->segment = Segment.unknown;
 579                     currentSymbol->linkage = Linkage.internal_;
 580                     currentSymbol->value = Value(Value.Flag.undefinedundefinedValuecurrentSymbol);
 581                     currentSymbol->start = 0u;
 582                     currentSymbol->length = 0u;
 583                     currentSymbol->section = currentSection;
 584                     objectFile.GetSymbolTable().AddSymbol(currentSymbol);
 585                 }
 586             }
 587             else if (stage == Stage.setExternal)
 588             {
 589                 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
 590                 if (currentSymbol != null)
 591                 {
 592                     currentSymbol->linkage = Linkage.external;
 593                 }
 594                 else
 595                 {
 596                     Error("symbol '" + node.name + " not found"node.span);
 597                 }
 598             }
 599             else if (stage == Stage.setLinkOnce)
 600             {
 601                 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
 602                 if (currentSymbol != null)
 603                 {
 604                     currentSymbol->linkage = Linkage.once;
 605                 }
 606                 else
 607                 {
 608                     Error("symbol '" + node.name + " not found"node.span);
 609                 }
 610             }
 611             else if (stage == Stage.octas)
 612             {
 613                 if (currentSegment != Segment.data)
 614                 {
 615                     Error("OCTA allowed only in .DATA section"node.span);
 616                 }
 617                 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
 618                 if (currentSymbol == null)
 619                 {
 620                     currentSymbol = new Symbol();
 621                     currentSymbol->name = node.name;
 622                     currentSymbol->segment = Segment.unknown;
 623                     currentSymbol->linkage = Linkage.undefined;
 624                     currentSymbol->value = Value(Value.Flag.undefinedundefinedValuecurrentSymbol);
 625                     currentSymbol->section = currentSection;
 626                     objectFile.GetSymbolTable().AddSymbol(currentSymbol);
 627                 }
 628                 objectFile.linkSection->EmitByte(LinkCode.farOcta);
 629                 objectFile.linkSection->EmitUInt(cast<uint>(currentSymbol->index));
 630                 objectFile.linkSection->EmitULong(objectFile.dataSection->Address());
 631                 externalLinkCommandOffset = externalLinkCommandOffset + cast<int>(sizeof(byte) + sizeof(uint) + sizeof(ulong));
 632                 objectFile.dataSection->EmitULong(cast<ulong>(-1));
 633             }
 634             else if (stage == Stage.clsid)
 635             {
 636                 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
 637                 if (currentSymbol == null)
 638                 {
 639                     Error("symbol '" + node.name + " not found"node.span);
 640                 }
 641             }
 642             else if (stage == Stage.funcInfo)
 643             {
 644                 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
 645                 if (currentSymbol == null)
 646                 {
 647                     Error("symbol '" + node.name + " not found"node.span);
 648                 }
 649                 else
 650                 {
 651                     currentValue = Value(Value.Flag.functionundefinedValuecurrentSymbol);
 652                 }
 653             }
 654             else
 655             {
 656                 Error("undefined symbol '" + node.name + "' and not in OCTA mode"node.span);
 657             }
 658         }
 659         private void ProcessValue(ulong valueconst Span& span)
 660         {
 661             currentValue = Value(Value.Flag.purevaluenull);
 662             if (stage == Stage.bytes)
 663             {
 664                 if (value > 255u)
 665                 {
 666                     Error("invalid BYTE operand"span);
 667                 }
 668                 else
 669                 {
 670                     currentSection->EmitByte(cast<byte>(currentValue.value));
 671                 }
 672             }
 673             else if (stage == Stage.wydes)
 674             {
 675                 if (value > 65535u)
 676                 {
 677                     Error("invalid WYDE operand"span);
 678                 }
 679                 else
 680                 {
 681                     byte b0 = cast<byte>(value);
 682                     value = value >> 8u;
 683                     byte b1 = cast<byte>(value);
 684                     value = value >> 8u;
 685                     currentSection->EmitByte(b1);
 686                     currentSection->EmitByte(b0);
 687                 }
 688             }
 689             else if (stage == Stage.tetras)
 690             {
 691                 if (value > 0xFFFFFFFFu)
 692                 {
 693                     Error("invalid TETRA operand"span);
 694                 }
 695                 else
 696                 {
 697                     byte b0 = cast<byte>(value);
 698                     value = value >> 8u;
 699                     byte b1 = cast<byte>(value);
 700                     value = value >> 8u;
 701                     byte b2 = cast<byte>(value);
 702                     value = value >> 8u;
 703                     byte b3 = cast<byte>(value);
 704                     value = value >> 8u;
 705                     currentSection->EmitByte(b3);
 706                     currentSection->EmitByte(b2);
 707                     currentSection->EmitByte(b1);
 708                     currentSection->EmitByte(b0);
 709                 }
 710             }
 711             else if (stage == Stage.octas)
 712             {
 713                 byte b0 = cast<byte>(value);
 714                 value = value >> 8u;
 715                 byte b1 = cast<byte>(value);
 716                 value = value >> 8u;
 717                 byte b2 = cast<byte>(value);
 718                 value = value >> 8u;
 719                 byte b3 = cast<byte>(value);
 720                 value = value >> 8u;
 721                 byte b4 = cast<byte>(value);
 722                 value = value >> 8u;
 723                 byte b5 = cast<byte>(value);
 724                 value = value >> 8u;
 725                 byte b6 = cast<byte>(value);
 726                 value = value >> 8u;
 727                 byte b7 = cast<byte>(value);
 728                 value = value >> 8u;
 729                 currentSection->EmitByte(b7);
 730                 currentSection->EmitByte(b6);
 731                 currentSection->EmitByte(b5);
 732                 currentSection->EmitByte(b4);
 733                 currentSection->EmitByte(b3);
 734                 currentSection->EmitByte(b2);
 735                 currentSection->EmitByte(b1);
 736                 currentSection->EmitByte(b0);
 737             }
 738         }
 739         public override void Visit(DecimalConstant& dc)
 740         {
 741             ProcessValue(dc.valuedc.span);
 742         }
 743         public override void Visit(HexConstant& hc)
 744         {
 745             ProcessValue(hc.valuehc.span);
 746         }
 747         public override void Visit(CharacterConstant& cc)
 748         {
 749             currentValue = Value(Value.Flag.purecast<ulong>(cc.value)null);
 750             if (stage == Stage.bytes)
 751             {
 752                 string s = ToString(cc.value);
 753                 for (char c : s)
 754                 {
 755                     currentSection->EmitByte(cast<byte>(c));
 756                 }
 757             }
 758             else if (stage == Stage.wydes)
 759             {
 760                 uint value = cast<uint>(cc.value);
 761                 if (value > 65535u)
 762                 {
 763                     Error("invalid WYDE operand"cc.span);
 764                 }
 765                 byte b1 = cast<byte>(value);
 766                 value = value >> 8u;
 767                 byte b0 = cast<byte>(value);
 768                 value = value >> 8u;
 769                 currentSection->EmitByte(b1);
 770                 currentSection->EmitByte(b0);
 771             }
 772             else if (stage == Stage.tetras)
 773             {
 774                 uint value = cast<uint>(cc.value);
 775                 byte b3 = cast<byte>(value);
 776                 value = value >> 8u;
 777                 byte b2 = cast<byte>(value);
 778                 value = value >> 8u;
 779                 byte b1 = cast<byte>(value);
 780                 value = value >> 8u;
 781                 byte b0 = cast<byte>(value);
 782                 value = value >> 8u;
 783                 currentSection->EmitByte(b3);
 784                 currentSection->EmitByte(b2);
 785                 currentSection->EmitByte(b1);
 786                 currentSection->EmitByte(b0);
 787             }
 788             else if (stage == Stage.octas)
 789             {
 790                 uint value = cast<uint>(cc.value);
 791                 byte b3 = cast<byte>(value);
 792                 value = value >> 8u;
 793                 byte b2 = cast<byte>(value);
 794                 value = value >> 8u;
 795                 byte b1 = cast<byte>(value);
 796                 value = value >> 8u;
 797                 byte b0 = cast<byte>(value);
 798                 value = value >> 8u;
 799                 currentSection->EmitByte(0u);
 800                 currentSection->EmitByte(0u);
 801                 currentSection->EmitByte(0u);
 802                 currentSection->EmitByte(0u);
 803                 currentSection->EmitByte(b3);
 804                 currentSection->EmitByte(b2);
 805                 currentSection->EmitByte(b1);
 806                 currentSection->EmitByte(b0);
 807             }
 808         }
 809         public override void Visit(At&)
 810         {
 811             currentValue = Value(cast<Value.Flag>(Value.Flag.pure | Value.Flag.address)currentSection->Address()null);
 812         }
 813         public override void Visit(StringConstant& sc)
 814         {
 815             if (stage == Stage.bytes)
 816             {
 817                 string s = ToUtf8(sc.value);
 818                 for (char c : s)
 819                 {
 820                     currentSection->EmitByte(cast<byte>(c));
 821                 }
 822             }
 823             else if (stage == Stage.funcInfo || stage == Stage.fileInfo)
 824             {
 825                 str = ToUtf8(sc.value);
 826             }
 827             else
 828             {
 829                 Error("string constant can appear only inside a BYTE instruction"sc.span);
 830             }
 831         }
 832         public override void Visit(OperandList& operandList)
 833         {
 834             for (const UniquePtr<Node>& node : operandList.operands)
 835             {
 836                 currentValue = Value();
 837                 node->Accept(*this);
 838             }
 839         }
 840         public override void Visit(UnaryExpression& expr)
 841         {
 842             currentValue = Value();
 843             expr.subject->Accept(*this);
 844             if (currentValue.flags == Value.Flag.undefined)
 845             {
 846                 Error("operand is undefined"expr.subject->span);
 847             }
 848             switch (expr.op)
 849             {
 850                 case Operator.unaryPlus:
 851                 {
 852                     break;
 853                 }
 854                 case Operator.unaryMinus:
 855                 {
 856                     if (currentValue.GetFlag(Value.Flag.pure))
 857                     {
 858                         currentValue.value = cast<ulong>(-currentValue.value);
 859                     }
 860                     else
 861                     {
 862                         Error("unary minus needs pure operand"expr.span);
 863                     }
 864                     break;
 865                 }
 866                 case Operator.complement:
 867                 {
 868                     if (currentValue.GetFlag(Value.Flag.pure))
 869                     {
 870                         currentValue.value = ~currentValue.value;
 871                     }
 872                     else
 873                     {
 874                         Error("complement needs pure operand"expr.span);
 875                     }
 876                     break;
 877                 }
 878                 case Operator.register:
 879                 {
 880                     if (currentValue.value >= 0u && currentValue.value <= 255u && currentValue.GetFlag(Value.Flag.pure))
 881                     {
 882                         currentValue.SetRegister();
 883                     }
 884                     else
 885                     {
 886                         Error("invalid registerize operand"expr.span);
 887                     }
 888                     break;
 889                 }
 890                 case Operator.serial:
 891                 {
 892                     Error("serial not implemented"expr.span);
 893                     break;
 894                 }
 895             }
 896         }
 897         public override void Visit(BinaryExpression& expr)
 898         {
 899             currentValue = Value();
 900             expr.left->Accept(*this);
 901             if (currentValue.flags == Value.Flag.undefined)
 902             {
 903                 Error("left operand is undefined"expr.left->span);
 904             }
 905             Value leftValue = currentValue;
 906             currentValue = Value();
 907             expr.right->Accept(*this);
 908             if (currentValue.flags == Value.Flag.undefined)
 909             {
 910                 Error("right operand is undefined"expr.right->span);
 911             }
 912             Value rightValue = currentValue;
 913             currentValue = Value();
 914             switch (expr.op)
 915             {
 916                 case Operator.multiply:
 917                 {
 918                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
 919                     {
 920                         currentValue = Value(Value.Flag.pureleftValue.value * rightValue.valuenull);
 921                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
 922                         {
 923                             currentValue.SetAddress();
 924                         }
 925                     }
 926                     else
 927                     {
 928                         Error("multiplication needs pure operands"expr.span);
 929                     }
 930                     break;
 931                 }
 932                 case Operator.divide:
 933                 {
 934                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
 935                     {
 936                         currentValue = Value(Value.Flag.pureleftValue.value / rightValue.valuenull);
 937                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
 938                         {
 939                             currentValue.SetAddress();
 940                         }
 941                     }
 942                     else
 943                     {
 944                         Error("division needs pure operands"expr.span);
 945                     }
 946                     break;
 947                 }
 948                 case Operator.modulus:
 949                 {
 950                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
 951                     {
 952                         currentValue = Value(Value.Flag.pureleftValue.value % rightValue.valuenull);
 953                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
 954                         {
 955                             currentValue.SetAddress();
 956                         }
 957                     }
 958                     else
 959                     {
 960                         Error("modulus needs pure operands"expr.span);
 961                     }
 962                     break;
 963                 }
 964                 case Operator.shiftLeft:
 965                 {
 966                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
 967                     {
 968                         currentValue = Value(Value.Flag.pureleftValue.value << rightValue.valuenull);
 969                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
 970                         {
 971                             currentValue.SetAddress();
 972                         }
 973                     }
 974                     else
 975                     {
 976                         Error("shift left needs pure operands"expr.span);
 977                     }
 978                     break;
 979                 }
 980                 case Operator.shiftRight:
 981                 {
 982                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
 983                     {
 984                         currentValue = Value(Value.Flag.pureleftValue.value >> rightValue.valuenull);
 985                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
 986                         {
 987                             currentValue.SetAddress();
 988                         }
 989                     }
 990                     else
 991                     {
 992                         Error("shift right needs pure operands"expr.span);
 993                     }
 994                     break;
 995                 }
 996                 case Operator.bitwiseAnd:
 997                 {
 998                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
 999                     {
1000                         currentValue = Value(Value.Flag.pureleftValue.value & rightValue.valuenull);
1001                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1002                         {
1003                             currentValue.SetAddress();
1004                         }
1005                     }
1006                     else
1007                     {
1008                         Error("bitwise AND needs pure operands"expr.span);
1009                     }
1010                     break;
1011                 }
1012                 case Operator.bitwiseOr:
1013                 {
1014                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
1015                     {
1016                         currentValue = Value(Value.Flag.pureleftValue.value | rightValue.valuenull);
1017                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1018                         {
1019                             currentValue.SetAddress();
1020                         }
1021                     }
1022                     else
1023                     {
1024                         Error("bitwise OR needs pure operands"expr.span);
1025                     }
1026                     break;
1027                 }
1028                 case Operator.bitwiseXor:
1029                 {
1030                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
1031                     {
1032                         currentValue = Value(Value.Flag.pureleftValue.value ^ rightValue.valuenull);
1033                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1034                         {
1035                             currentValue.SetAddress();
1036                         }
1037                     }
1038                     else
1039                     {
1040                         Error("bitwise XOR needs pure operands"expr.span);
1041                     }
1042                     break;
1043                 }
1044                 case Operator.add:
1045                 {
1046                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
1047                     {
1048                         currentValue = Value(Value.Flag.pureleftValue.value + rightValue.valuenull);
1049                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1050                         {
1051                             currentValue.SetAddress();
1052                         }
1053                     }
1054                     else if (leftValue.flags == Value.Flag.register && rightValue.GetFlag(Value.Flag.pure))
1055                     {
1056                         currentValue = Value(Value.Flag.registerleftValue.value + rightValue.valuenull);
1057                     }
1058                     else if (rightValue.flags == Value.Flag.register && leftValue.GetFlag(Value.Flag.pure))
1059                     {
1060                         currentValue = Value(Value.Flag.registerleftValue.value + rightValue.valuenull);
1061                     }
1062                     else
1063                     {
1064                         Error("add operands must both be pure or either can be a register number"expr.span);
1065                     }
1066                     break;
1067                 }
1068                 case Operator.subtract:
1069                 {
1070                     if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
1071                     {
1072                         currentValue = Value(Value.Flag.pureleftValue.value - rightValue.valuenull);
1073                         if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1074                         {
1075                             currentValue.SetAddress();
1076                         }
1077                     }
1078                     else if (leftValue.flags == Value.Flag.register)
1079                     {
1080                         if (rightValue.GetFlag(Value.Flag.pure))
1081                         {
1082                             currentValue = Value(Value.Flag.registerleftValue.value - rightValue.valuenull);
1083                         }
1084                         else if (rightValue.flags == Value.Flag.register)
1085                         {
1086                             currentValue = Value(Value.Flag.pureleftValue.value - rightValue.valuenull);
1087                         }
1088                         else
1089                         {
1090                             Error("subtract operands must both be pure or register numbers, or left can be a register number and right can be pure"expr.span);
1091                         }
1092                     }
1093                     else
1094                     {
1095                         Error("add operands must both be pure or either can be a register number"expr.span);
1096                     }
1097                     break;
1098                 }
1099                 default:
1100                 {
1101                     currentValue = Value();
1102                     break;
1103                 }
1104             }
1105             if (currentValue.flags == Value.Flag.undefined)
1106             {
1107                 Error("invalid binary expression"expr.span);
1108             }
1109             else if (currentValue.flags == Value.Flag.register)
1110             {
1111                 if (!(currentValue.value >= 0u && currentValue.value <= 255u))
1112                 {
1113                     Error("invalid binary expression register result"expr.span);
1114                 }
1115             }
1116         }
1117         public override void Visit(ParenthesizedExpression& expr)
1118         {
1119             currentValue = Value();
1120             expr.subject->Accept(*this);
1121             if (currentValue.flags == Value.Flag.undefined)
1122             {
1123                 Error("invalid parenthesized expression"expr.span);
1124             }
1125         }
1126         private void AlignAt()
1127         {
1128             ulong alignment = 1u;
1129             if (currentInstruction->opCode->value == WYDE)
1130             {
1131                 alignment = 2u;
1132                 currentAlignment = 2u;
1133             }
1134             else if (currentInstruction->opCode->value == TETRA || currentInstruction->opCode->value < 256)
1135             {
1136                 alignment = 4u;
1137                 currentAlignment = 4u;
1138             }
1139             else if (currentInstruction->opCode->value == OCTA || currentInstruction->opCode->value == STRUCT)
1140             {
1141                 alignment = 8u;
1142                 currentAlignment = 8u;
1143             }
1144             ulong at = currentSection->Address();
1145             ulong a = at & (alignment - 1u);
1146             if (a != 0u)
1147             {
1148                 ulong offset = alignment - a;
1149                 for (ulong i = 0u; i < offset; ++i;)
1150                 {
1151                     currentSection->EmitByte(0u);
1152                 }
1153             }
1154         }
1155         public Stage stage;
1156         public Value currentValue;
1157         public ObjectFile objectFile;
1158         public Section* currentSection;
1159         public Symbol* currentSymbol;
1160         public Segment currentSegment;
1161         public string str;
1162         public bool inSpec;
1163         public Stack<bool> specStack;
1164         public Symbol* currentFunctionSymbol;
1165         public Symbol* currentStructureSymbol;
1166         private Instruction* currentInstruction;
1167         private int parentSymbolIndex;
1168         private int externalLinkCommandOffset;
1169         private byte currentAlignment;
1170     }
1171 }