Team Ai
Datasetpublic

hschumann2/TempleOS-Source-Code

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes847downloads
MiniCompiler.txt248 linesDownload Raw Back to Lectures
1 2/*3-] Main Compiler4  The mini compiler is like the main compiler, except the main compiler's5  lexical analyser removes comments and does preprocessing.  Lex(),Echo(ON).6 7  The main compiler generates Intermediate Code at the parser stage.  See8  PrsExpression(), PrsStmt().9 10  The main compiler optimizes   See Intermediate Code Attributes,11  Combining Consts, Choosing Reg Vars.  Use PassTrace() to see the optimization12  stages.13 14  The main compiler makes machine code in the back end.  See IC Struct,15  COCCompile and OptPass789A(), BackEnd.  Set Trace(ON) to see the output of the16  backend.17 18-] Mini Compiler19  For this mini compiler, some things you should know about 64-bit asm:20 21  * Putting a 0x48, known as the REX byte, in front of an inst makes it 64-bit22  size.23 24  * "PUSH EAX", "POP EAX" and "XOR EAX,EAX" will behave as 64-bit even without25  REX because the stk is always 64 bit and because the XOR clears the upper26  32-bits.27 28  It is okay in TempleOS to change RAX, RBX, RCX, RDX, R8 and R9 without29  restoring them to their original values.30*/31 32#define TK_EOF          033#define TK_NUM          134#define TK_OP           235#define TK_LEFT         336#define TK_RIGHT        437 38#define OP_MUL          139#define OP_DIV          240#define OP_ADD          341#define OP_SUB          442 43I64 Lex(U8 **_src,I64 *num)44{//See Lex().45  U8 *src=*_src;46  I64 i;47  while (TRUE) {48    switch (*src) {49      case 0:50      case ';':51        *_src=src;52        return TK_EOF;53      case CH_SPACE:54      case '\r':55      case '\n':56        src++;57        break;58      case '0'...'9':59        i=0;60        do {61          i=i*10+*src-'0';62          src++;63        } while ('0'<=*src<='9');64        *num=i;65        *_src=src;66        return TK_NUM;67      case '*':68        *num=OP_MUL;69        *_src=src+1;70        return TK_OP;71      case '/':72        *num=OP_DIV;73        *_src=src+1;74        return TK_OP;75      case '+':76        *num=OP_ADD;77        *_src=src+1;78        return TK_OP;79      case '-':80        *num=OP_SUB;81        *_src=src+1;82        return TK_OP;83      case '(':84        *_src=src+1;85        return TK_LEFT;86      case ')':87        *_src=src+1;88        return TK_RIGHT;89      default:90        throw;91    }92  }93}94 95#define PREC_EOF        096#define PREC_TERM       197#define PREC_MUL        298#define PREC_ADD        399#define PREC_PAREN      4100 101extern I64 Parse(U8 **_src,U8 **_dst);102 103U0 PrsTerm(U8 **_src,U8 **_dst,I64 prec)104{//See PrsExpression().105  I64 i;106  U8 *src2;107  U8 *dst2;108  if (Parse(_src,_dst)==PREC_TERM) {109    src2=*_src;110    dst2=*_dst;111    while (TRUE) {112//This is inefficient.  The main compiler doesn't back-up like this.113      i=Parse(&src2,&dst2);114      if (PREC_MUL<=i<prec) {115        *_src=src2;116        *_dst=dst2;117      } else118        break;119    }120  } else121    throw;122}123 124I64 Parse(U8 **_src,U8 **_dst)125{//See PrsExpression().126//See Opcode Fmts for details on asm insts.127  I64 i;128  U8 *dst=*_dst;129  switch (Lex(_src,&i)) {130    case TK_EOF:131      *dst++=0x58; //POP RAX132      *dst++=0xC3; //RET133      *_dst=dst;134      return PREC_EOF;135    case TK_NUM:136      *dst++=0x48; //REX137      *dst++=0xB8; //MOV RAX,immediate num138      *dst(I64 *)++=i;139 140      *dst++=0x50; //PUSH RAX141      *_dst=dst;142      return PREC_TERM;143    case TK_LEFT:144      PrsTerm(_src,_dst,PREC_PAREN);145      if (Parse(_src,_dst)!=PREC_PAREN)146        throw;147      return PREC_TERM;148    case TK_RIGHT:149      return PREC_PAREN;150    case TK_OP:151      switch (i) {152        case OP_MUL:153          PrsTerm(_src,&dst,PREC_MUL);154          *dst++=0x5A; //POP RDX155          *dst++=0x58; //POP RAX156 157          *dst++=0x48; //REX158          *dst++=0x0F;159          *dst++=0xAF; //IMUL RAX,RDX160          *dst++=0xC2;161 162          *dst++=0x50; //PUSH RAX163          *_dst=dst;164          return PREC_MUL;165        case OP_DIV:166          PrsTerm(_src,&dst,PREC_MUL);167          *dst++=0x5B; //POP RBX168          *dst++=0x58; //POP RAX169 170          *dst++=0x33; //XOR RDX,RDX171          *dst++=0xD2;172 173          *dst++=0x48; //REX174          *dst++=0xF7; //IDIV RBX175          *dst++=0xFB;176 177          *dst++=0x50; //PUSH RAX178          *_dst=dst;179          return PREC_MUL;180        case OP_ADD:181          PrsTerm(_src,&dst,PREC_ADD);182          *dst++=0x5A; //POP RDX183          *dst++=0x58; //POP RAX184 185          *dst++=0x48; //REX186          *dst++=0x03; //ADD RAX,RDX187          *dst++=0xC2;188 189          *dst++=0x50; //PUSH RAX190          *_dst=dst;191          return PREC_ADD;192        case OP_SUB:193          PrsTerm(_src,&dst,PREC_ADD);194          *dst++=0x5A; //POP RDX195          *dst++=0x58; //POP RAX196 197          *dst++=0x48; //REX198          *dst++=0x2B; //SUB RAX,RDX199          *dst++=0xC2;200 201          *dst++=0x50; //PUSH RAX202          *_dst=dst;203          return PREC_ADD;204      }205  }206}207 208U0 Main()209{210  U8 *src,*src2,*code,*dst;211 212  //Fixed size, no buffer overrun check.213  //You can make it fancier if you like.214  code=MAlloc(512,Fs->code_heap);215 216  while (TRUE) {217    "This will compile an expression\n"218          "consisting of ints, parentheses\n"219          "and the operators +,-,* and /.\n";220    src=GetStr;221    if (*src) {222      src2=src;223      dst=code;224      try {225        PrsTerm(&src2,&dst,PREC_PAREN);226        if (Parse(&src2,&dst)!=PREC_EOF)227          throw;228        "$RED$This code is not efficient, but the compiler is simple.$FG$\n";229        Un(code,dst-code); //Unassemble the code we created.230//Call() is a function.  See _CALL::231        //See also CallInd().  See _CALL_IND::232        "$LTBLUE$Answer:%d$FG$\n",Call(code);233      } catch {234        "$RED$Error$FG$\n";235        PutExcept;236      }237      Free(src);238    } else {239      Free(src);240      break;241    }242  }243  Free(code);244}245 246Main;247 248