Trivial Solutions
                    The LoseThos 64-bit PC Operating System
File:/LT/Compiler/CmpMain.CPZ
This, and all LoseThos files, are public domain.  Do whatever you like.
God is watching; God is just; God is never out-done in generosity.  He talks!

LoseThos code compiles with the 64-bit LoseThos compiler/assembler I wrote.
Boot the LoseThos CD and you can compile it.  Not in Kansas anymore!

Click here for preliminary compiler information you need.

Project: Compiler.SPZ
U0 StreamPutS(U8 *st)
//Inserts text into the stream of
//characters being compiled.  Called
//from withing #exe{} block.
{
  LexStruct *lx=Fs->last_lex;
  StreamBlkStruct *tempe=lx->last_stream_blk;
  if (tempe!=&lx->next_stream_blk)
    tempe->body=StrAdd(tempe->body,st);
  else
    PrintFErr("No exe{} blk\n");
}

U0 StreamPrintF(U8 *src,...)
//Inserts text into the stream of
//characters being compiled.  Called
//from withing #exe{} block.
{
  U8 *buf=SPrintFJoin(NULL,src,argc,argv);
  StreamPutS(buf);
  Free(buf);
}

U8 *CmpStatement(LexStruct *lx,U64 *type)
{
  U64 *result=INVALID_PTR;
  U64 size,i,j,k;
  DbgInfo *dbg=NULL;
  IndentInfo *indent=NULL;
  IntermediateCode *tempi;
  if (type) *type=IT_I64;
  Btr(&lx->flags,Lf_OPT_TRACE_PRESENT);
  if (lx->a_depth==2)
    CbPush(lx);
  CbOutPtrsInit(lx);
  CbIcAdd(lx,EC_START,0,0); //So we can scan back an instruction
  tempi=lx->cbh.cb_last_out_ptr;
  if (!PrsStatement(lx,NULL)) {
    if (tempi!=lx->cbh.cb_last_out_ptr) {
      CbIcAdd(lx,EC_RETURN_VAL2,0,NULL);
      CbIcAdd(lx,EC_RET,0,0);
      CbIcAdd(lx,EC_END,0,0);
      if (result=CbCompile(lx,NULL,&size,&dbg,&indent,type)) {
        if (lx->flags&LF_STATIC_COMPILE) {
          j=lx->a->ip;
          k=(size+7)>>3;
          for (i=0;i<k;i++)
            AsmStoreCodeU64(lx,result[i]);
          Free(result);
          result=j;
        }
      }
    } else
      LinkedListDel(lx->cbh.cb_out_first);
  } else
    LinkedListDel(lx->cbh.cb_out_first);
  if (lx->a_depth==2)
    CbPop(lx);
  Free(dbg);
  Free(indent);
  return result;
}


ExeStruct *CmpJoin(LexStruct *lx,ClassStruct *locals,BoolI8 first_lex,BoolI8 asm_blk=FALSE,
  U8 *map_name=NULL,U8 mapfile_drv=0)
{
  AsmCtrlStruct *a,*old_a=lx->a;
  U64 i,j,l;
  ExeStruct *result;
  AsmCodeBlk *tempc;
  ExeImportExportStruct *tempe;
  BoolI8 okay=TRUE;
  SysHashTable *ht1=lx->hash_table_list,
               *ht2=lx->define_hash_table,
               *ht3=lx->glbl_hash_table,
               *ht4=lx->local_hash_table,
               *asm_hash_alias=MAllocIdentical(asm_hash);
  ClassStruct  *old_var_list=lx->local_var_list;
  result=CAlloc(sizeof(ExeStruct));
  result->parent_exe=lx->exe_struct;
  lx->exe_struct=result;

  result->next_ie=result->last_ie=&result->next_ie;
  lx->a=a=CAlloc(sizeof(AsmCtrlStruct));
  lx->a_depth++;

  a->code=CAlloc(sizeof(AsmCodeBlk));
  a->max_align=1;

  lx->local_hash_table=HashTableNew(16);
  lx->glbl_hash_table =HashTableNew(2048);

  asm_hash_alias->next=lx->local_hash_table;
  lx->local_hash_table->next=lx->glbl_hash_table;

  if (lx->flags&LF_STATIC_COMPILE)
    lx->define_hash_table=lx->glbl_hash_table;
  else
    lx->glbl_hash_table->next=Fs->hash_table;
  lx->hash_table_list =asm_hash_alias;

  lx->local_var_list=locals; //C+ local vars
  try {
    if (first_lex)
      Lex(lx);
    if (lx->flags&LF_STATIC_COMPILE) {
      while (lx->token!=TK_EOF) {
        i=CmpStatement(lx,NULL);
        if (i!=INVALID_PTR) {
          tempe=CAlloc(sizeof(ExeImportExportStruct));
          tempe->type=EIE_MAIN;
          tempe->ip=i;
          InsQue(tempe,result->last_ie);
        }
        if (asm_blk)
          break;
      }
    } else
      PrsStatement(lx,NULL);
    AsmGlblsResolve(lx,result);
  } catch {
    if (Fs->except_argc>0 && Fs->except_argv[0]==EXCEPT_COMPILER &&
      !asm_blk) {
      if (Fs->except_argc>1 && Fs->except_argv[1]) {
        "Compiler exception #%d\n",Fs->except_argv[1];
        LexPutLink(lx);
        LexPutLine(lx,lx->cur_lfn->line_start);
      }
      Fs->catch_except=TRUE;
    }
    okay=FALSE;
  }
  if (!okay) {
    if (lx->error_cnt<1)
      lx->error_cnt=1;
    lx->exe_struct=result->parent_exe;
    Free(result);
    LinkedListDel(a->code);
    result=NULL;
  } else {
    if (map_name && !cmp_do_not_write_to_dsk)
      HashRep(lx->glbl_hash_table,HTT_ALL,map_name,"-r-p",mapfile_drv);
    HashTableDel(lx->local_hash_table);
    HashTableDel(lx->glbl_hash_table);

    if (!a->num_code_U8s)
      result->code=NULL;
    else {
      if (lx->flags&LF_STATIC_COMPILE)
        result->code=MAlloc(a->num_code_U8s);
      else
        result->code=MAlloc(a->num_code_U8s,Fs->code_heap);
      result->code_U8s=a->num_code_U8s;
      tempc=a->code;
      j=0;
      l=a->num_code_U8s;
      while (tempc) {
        i=l;
        if (i>ASM_CODE_BLK_SIZE)
          i=ASM_CODE_BLK_SIZE;
        MemCpy(result->code+j,tempc->body,i);
        j+=i;
        l-=i;
        tempc=tempc->next;
      }
    }
    LinkedListDel(a->code);
    result->abss=a->abss;
    result->heap_glbls=a->heap_glbls;
    result->max_align=a->max_align;
    lx->exe_struct=result->parent_exe;
  }
  lx->hash_table_list  =ht1,
  lx->define_hash_table=ht2;
  lx->glbl_hash_table  =ht3;
  lx->local_hash_table =ht4;
  lx->local_var_list=old_var_list;
  Free(asm_hash_alias);
  Free(a);
  lx->a=old_a;
  lx->a_depth--;
  return result;
}

ExeStruct *CmpBuf(U8 *buf,U8 *map_name=NULL,
  I64 *error_cnt=NULL, I64 *warning_cnt=NULL,U8 mapfile_drv=0)
{
  LexStruct *lx;
  ExeStruct *result=NULL;
 
  if (!is_first_compiler)
    "$FG,PURPLE$**** Not First Compiler ****$FG$\n";
 
  lx=LexNew(buf,LF_DONT_FREE_BUF,NULL);
  lx->flags|=LF_STATIC_COMPILE;
  InsQue(lx,Fs->last_lex);
  result=CmpJoin(lx,NULL,TRUE,FALSE,map_name,mapfile_drv);
  if (error_cnt) *error_cnt=lx->error_cnt;
  if (warning_cnt) *warning_cnt=lx->warning_cnt;
  RemQue(lx);
  if (result)
    LexDel(lx);
  return result;
}

U0 CmpFixUpJITAsm(LexStruct *lx,ExeStruct *ex,I64 ip2)
{
  I64 i;
  U0 *ptr;
  ExeAbsAddrStruct *tempa,*tempa1;
  ExeImportExportStruct *tempe,*tempe1;
  ExportSysSymHashEntry *tempess;
  ClassStruct *tempc;
  GlblVarStruct *tempg;
  I64 *str=NULL;

  tempa=ex->abss;
  while (tempa) {
    tempa1=tempa->next;
    nobound_switch (tempa->type) {
      case EAA_ADD_U8:
        *(ex->code><(U8 *)+tempa->ip)><(U8 *)+=ip2;
        break;
      case EAA_SUB_U8:
        *(ex->code><(U8 *)+tempa->ip)><(U8 *)-=ip2;
        break;
      case EAA_ADD_U16:
        *(ex->code><(U8 *)+tempa->ip)><(U16 *)+=ip2;
        break;
      case EAA_SUB_U16:
        *(ex->code><(U8 *)+tempa->ip)><(U16 *)-=ip2;
        break;
      case EAA_ADD_U32:
        *(ex->code><(U8 *)+tempa->ip)><(U32 *)+=ip2;
        break;
      case EAA_SUB_U32:
        *(ex->code><(U8 *)+tempa->ip)><(U32 *)-=ip2;
        break;
      case EAA_ADD_U64:
        *(ex->code><(U8 *)+tempa->ip)><(U64 *)+=ip2;
        break;
      case EAA_SUB_U64:
        *(ex->code><(U8 *)+tempa->ip)><(U64 *)-=ip2;
        break;
    }
    Free(tempa);
    tempa=tempa1;
  }
  tempe=ex->next_ie;
  while (tempe!=&ex->next_ie) {
    tempe1=tempe->next;
    if (tempe->str) {
      Free(str);
      str=tempe->str;
    }
    if (tempe->type<=EIE_LIT_EXPORT) {
      tempess=CAlloc(sizeof(ExportSysSymHashEntry));
      tempess->str=str;
      str=NULL;
      tempess->type=HTT_EXPORT_SYS_SYM|HTT_LITERAL;
      if (tempe->type==EIE_LIT_EXPORT)
        tempess->val=tempe->ip;
      else
        tempess->val=tempe->ip+ip2;
      if (IsReplaceSyms)
        HashReplace(tempess,Fs->hash_table);
      else
        HashAdd(tempess,Fs->hash_table);
      SysSymImportsResolve(tempess->str);
    } else if (tempe->type<EIE_MAIN) {
      if (tempe->str && !(tempess=HashFind(str,Fs->hash_table,HTT_ALL-HTT_IMPORT_SYS_SYM)))
        "%S%s\n","ST_UNRESOLVED_REFERENCE",str;
      else {
        ptr=tempe->ip+ip2;
        if (tempess->type & HTT_FUN) {
          tempc=tempess;
          if (tempe->type & 1)
            i=tempc->executable_addr;
          else
            i=tempc->executable_addr-ex->code;
        } else if (tempess->type & HTT_GLBL_VAR) {
          tempg=tempess;
          if (tempe->type & 1)
            i=tempg->data_addr;
          else
            i=tempg->data_addr-ex->code;
        } else {
          if (tempe->type & 1)
            i=tempess->val;
          else
            i=tempess->val><(U8 *)-ex->code;
        }
        if (tempe->type<=EIE_LIT_U8)
          *ptr><(U8 *)+=i;
        else if (tempe->type<=EIE_LIT_U16)
          *ptr><(U16 *)+=i;
        else if (tempe->type<=EIE_LIT_U32)
          *ptr><(U32 *)+=i;
        else if (tempe->type<=EIE_LIT_U64)
          *ptr><(U64 *)+=i;
      }
    }
    Free(tempe);
    tempe=tempe1;
  }
  Free(str);
  if (!lx->a_depth && Bt(&lx->opts,OPTf_COMPILE_TRACE))
    Un(ex->code,ex->code_U8s,64);
  Free(ex);
}

U0 CmpFixUpStaticAsm(LexStruct *lx,ExeStruct *ex,I64 ip2)
{
  AsmCtrlStruct *a=lx->a;
  U0 *ptr;
  ExeAbsAddrStruct *tempa,*tempa1;
  ExeImportExportStruct *tempe,*tempe1;

  tempa=ex->abss;
  while (tempa) {
    tempa1=tempa->next;
    tempa->next=a->abss;
    nobound_switch (tempa->type) {
      case EAA_ADD_U8:
        *(ex->code><(U8 *)+tempa->ip)><(U8 *)+=ip2;
        break;
      case EAA_SUB_U8:
        *(ex->code><(U8 *)+tempa->ip)><(U8 *)-=ip2;
        break;
      case EAA_ADD_U16:
        *(ex->code><(U8 *)+tempa->ip)><(U16 *)+=ip2;
        break;
      case EAA_SUB_U16:
        *(ex->code><(U8 *)+tempa->ip)><(U16 *)-=ip2;
        break;
      case EAA_ADD_U32:
        *(ex->code><(U8 *)+tempa->ip)><(U32 *)+=ip2;
        break;
      case EAA_SUB_U32:
        *(ex->code><(U8 *)+tempa->ip)><(U32 *)-=ip2;
        break;
      case EAA_ADD_U64:
        *(ex->code><(U8 *)+tempa->ip)><(U64 *)+=ip2;
        break;
      case EAA_SUB_U64:
        *(ex->code><(U8 *)+tempa->ip)><(U64 *)-=ip2;
        break;
    }
    a->abss=tempa;
    tempa->ip+=ip2;
    tempa=tempa1;
  }

  tempe=ex->next_ie;
  while (tempe!=&ex->next_ie) {
    tempe1=tempe->next;
    RemQue(tempe);
    if (tempe->type<=EIE_LIT_EXPORT)
      tempe->ip+=ip2;
    else if (tempe->type<EIE_MAIN) {
      ptr=ex->code><(U8 *)+tempe->ip;
      if (tempe->type<=EIE_LIT_U8)
        *ptr><(U8 *)-=ip2;
      else if (tempe->type<=EIE_LIT_U16)
        *ptr><(U16 *)-=ip2;
      else if (tempe->type<=EIE_LIT_U32)
        *ptr><(U32 *)-=ip2;
      else if (tempe->type<=EIE_LIT_U64)
        *ptr><(U64 *)-=ip2;
      tempe->ip+=ip2;
    }
    InsQue(tempe,ex->parent_exe->last_ie);
    tempe=tempe1;
  }
  Free(ex);
}

I64 Cmp(U8 *filename,U8 *map_name=NULL,U8 *out_name=NULL,U8 mapfile_drv=0)
{ //Compile file
  U8 *fbuf=NULL,*fbuf2=NULL,*fbuf3=NULL;
  ExeStruct *ex;
  U64 size=0;
  U8 *patch_table=MAlloc(0x20000),*ptr;
  BinFileHeaderStruct *bfh;
  U64 i,cnt,error_cnt=0,warning_cnt=0,code_U8s=0;
  ExeImportExportStruct *tempe,*tempe1;
  ExeAbsAddrStruct *tempa,*tempa1;
  ExeHeapGlblRefStruct *temphgr,*temphgr1;
  ExeHeapGlblStruct *temphg,*temphg1;

  fbuf=DftExt(filename,"SPZ");
  fbuf2=MSPrintF("#include \"%s\"",fbuf);
  if (map_name)
    fbuf3=DftExt(map_name,"MPZ");
  ex=CmpBuf(fbuf2,fbuf3,&error_cnt,&warning_cnt,mapfile_drv);

  if (ex) {
    code_U8s=ex->code_U8s;
    ptr=patch_table;
    *ptr++=EIE_MODULE_ALIGNMENT; //See Load() and BinRep()
    *ptr><(U32 *)++=ex->max_align;
    *ptr++=0;
    cnt=0;
    tempa=ex->abss;
    while (tempa) {
      if (!(tempa->type&1))
        cnt++;
      tempa=tempa->next;
    }
    if (cnt) {
      *ptr++=EIE_ABS_ADDR;
      *ptr><(U32 *)++=cnt;
      *ptr++=0;
      tempa=ex->abss;
      while (tempa) {
        tempa1=tempa->next;
        if (!(tempa->type&1))
          *ptr><(U32 *)++ =tempa->ip;
        Free(tempa);
        tempa=tempa1;
      }
    }
    temphg=ex->heap_glbls;
    while (temphg) {
      temphg1=temphg->next;
      cnt=0;
      temphgr=temphg->referrences;
      while (temphgr) {
        cnt++;
        temphgr=temphgr->next;
      }
      if (cnt) {
        *ptr++=EIE_HEAP_GLBL;
        *ptr><(U32 *)++=cnt;
        if (temphg->str) {
          i=StrLen(temphg->str);
          MemCpy(ptr,temphg->str,i+1);
          Free(temphg->str);
          ptr+=i+1;
        } else
          *ptr++=0;
        *ptr><(U64 *)++=temphg->size;
        temphgr=temphg->referrences;
        while (temphgr) {
          temphgr1=temphgr->next;
          *ptr><(U32 *)++=temphgr->ip;
          Free(temphgr);
          temphgr=temphgr1;
        }
      }
      Free(temphg);
      temphg=temphg1;
    }

//Do exports first
    tempe=ex->next_ie;
    while (tempe!=&ex->next_ie) {
      tempe1=tempe->next;
      if (tempe->type<=EIE_LIT_EXPORT) {
        RemQue(tempe);
        *ptr++=tempe->type;
        *ptr><(U32 *)++=tempe->ip;
        if (tempe->str) {
          i=StrLen(tempe->str);
          MemCpy(ptr,tempe->str,i+1);
          Free(tempe->str);
          ptr+=i+1;
        } else
          *ptr++=0;
        Free(tempe);
      }
      tempe=tempe1;
    }

//Do imports second
    tempe=ex->next_ie;
    while (tempe!=&ex->next_ie) {
      tempe1=tempe->next;
      RemQue(tempe);
      *ptr++=tempe->type;
      *ptr><(U32 *)++=tempe->ip;
      if (tempe->str) {
        i=StrLen(tempe->str);
        MemCpy(ptr,tempe->str,i+1);
        Free(tempe->str);
        ptr+=i+1;
      } else
        *ptr++=0;
      Free(tempe);
      tempe=tempe1;
    }

    *ptr++=EIE_END;
    i=(ptr-patch_table+15) & -0x10;
    size=i+code_U8s+sizeof(BinFileHeaderStruct);
    bfh=MAlloc(size);
    MemCpy(bfh><(U8 *)+code_U8s+sizeof(BinFileHeaderStruct),patch_table,i);
    MemCpy(bfh><(U8 *)+sizeof(BinFileHeaderStruct),ex->code,code_U8s);
    bfh->jmp=0xEB+256*(sizeof(BinFileHeaderStruct)-2);
#assert sizeof(BinFileHeaderStruct)-2<=MAX_I8
    bfh->type=0;
    bfh->loader_patch_table_offset=code_U8s+sizeof(BinFileHeaderStruct);
    bfh->file_size=size;
    bfh->xsum=LT_XSUM;
    bfh->xsum=ArcXSum(bfh,size);
    Free(fbuf2);
    if (out_name)
      fbuf2=DftExt(out_name,"BIZ");
    else
      fbuf2=ChgExt(fbuf,"BIZ");
    if (!cmp_do_not_write_to_dsk)
      FileWrite(fbuf2,bfh,size);
    Free(bfh);
    Free(ex->code);
    Free(ex);
  }
  Free(patch_table);
  Free(fbuf);
  Free(fbuf2);
  Free(fbuf3);
  PrintF(Define("ST_ERRORS_WARNINGS"),error_cnt,warning_cnt,code_U8s,size);
  return error_cnt;
}

I64 ExePutS(U8 *buf,U8 *filename=NULL,BoolI8 just_load=FALSE)
{
  I64 result;
  BoolI8 okay=TRUE;
  LexStruct *lx;
  if (!filename)
    filename=sys_temp_filename;
  lx=LexNew(buf,LF_DONT_FREE_BUF,FileNameAbs(filename));
  if (just_load)
    lx->flags|=LF_JUST_LOAD;
  if (Fs->last_lex!=&Fs->next_lex)
    lx->opts=Fs->last_lex->opts;
  InsQue(lx,Fs->last_lex);
  try {
    Lex(lx);
    result=ExeCmdLine(lx);
  } catch {
    if (Fs->except_argc>0) {
      if (Fs->except_argv[0]==EXCEPT_COMPILER ||
      Fs->except_argv[0]==EXCEPT_BREAK) {
        Fs->catch_except=TRUE;
        okay=FALSE;
        result=0;
      }
    }
  }
  RemQue(lx);
  if (okay)
    LexDel(lx); //TODO: can crash
  return result;
}

I64 ExePrintF(U8 *fmt,...)
{
  I64 result;
  U8 *buf=SPrintFJoin(NULL,fmt,argc,argv);
  result=ExePutS(buf);
  Free(buf);
  return result;
}

I64 ExeFile(U8 *name,BoolI8 just_load=FALSE)
{
  I64 result;
  U8 *name2=DftExt(name,"CPZ");
  U8 *st=MSPrintF("#include \"%s\";",name2);
  result=ExePutS(st,name,just_load);
  Free(st);
  Free(name2);
  return result;
}

I64 ExePutS2(U8 *buf,U8 *filename=NULL,BoolI8 just_load=FALSE)
{ //with REPLACE_SYMS
  I64 result;
  BoolI8 okay=TRUE;
  LexStruct *lx;
  if (!filename)
    filename=sys_temp_filename;
  lx=LexNew(buf,LF_DONT_FREE_BUF,FileNameAbs(filename));
  if (just_load)
    lx->flags|=LF_JUST_LOAD;
  if (Fs->last_lex!=&Fs->next_lex)
    lx->opts=Fs->last_lex->opts|1<<OPTf_REPLACE_SYMS;
  InsQue(lx,Fs->last_lex);
  try {
    Lex(lx);
    result=ExeCmdLine(lx);
  } catch {
    if (Fs->except_argc>0) {
      if (Fs->except_argv[0]==EXCEPT_COMPILER ||
      Fs->except_argv[0]==EXCEPT_BREAK) {
        Fs->catch_except=TRUE;
        okay=FALSE;
        result=0;
      }
    }
  }
  RemQue(lx);
  if (okay)
    LexDel(lx); //TODO: can crash
  return result;
}

I64 ExePrintF2(U8 *fmt,...)
{ //with REPLACE_SYMS
  I64 result;
  U8 *buf=SPrintFJoin(NULL,fmt,argc,argv);
  result=ExePutS2(buf);
  Free(buf);
  return result;
}

I64 ExeFile2(U8 *name,BoolI8 just_load=FALSE)
{ //with REPLACE_SYMS
  I64 result;
  U8 *name2=DftExt(name,"CPZ");
  U8 *st=MSPrintF("#include \"%s\";",name2);
  result=ExePutS2(st,name,just_load);
  Free(st);
  Free(name2);
  return result;
}

I64 ExePutS3(U8 *buf,U8 *filename=NULL,BoolI8 just_load=FALSE)
{ //throws exceptions
  I64 result;
  LexStruct *lx;
  if (!filename)
    filename=sys_temp_filename;
  lx=LexNew(buf,LF_DONT_FREE_BUF,FileNameAbs(filename));
  if (just_load)
    lx->flags|=LF_JUST_LOAD;
  if (Fs->last_lex!=&Fs->next_lex)
    lx->opts=Fs->last_lex->opts;
  InsQue(lx,Fs->last_lex);
  Lex(lx);
  result=ExeCmdLine(lx);
  RemQue(lx);
  LexDel(lx);
  return result;
}

I64 ExePrintF3(U8 *fmt,...)
{ //throws exceptions
  I64 result;
  U8 *buf=SPrintFJoin(NULL,fmt,argc,argv);
  result=ExePutS3(buf);
  Free(buf);
  return result;
}


I64 ExeFile3(U8 *name,BoolI8 just_load=FALSE)
{ //throws exceptions
  I64 result;
  U8 *name2=DftExt(name,"CPZ");
  U8 *st=MSPrintF("#include \"%s\";",name2);
  result=ExePutS3(st,name,just_load);
  Free(st);
  Free(name2);
  return result;
}

U0 CmpInit()
{
  if (!sys_num_installed_compilers++) {
    is_first_compiler=TRUE;
    fp_prs_stream_blk=&PrsStreamBlk;
  } else
    is_first_compiler=FALSE;
  compiled_lines=0;
  compiled_funs=0;
  compiled_bytes=0;
  cmp_do_not_write_to_dsk=FALSE;
  CmpLoadDefines;
  CmpFillTables;
  MemSet(&opt_nop,0,sizeof(IntermediateCode));
  opt_nop.ic_class=sys_internal_types[IT_I64];

  opt_nop.ic_opcode=EC_NOP;
  AsmHashLoad(is_first_compiler);
  UnasmHashLoad;
}

CmpInit;
Historical capture: 2012-03-02. Home | Power on LoseThos | Sources and changes