Files
TempleOS-Rijn/Compiler/AsmResolve.HC
T
2018-09-08 21:47:50 +02:00

217 lines
6.2 KiB
HolyC

U0 AsmResolve(CCmpCtrl *cc,CAsmUnresolvedRef *tempu,U8 *label,Bool undefined)
{
CAOTImportExport *tempie;
CAsmUndefHash *tempauh;
I64 r=Call(tempu->machine_code);
if (undefined) {
tempauh=tempu->asm_undef_hash;
while (tempauh) {
if (tempauh->hash->type & HTF_UNRESOLVED) {
tempie=CAlloc(sizeof(CAOTImportExport));
tempie->next=tempauh->hash->ie_lst;
tempauh->hash->ie_lst=tempie;
tempie->ip=tempu->ip;
tempie->aot=cc->aot;
tempie->type=tempu->type;
}
tempauh=tempauh->next; //Technically, more than one won't work.
}
} else if (!(tempu->type&IEF_IMM_NOT_REL)) {
r-=tempu->rel_ip;
if (tempu->type==IET_REL_I8 && !(MIN_I8<=r<=MAX_I8) ||
tempu->type==IET_REL_I16 && !(MIN_I16<=r<=MAX_I16)) {
PrintErr("Branch out of range at line:%04d %s\n",
tempu->line_num,label);
LexExcept(cc);
}
if (tempu->U8_avail && tempu->type>IET_IMM_U8 && -124<=r<=123)
PrintWarn("could use I8 displacement at line:%04d %s %s\n",
tempu->line_num,cc->aotc->last_label,label);
}
AOTStoreCodeU8At(cc,tempu->ip,r.u8[0]);
if (tempu->type>=IET_REL_I16) {
AOTStoreCodeU8At(cc,tempu->ip+1,r.u8[1]);
if (tempu->type>=IET_REL_I32) {
AOTStoreCodeU8At(cc,tempu->ip+2,r.u8[2],r.u8[3]);
if (tempu->type>=IET_REL_I64)
AOTStoreCodeU8At(cc,tempu->ip+4,r.u8[4],r.u8[5],r.u8[6],r.u8[7]);
}
}
}
U0 AOTLocalsResolve(CCmpCtrl *cc)
{
CAOTCtrl *aotc=cc->aotc;
CAsmUnresolvedRef *tempu=aotc->local_unresolved,*tempu1;
CAsmUndefHash *tempauh;
Bool undefined;
U8 *label=NULL;
while (tempu) {
undefined=FALSE;
tempu1=tempu->next;
tempauh=tempu->asm_undef_hash;
while (tempauh) {
if (tempauh->hash->type & HTF_UNRESOLVED) {
PrintErr("Undefined sym at line:%04d %s %s\n",
tempu->line_num,aotc->last_label,tempauh->hash->str);
LexExcept(cc);
}
label=tempauh->hash->str;
tempauh=tempauh->next;
}
if (!undefined)
AsmResolve(cc,tempu,label,FALSE);
Free(tempu->machine_code);
LinkedLstDel(tempu->asm_undef_hash);
Free(tempu);
tempu=tempu1;
}
HashTableDel(cc->htc.local_hash_table);
cc->htc.hash_table_lst=cc->htc.local_hash_table=HashTableNew(16);
cc->htc.local_hash_table->next=cc->htc.glbl_hash_table;
aotc->local_unresolved=NULL;
}
U0 AOTGlblsResolve(CCmpCtrl *cc,CAOT *tempaot)
{
CAOTCtrl *aotc=cc->aotc;
CHashFun *tempf;
CAsmUnresolvedRef *tempu=aotc->glbl_unresolved,*tempu1;
I64 i,j;
CAOTImportExport *tempie,*tempie1;
CAsmUndefHash *tempauh;
CHashExport *tempex;
U8 *label;
Bool undefined;
CExternUsage *tempeu,*tempeu8;
while (tempu) {
label=NULL;
undefined=FALSE;
tempu1=tempu->next;
tempauh=tempu->asm_undef_hash;
while (tempauh) {
if (tempauh->hash->type & HTF_UNRESOLVED) {
tempex=tempauh->hash;
if (tempex->type & HTT_EXPORT_SYS_SYM&& tempex->type & HTF_UNRESOLVED &&
!(tempex->type & HTF_IMPORT) &&
(tempf=HashFind(tempex->str,cc->htc.hash_table_lst,HTT_FUN)) &&
!Bt(&tempf->flags,Cf_EXTERN)) {
tempex->val=tempf->exe_addr;
tempex->type&=~HTF_UNRESOLVED;
label=tempauh->hash->str;
} else {
if (!(tempex->type & HTF_IMPORT)) {
if (cc->htc.local_var_lst) {
tempex->type|=HTF_GOTO_LABEL;
tempex->use_cnt++;
} else {
PrintErr("Undefined sym at line:%04d %s\n",
tempu->line_num,tempex->str);
LexExcept(cc);
}
} else if (undefined) {
PrintErr("Two imports in same expression "
"not allowed at line:%04d %s\n",
tempu->line_num,tempex->str);
LexExcept(cc);
}
undefined=TRUE;
}
} else
label=tempauh->hash->str;
tempauh=tempauh->next;
}
AsmResolve(cc,tempu,label,undefined);
Free(tempu->machine_code);
LinkedLstDel(tempu->asm_undef_hash);
Free(tempu);
tempu=tempu1;
}
for (i=0;i<=cc->htc.glbl_hash_table->mask;i++) {
tempex=cc->htc.glbl_hash_table->body[i];
while (tempex) {
if (tempex->type & (HTF_IMPORT|HTF_GOTO_LABEL)) {
if (tempex->use_cnt && (tempie=tempex->ie_lst)) {
if (tempex->type&HTF_GOTO_LABEL)
tempie->flags|=IEF_GOTO_LABEL;
if (tempex->import_name)
tempie->str=StrNew(tempex->import_name);
else
tempie->str=StrNew(tempex->str);
do {
tempie1=tempie->next;
QueIns(tempie,tempaot->last_ie);
} while (tempie=tempie1);
tempex->ie_lst=NULL;
}
} else if (tempex->type & (HTF_EXPORT|HTF_RESOLVE)) {
if (tempex->type & HTF_UNRESOLVED) {
PrintErr("Undefined sym at %s\n",tempex->str);
LexExcept(cc);
}
if (tempex->type & HTF_RESOLVE) {
tempf=tempex;
tempeu=tempf->ext_lst;
while (tempeu) {
tempeu8=tempeu->next;
j=tempf->exe_addr-(tempeu->ip+4);
AOTStoreCodeU8At(cc,tempeu->ip,j.u8[0],j.u8[1],j.u8[2],j.u8[3]);
Free(tempeu);
tempeu=tempeu8;
}
}
if (tempex->type & HTF_EXPORT) {
tempie=CAlloc(sizeof(CAOTImportExport));
tempie->type=IET_REL32_EXPORT;
if (tempex->type & HTT_FUN)
tempie->ip=tempf->exe_addr;
else if (tempex->type & HTT_GLBL_VAR)
tempie->ip=tempex(CHashGlblVar *)->data_addr_ip;
else
tempie->ip=tempex->val;
tempie->aot=cc->aot;
if (tempex->type & HTF_IMM)
tempie->type++;
tempie->str=StrNew(tempex->str);
tempie->src_link=StrNew(tempex->src_link);
QueIns(tempie,tempaot->last_ie);
}
}
tempex=tempex->next;
}
}
}
U0 AsmUnresolvedAdd(CCmpCtrl *cc,U8 *machine_code,I64 type,I64 ip,I64 rel_ip,
CAsmUndefHash *local_asm_undef_hash,CAsmUndefHash *glbl_asm_undef_hash,
I64 line_num,Bool U8_avail)
{
CAsmUnresolvedRef *tempu=MAlloc(sizeof(CAsmUnresolvedRef));
tempu->machine_code=machine_code;
tempu->type=type;
tempu->ip=ip;
tempu->rel_ip=rel_ip;
tempu->aot=cc->aot;
tempu->imm_flag=FALSE;
tempu->line_num=line_num;
tempu->U8_avail=U8_avail;
tempu->str=NULL;
if (local_asm_undef_hash) {
tempu->asm_undef_hash=local_asm_undef_hash;
tempu->next=cc->aotc->local_unresolved;
cc->aotc->local_unresolved=tempu;
} else {
tempu->asm_undef_hash=glbl_asm_undef_hash;
tempu->next=cc->aotc->glbl_unresolved;
cc->aotc->glbl_unresolved=tempu;
if (glbl_asm_undef_hash->hash->type & HTF_IMPORT) {
tempu->str=StrNew(glbl_asm_undef_hash->hash->str);
if (glbl_asm_undef_hash->hash->type & HTF_IMM)
tempu->imm_flag=TRUE;
}
}
}