mirror of
https://github.com/dschmenk/PLASMA.git
synced 2025-08-08 09:25:19 +00:00
PLASMA PLASMA compiler roughly up-to-date with PLASMA C compiler
This commit is contained in:
@@ -29,64 +29,52 @@ def idmatch(nameptr, len, idptr, idcnt)
|
|||||||
while idcnt
|
while idcnt
|
||||||
if len == idptr->idname
|
if len == idptr->idname
|
||||||
for i = 1 to len
|
for i = 1 to len
|
||||||
if nameptr->[i - 1] <> idptr->idname.[i]
|
if nameptr->[i - 1] <> idptr->idname.[i]; break; fin
|
||||||
break
|
|
||||||
fin
|
|
||||||
next
|
next
|
||||||
if i > len
|
if i > len; return idptr; fin
|
||||||
return idptr
|
|
||||||
fin
|
|
||||||
fin
|
fin
|
||||||
idptr = idptr + idptr->idname + idrecsz
|
idptr = idptr + idptr->idname + t_id
|
||||||
idcnt--
|
idcnt--
|
||||||
loop
|
loop
|
||||||
return 0
|
return NULL
|
||||||
end
|
end
|
||||||
def id_lookup(nameptr, len)
|
def id_lookup(nameptr, len)
|
||||||
word idptr
|
word idptr
|
||||||
|
|
||||||
idptr = idmatch(nameptr, len, idlocal_tbl, locals)
|
idptr = idmatch(nameptr, len, idlocal_tbl, locals)
|
||||||
if idptr
|
if not idptr
|
||||||
return idptr
|
idptr = idmatch(nameptr, len, idglobal_tbl, globals)
|
||||||
|
if not idptr; exit_err(@undecl_id); fin
|
||||||
fin
|
fin
|
||||||
idptr = idmatch(nameptr, len, idglobal_tbl, globals)
|
return idptr
|
||||||
if idptr
|
|
||||||
return idptr
|
|
||||||
fin
|
|
||||||
exit_err(@undecl_id)
|
|
||||||
return 0
|
|
||||||
end
|
end
|
||||||
def idglobal_lookup(nameptr, len)
|
def idglobal_lookup(nameptr, len)
|
||||||
return idmatch(nameptr, len, idglobal_tbl, globals)
|
word idptr
|
||||||
|
idptr idmatch(nameptr, len, idglobal_tbl, globals)
|
||||||
|
if not idptr; exit_err(@undecl_id); fin
|
||||||
|
return idptr
|
||||||
end
|
end
|
||||||
def idlocal_add(namestr, len, type, size)
|
def idlocal_add(namestr, len, type, size)
|
||||||
if idmatch(namestr, len, @idlocal_tbl, locals); return exit_err(@dup_id); fin
|
if idmatch(namestr, len, @idlocal_tbl, locals); exit_err(@dup_id); fin
|
||||||
lastlocal=>idval = framesize
|
lastlocal=>idval = framesize
|
||||||
lastlocal->idtype = type | LOCAL_TYPE
|
lastlocal->idtype = type | LOCAL_TYPE
|
||||||
nametostr(namestr, len, lastlocal + idname)
|
nametostr(namestr, len, lastlocal + idname)
|
||||||
locals++
|
locals++
|
||||||
lastlocal = lastlocal + idrecsz + len
|
lastlocal = lastlocal + idrecsz + len
|
||||||
if lastlocal > idlocal_tbl + idlocal_tblsz
|
if lastlocal > idlocal_tbl + idlocal_tblsz; exit_err(@local_sym_overflw); fin
|
||||||
exit_err(@local_sym_overflw)
|
|
||||||
fin
|
|
||||||
framesize = framesize + size
|
framesize = framesize + size
|
||||||
if framesize > 255
|
if framesize > 255; exit_err(@local_overflw); fin
|
||||||
return exit_err(@local_overflw)
|
|
||||||
fin
|
|
||||||
return TRUE
|
return TRUE
|
||||||
end
|
end
|
||||||
def iddata_add(namestr, len, type, size)
|
def iddata_add(namestr, len, type, size)
|
||||||
if idmatch(namestr, len, idglobal_tbl, globals); return exit_err(@dup_id); fin
|
if idmatch(namestr, len, idglobal_tbl, globals); exit_err(@dup_id); fin
|
||||||
lastglobal=>idval = datasize
|
lastglobal=>idval = datasize
|
||||||
lastglobal->idtype = type
|
lastglobal->idtype = type
|
||||||
nametostr(namestr, len, lastglobal + idname)
|
nametostr(namestr, len, lastglobal + idname)
|
||||||
emit_iddata(datasize, size, lastglobal + idname)
|
emit_iddata(datasize, size, lastglobal + idname)
|
||||||
globals++
|
globals++
|
||||||
lastglobal = lastglobal + idrecsz + len
|
lastglobal = lastglobal + idrecsz + len
|
||||||
if lastglobal > idglobal_tbl + idglobal_tblsz
|
if lastglobal > idglobal_tbl + idglobal_tblsz; exit_err((@global_sym_overflw); fin
|
||||||
prstr(@global_sym_overflw)
|
|
||||||
exit
|
|
||||||
fin
|
|
||||||
datasize = datasize + size
|
datasize = datasize + size
|
||||||
return TRUE
|
return TRUE
|
||||||
end
|
end
|
||||||
@@ -99,7 +87,7 @@ def iddata_size(type, varsize, initsize)#0
|
|||||||
fin
|
fin
|
||||||
end
|
end
|
||||||
def idglobal_add(namestr, len, type, value)
|
def idglobal_add(namestr, len, type, value)
|
||||||
if idmatch(namestr, len, idglobal_tbl, globals); return exit_err(@dup_id); fin
|
if idmatch(namestr, len, idglobal_tbl, globals); exit_err(@dup_id); fin
|
||||||
lastglobal=>idval = value
|
lastglobal=>idval = value
|
||||||
lastglobal->idtype = type
|
lastglobal->idtype = type
|
||||||
nametostr(namestr, len, lastglobal + idname)
|
nametostr(namestr, len, lastglobal + idname)
|
||||||
@@ -150,7 +138,7 @@ end
|
|||||||
// Flags are:
|
// Flags are:
|
||||||
//
|
//
|
||||||
def ctag_new
|
def ctag_new
|
||||||
if codetag >= ctag_max; return exit_err(@ctag_full); fin
|
if codetag >= ctag_max; exit_err(@ctag_full); fin
|
||||||
codetag = codetag + 1
|
codetag = codetag + 1
|
||||||
ctag_tbl:[codetag] = 0 // Unresolved, nothing to update yet
|
ctag_tbl:[codetag] = 0 // Unresolved, nothing to update yet
|
||||||
return codetag | IS_CTAG
|
return codetag | IS_CTAG
|
||||||
@@ -159,7 +147,7 @@ def ctag_resolve(ctag)#0
|
|||||||
word updtptr, nextptr
|
word updtptr, nextptr
|
||||||
|
|
||||||
ctag = ctag & MASK_CTAG // Better be a ctag!
|
ctag = ctag & MASK_CTAG // Better be a ctag!
|
||||||
if ctag_tbl:[ctag] & IS_RESOLVED;exit_err(@dup_id); return; fin
|
if ctag_tbl:[ctag] & IS_RESOLVED;exit_err(@dup_id); fin
|
||||||
updtptr = ctag_tbl:[ctag] & MASK_CTAG
|
updtptr = ctag_tbl:[ctag] & MASK_CTAG
|
||||||
while updtptr
|
while updtptr
|
||||||
//
|
//
|
||||||
@@ -392,11 +380,10 @@ end
|
|||||||
def emit_indexword#0
|
def emit_indexword#0
|
||||||
emit_op($1E)
|
emit_op($1E)
|
||||||
end
|
end
|
||||||
def emit_unaryop(op)
|
def emit_unaryop(op)#0
|
||||||
when op
|
when op
|
||||||
is NEG_TKN
|
is NEG_TKN
|
||||||
emit_op($10); break
|
emit_op($10); break
|
||||||
is ALT_COMP_TKN
|
|
||||||
is COMP_TKN
|
is COMP_TKN
|
||||||
emit_op($12); break
|
emit_op($12); break
|
||||||
is LOGIC_NOT_TKN
|
is LOGIC_NOT_TKN
|
||||||
@@ -410,60 +397,21 @@ def emit_unaryop(op)
|
|||||||
is WPTR_TKN
|
is WPTR_TKN
|
||||||
emit_op($62); break
|
emit_op($62); break
|
||||||
otherwise
|
otherwise
|
||||||
return FALSE
|
exit_err("Invalid unary operation")
|
||||||
wend
|
wend
|
||||||
return TRUE
|
|
||||||
end
|
end
|
||||||
def emit_binaryop(op)
|
def emit_binaryop(op)#0
|
||||||
when op
|
when op
|
||||||
is MUL_TKN
|
is MUL_TKN
|
||||||
//
|
emit_op($06); break
|
||||||
// Replace MUL 2 with SHL 1
|
|
||||||
//
|
|
||||||
if lastop == $2A and ^(codeptr - 1) == 2 // CB 2
|
|
||||||
codeptr = codeptr - 1
|
|
||||||
emit_byte(1) // CB 1
|
|
||||||
emit_op($1A) // SHL
|
|
||||||
else
|
|
||||||
emit_op($06)
|
|
||||||
fin
|
|
||||||
break
|
|
||||||
is DIV_TKN
|
is DIV_TKN
|
||||||
//
|
emit_op($08); break
|
||||||
// Replace DIV 2 with SHR 1
|
|
||||||
//
|
|
||||||
if lastop == $2A and ^(codeptr - 1) == 2 // CB 2
|
|
||||||
codeptr = codeptr - 1
|
|
||||||
emit_byte(1) // CB 1
|
|
||||||
emit_op($1C) // SHR
|
|
||||||
else
|
|
||||||
emit_op($08)
|
|
||||||
fin
|
|
||||||
break
|
|
||||||
is MOD_TKN
|
is MOD_TKN
|
||||||
emit_op($0A); break
|
emit_op($0A); break
|
||||||
is ADD_TKN
|
is ADD_TKN
|
||||||
//
|
emit_op($02); break
|
||||||
// Replace ADD 1 with INCR
|
|
||||||
//
|
|
||||||
if lastop == $2A and ^(codeptr - 1) == 1 // CB 1
|
|
||||||
codeptr = codeptr - 2
|
|
||||||
emit_op($0C) // INC_OP
|
|
||||||
else
|
|
||||||
emit_op($02)
|
|
||||||
fin
|
|
||||||
break
|
|
||||||
is SUB_TKN
|
is SUB_TKN
|
||||||
//
|
emit_op($04); break
|
||||||
// Replace SUB 1 with DECR
|
|
||||||
//
|
|
||||||
if lastop == $2A and ^(codeptr - 1) == 1 // CB 1
|
|
||||||
codeptr = codeptr - 2
|
|
||||||
emit_op($0E) // DEC_OP
|
|
||||||
else
|
|
||||||
emit_op($04)
|
|
||||||
fin
|
|
||||||
break
|
|
||||||
is SHL_TKN
|
is SHL_TKN
|
||||||
emit_op($1A); break
|
emit_op($1A); break
|
||||||
is SHR_TKN
|
is SHR_TKN
|
||||||
@@ -491,9 +439,8 @@ def emit_binaryop(op)
|
|||||||
is LOGIC_AND_TKN
|
is LOGIC_AND_TKN
|
||||||
emit_op($24); break
|
emit_op($24); break
|
||||||
otherwise
|
otherwise
|
||||||
return FALSE
|
exit_err("Invalid operation")
|
||||||
wend
|
wend
|
||||||
return TRUE
|
|
||||||
end
|
end
|
||||||
def emit_brtru(tag)#0
|
def emit_brtru(tag)#0
|
||||||
emit_op($4E)
|
emit_op($4E)
|
||||||
@@ -540,7 +487,7 @@ def emit_enter(cparams)#0
|
|||||||
fin
|
fin
|
||||||
end
|
end
|
||||||
//
|
//
|
||||||
//New/release sequence ops
|
// New/release sequence ops
|
||||||
//
|
//
|
||||||
def new_op
|
def new_op
|
||||||
word op
|
word op
|
||||||
@@ -573,7 +520,448 @@ def release_seq(seq)#0
|
|||||||
loop
|
loop
|
||||||
end
|
end
|
||||||
//
|
//
|
||||||
//Generate a sequence of code
|
// Replace all but the first of a series of identical load opcodes by DUP. This
|
||||||
|
// doesn't reduce the number of opcodes but does reduce their size in bytes.
|
||||||
|
// This is only called on the second optimisation pass because the DUP opcodes
|
||||||
|
// may inhibit other peephole optimisations which are more valuable.
|
||||||
|
//
|
||||||
|
def try_dupify(op)
|
||||||
|
byte crunched
|
||||||
|
word opnext
|
||||||
|
|
||||||
|
crunched = 0
|
||||||
|
opnext = op=>nextop
|
||||||
|
while opnext
|
||||||
|
if op->code <> opn->code
|
||||||
|
return crunched
|
||||||
|
when op->code
|
||||||
|
is CONST_CODE
|
||||||
|
if op->val <> opnext->val; return crunched; fin
|
||||||
|
break
|
||||||
|
is LADDR_CODE
|
||||||
|
is LLB_CODE
|
||||||
|
is LLW_CODE
|
||||||
|
if op=>offsz <> opnext=>offsz; return crunched; fin
|
||||||
|
break
|
||||||
|
is GADDR_CODE
|
||||||
|
is LAB_CODE
|
||||||
|
is LAW_CODE
|
||||||
|
if (op=>tag <> opnext=>tag) or (op=>offsz <> opnext=>offsz) or (op->type <> opnext->type); return crunched; fin
|
||||||
|
break
|
||||||
|
otherwise
|
||||||
|
return crunched
|
||||||
|
wend
|
||||||
|
opnext->code = DUP_CODE
|
||||||
|
opnext = opnext=>nextop
|
||||||
|
crunched = 1
|
||||||
|
loop
|
||||||
|
return crunched
|
||||||
|
end
|
||||||
|
//
|
||||||
|
// Crunch sequence (peephole optimize)
|
||||||
|
//
|
||||||
|
def crunch_seq(seq, pass)
|
||||||
|
word opnext opnextnext opprev, op
|
||||||
|
byte crunched, freeops, shiftcnt
|
||||||
|
opprev = NULL
|
||||||
|
op = *seq
|
||||||
|
opnext = op=>nextop
|
||||||
|
crunched = FALSE
|
||||||
|
freeops = 0
|
||||||
|
while op and opnext
|
||||||
|
when op->code
|
||||||
|
is CONST_CODE
|
||||||
|
if op=>val == 1
|
||||||
|
{
|
||||||
|
if opnext->code == BINARY_CODE|ADD_TOKEN
|
||||||
|
op->code = INC_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
fin
|
||||||
|
if opnext->code == BINARY_CODE|SUB_TOKEN
|
||||||
|
op->code = DEC_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
fin
|
||||||
|
if opnext->code == BINARY_CODE|SHL_TOKEN
|
||||||
|
op->code = DUP_CODE
|
||||||
|
opnext->code = BINARY_CODE|ADD_TOKEN
|
||||||
|
crunched = 1
|
||||||
|
break
|
||||||
|
fin
|
||||||
|
fin
|
||||||
|
when opnext->code
|
||||||
|
is NEG_CODE
|
||||||
|
op=>val = -(op=>val)
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is COMP_CODE
|
||||||
|
op->val = ~(op=>val)
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is LOGIC_NOT_CODE
|
||||||
|
op=>val = op=>val ?? FALSE :: TRUE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is UNARY_CODE|BPTR_TOKEN
|
||||||
|
is LB_CODE
|
||||||
|
op=>offsz = op=>val
|
||||||
|
op->code = LAB_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is UNARY_CODE|WPTR_TOKEN
|
||||||
|
is LW_CODE
|
||||||
|
op=>offsz = op=>val
|
||||||
|
op->code = LAW_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is SB_CODE
|
||||||
|
op=>offsz = op=>val
|
||||||
|
op->code = SAB_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is SW_CODE
|
||||||
|
op=>offsz = op=>val
|
||||||
|
op->code = SAW_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is BRFALSE_CODE
|
||||||
|
if op=>val
|
||||||
|
freeops = -2 // Remove constant and never taken branch
|
||||||
|
else
|
||||||
|
op->code = BRNCH_CODE // Always taken branch
|
||||||
|
op=>tag = opnext=>tag
|
||||||
|
freeops = 1
|
||||||
|
fin
|
||||||
|
break
|
||||||
|
is BRTRUE_CODE
|
||||||
|
if not op=>val
|
||||||
|
freeops = -2 // Remove constant never taken branch
|
||||||
|
else
|
||||||
|
op->code = BRNCH_CODE // Always taken branch
|
||||||
|
op=>tag = opnext=>tag
|
||||||
|
freeops = 1
|
||||||
|
fin
|
||||||
|
break
|
||||||
|
is NE_CODE
|
||||||
|
if not op=>val
|
||||||
|
freeops = -2 // Remove ZERO:ISNE
|
||||||
|
fin
|
||||||
|
break
|
||||||
|
is EQ_CODE
|
||||||
|
if not op=>val
|
||||||
|
op->code = LOGIC_NOT_CODE
|
||||||
|
freeops = 1
|
||||||
|
fin
|
||||||
|
break
|
||||||
|
is CONST_CODE // Collapse constant operation
|
||||||
|
opnextnext = opnext->nextop
|
||||||
|
if opnextnext
|
||||||
|
when opnextnext->code
|
||||||
|
is BINARY_CODE|MUL_TOKEN
|
||||||
|
op=>val = op=>val * opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|DIV_TOKEN
|
||||||
|
op=>val = op=>val / opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|MOD_TOKEN
|
||||||
|
op=>val = op=>val % opnext=>val
|
||||||
|
freeop = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|ADD_TOKEN
|
||||||
|
op=>val = op=>val + opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|SUB_TOKEN
|
||||||
|
op=>val = op=>val - opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|SHL_TOKEN
|
||||||
|
op=>val = op=>val << opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|SHR_TOKEN
|
||||||
|
op=>val = op=>val >> opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|AND_TOKEN
|
||||||
|
op=>val = op=>val & opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|OR_TOKEN
|
||||||
|
op=>val = op=>val | opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|EOR_TOKEN
|
||||||
|
op=>val = op=>val ^ opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|EQ_TOKEN
|
||||||
|
op=>val = op=>val == opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|NE_TOKEN
|
||||||
|
op=>val = op=>val <> opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|GE_TOKEN
|
||||||
|
op=>val = op=>val >= opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|LT_TOKEN
|
||||||
|
op=>val = op=>val < opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|GT_TOKEN
|
||||||
|
op=>val = op=>val > opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|LE_TOKEN
|
||||||
|
op=>val = op=>val <= opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|LOGIC_OR_TOKEN
|
||||||
|
op=>val = op=>val or opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is BINARY_CODE|LOGIC_AND_TOKEN
|
||||||
|
op=>val = op=>val and opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
wend // End of collapse constant operation
|
||||||
|
if pass > 0 and freeops == 0 and op=>val
|
||||||
|
crunched = try_dupify(op)
|
||||||
|
fin
|
||||||
|
break // CONST_CODE
|
||||||
|
is BINARY_CODE|MUL_TOKEN
|
||||||
|
for shiftcnt = 0 to 15
|
||||||
|
if op=>val == 1 << shiftcnt
|
||||||
|
op=>val = shiftcnt
|
||||||
|
opnext->code = BINARY_CODE|SHL_TOKEN
|
||||||
|
break
|
||||||
|
fin
|
||||||
|
next
|
||||||
|
break
|
||||||
|
is BINARY_CODE|DIV_TOKEN
|
||||||
|
for shiftcnt = 0 to 15
|
||||||
|
if op=>val == 1 << shiftcnt
|
||||||
|
op=>val = shiftcnt
|
||||||
|
opnext->code = BINARY_CODE|SHR_TOKEN
|
||||||
|
break
|
||||||
|
fin
|
||||||
|
next
|
||||||
|
break
|
||||||
|
}
|
||||||
|
break // CONST_CODE
|
||||||
|
is LADDR_CODE
|
||||||
|
when opnext->code
|
||||||
|
is CONST_CODE
|
||||||
|
if opnext=>nextop
|
||||||
|
opnextnext = opnext=>nextop
|
||||||
|
when opnextnext->code
|
||||||
|
is ADD_CODE
|
||||||
|
is INDEXB_CODE
|
||||||
|
op=>offsz = op=>offsz + opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is INDEXW_CODE
|
||||||
|
op=>offsz = op=>offsz + opnext=>val * 2
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
wend
|
||||||
|
fin
|
||||||
|
break
|
||||||
|
is LB_CODE
|
||||||
|
op->code = LLB_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is LW_CODE
|
||||||
|
op->code = LLW_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is SB_CODE
|
||||||
|
op->code = SLB_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is SW_CODE
|
||||||
|
op->code = SLW_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
wend
|
||||||
|
if pass > 0 and not freeops
|
||||||
|
crunched = try_dupify(op)
|
||||||
|
fin
|
||||||
|
break // LADDR_CODE
|
||||||
|
is GADDR_CODE
|
||||||
|
when opnext->code
|
||||||
|
is CONST_CODE
|
||||||
|
if opnext=>nextop
|
||||||
|
opnextnext = opnext=>nextop
|
||||||
|
when opnextnext->code
|
||||||
|
is ADD_CODE
|
||||||
|
is INDEXB_CODE
|
||||||
|
op=>offsz = op=>offsz + opnext=>val
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
is INDEXW_CODE
|
||||||
|
op=>offsz = op=>offsz + opnext=>val * 2
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
wend
|
||||||
|
fin
|
||||||
|
break
|
||||||
|
is LB_CODE:
|
||||||
|
op->code = LAB_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is LW_CODE
|
||||||
|
op->code = LAW_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is SB_CODE
|
||||||
|
op->code = SAB_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is SW_CODE
|
||||||
|
op->code = SAW_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is ICAL_CODE
|
||||||
|
op->code = CALL_CODE
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
wend
|
||||||
|
if pass > 0 and not freeops
|
||||||
|
crunched = try_dupify(op)
|
||||||
|
fin
|
||||||
|
break // GADDR_CODE
|
||||||
|
is LLB_CODE:
|
||||||
|
if pass > 0
|
||||||
|
crunched = try_dupify(op)
|
||||||
|
break // LLB_CODE
|
||||||
|
is LLW_CODE
|
||||||
|
// LLW [n]:CB 8:SHR -> LLB [n+1]
|
||||||
|
if opnext->code == CONST_CODE and opnext=>val == 8
|
||||||
|
if opnext=>nextop
|
||||||
|
opnextnext = opnext=>nextop
|
||||||
|
if opnextnext->code == SHR_CODE
|
||||||
|
op->code = LLB_CODE
|
||||||
|
op=>offsz++
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
fin
|
||||||
|
fin
|
||||||
|
fin
|
||||||
|
if pass > 0 and not freeops
|
||||||
|
crunched = try_dupify(op)
|
||||||
|
fin
|
||||||
|
break // LLW_CODE
|
||||||
|
is LAB_CODE
|
||||||
|
if pass > 0 and (op->type) // || !is_hardware_address(op->offsz)))
|
||||||
|
crunched = try_dupify(op)
|
||||||
|
break // LAB_CODE
|
||||||
|
is LAW_CODE
|
||||||
|
// LAW x:CB 8:SHR -> LAB x+1
|
||||||
|
if opnext->code == CONST_CODE and opnext=>val == 8
|
||||||
|
if opnext=>nextop
|
||||||
|
opnextnext = opnext=>nextop
|
||||||
|
if opnextnext->code == SHR_CODE
|
||||||
|
op->code = LAB_CODE
|
||||||
|
op=>offsz++
|
||||||
|
freeops = 2
|
||||||
|
break
|
||||||
|
fin
|
||||||
|
fin
|
||||||
|
fin
|
||||||
|
if pass > 0 and not freeops and (op->type) // || !is_hardware_address(op->offsz)))
|
||||||
|
crunched = try_dupify(op)
|
||||||
|
fin
|
||||||
|
break // LAW_CODE
|
||||||
|
is LOGIC_NOT_CODE
|
||||||
|
when opnext->code
|
||||||
|
is BRFALSE_CODE
|
||||||
|
op->code = BRTRUE_CODE
|
||||||
|
op=>tag = opnext=>tag
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
is BRTRUE_CODE
|
||||||
|
op->code = BRFALSE_CODE
|
||||||
|
op=>tag = opnext=>tag
|
||||||
|
freeops = 1
|
||||||
|
break
|
||||||
|
wend
|
||||||
|
break // LOGIC_NOT_CODE
|
||||||
|
is SLB_CODE
|
||||||
|
if opnext->code == LLB_CODE and op=>offsz == opnext=>offsz
|
||||||
|
op->code = DLB_CODE
|
||||||
|
freeops = 1
|
||||||
|
fin
|
||||||
|
break // SLB_CODE
|
||||||
|
is SLW_CODE
|
||||||
|
if opnext->code == LLW_CODE and op=>offsz == opnext=>offsz
|
||||||
|
op->code = DLW_CODE
|
||||||
|
freeops = 1
|
||||||
|
fin
|
||||||
|
break // SLW_CODE
|
||||||
|
is SAB_CODE
|
||||||
|
if opnext->code == LAB_CODE and op=>tag == opnext=>tag and op=>offsz == opnext=>offsz and op->type == opnext->type
|
||||||
|
op->code = DAB_CODE
|
||||||
|
freeops = 1
|
||||||
|
fin
|
||||||
|
break // SAB_CODE
|
||||||
|
is SAW_CODE
|
||||||
|
if opnext->code == LAW_CODE and op=>tag == opnext=>tag and op=>offsz == opnext=>offsz and op->type == opnext->type
|
||||||
|
op->code = DAW_CODE
|
||||||
|
freeops = 1
|
||||||
|
fin
|
||||||
|
break // SAW_CODE
|
||||||
|
wend
|
||||||
|
//
|
||||||
|
// Free up crunched ops. If freeops is positive we free up that many ops
|
||||||
|
// *after* op; if it's negative, we free up abs(freeops) ops *starting
|
||||||
|
// with* op.
|
||||||
|
//
|
||||||
|
if freeops < 0
|
||||||
|
freeops = -freeops
|
||||||
|
if op == *seq
|
||||||
|
//
|
||||||
|
// If op is at the start of the sequence, we treat this as a special case.
|
||||||
|
//
|
||||||
|
while freeops > 0
|
||||||
|
opnext = op=>nextop
|
||||||
|
release_op(op)
|
||||||
|
*seq = opnext
|
||||||
|
op = opnext
|
||||||
|
freeops--
|
||||||
|
loop
|
||||||
|
crunched = TRUE
|
||||||
|
else
|
||||||
|
//
|
||||||
|
// Otherwise we just move op back to point to the previous op and
|
||||||
|
// let the following loop remove the required number of ops.
|
||||||
|
//
|
||||||
|
op = opprev
|
||||||
|
opnext = op=>nextop
|
||||||
|
fin
|
||||||
|
fin
|
||||||
|
while freeops
|
||||||
|
op=>nextop = opnext=>nextop
|
||||||
|
opnext=>nextop = freeop_lst
|
||||||
|
freeop_lst = opnext
|
||||||
|
opnext = op=>nextop
|
||||||
|
crunched = TRUE
|
||||||
|
freeops--
|
||||||
|
loop
|
||||||
|
opprev = op
|
||||||
|
op = opnext
|
||||||
|
opnext = op=>nextop
|
||||||
|
loop
|
||||||
|
return crunched
|
||||||
|
end
|
||||||
|
//
|
||||||
|
// Generate a sequence of code
|
||||||
//
|
//
|
||||||
def gen_seq(seq, opcode, cval, tag, offsz, type)
|
def gen_seq(seq, opcode, cval, tag, offsz, type)
|
||||||
{
|
{
|
||||||
@@ -596,7 +984,7 @@ def gen_seq(seq, opcode, cval, tag, offsz, type)
|
|||||||
return seq
|
return seq
|
||||||
end
|
end
|
||||||
//
|
//
|
||||||
//Append one sequence to the end of another
|
// Append one sequence to the end of another
|
||||||
//
|
//
|
||||||
def cat_seq(seq1, seq2)
|
def cat_seq(seq1, seq2)
|
||||||
{
|
{
|
||||||
@@ -609,10 +997,11 @@ def cat_seq(seq1, seq2)
|
|||||||
return seq1
|
return seq1
|
||||||
fin
|
fin
|
||||||
//
|
//
|
||||||
//Emit the pending sequence
|
// Emit the pending sequence
|
||||||
//
|
//
|
||||||
def emit_pending_seq#0
|
def emit_pending_seq#0
|
||||||
word lcl_pending, op
|
word lcl_pending, op
|
||||||
|
//
|
||||||
// This is called by some of the emit_*() functions to ensure that any
|
// This is called by some of the emit_*() functions to ensure that any
|
||||||
// pending ops are emitted before they emit their own op when they are
|
// pending ops are emitted before they emit their own op when they are
|
||||||
// called from the parser. However, this function itself calls some of those
|
// called from the parser. However, this function itself calls some of those
|
||||||
@@ -620,6 +1009,7 @@ def emit_pending_seq#0
|
|||||||
// would cause an infinite loop if we weren't careful. We therefore set
|
// would cause an infinite loop if we weren't careful. We therefore set
|
||||||
// pending_seq to null on entry and work with a local copy, so if this
|
// pending_seq to null on entry and work with a local copy, so if this
|
||||||
// function calls back into itself it is a no-op.
|
// function calls back into itself it is a no-op.
|
||||||
|
//
|
||||||
if not pending_seq; return; fin
|
if not pending_seq; return; fin
|
||||||
lcl_pending = pending_seq
|
lcl_pending = pending_seq
|
||||||
pending_seq = NULL
|
pending_seq = NULL
|
||||||
@@ -661,7 +1051,7 @@ def emit_pending_seq#0
|
|||||||
break
|
break
|
||||||
is SW_CODE
|
is SW_CODE
|
||||||
emit_sw()
|
emit_sw()
|
||||||
break;
|
break
|
||||||
is SLB_CODE
|
is SLB_CODE
|
||||||
emit_slb(op-=>offsz)
|
emit_slb(op-=>offsz)
|
||||||
break
|
break
|
||||||
@@ -727,7 +1117,7 @@ def emit_pending_seq#0
|
|||||||
break
|
break
|
||||||
is CODETAG_CODE
|
is CODETAG_CODE
|
||||||
printf("_B%03d%c\n", op->tag, LBL);
|
printf("_B%03d%c\n", op->tag, LBL);
|
||||||
break;
|
break
|
||||||
is NEG_CODE
|
is NEG_CODE
|
||||||
is COMP_CODE
|
is COMP_CODE
|
||||||
is LOGIC_NOT_CODE
|
is LOGIC_NOT_CODE
|
||||||
@@ -811,6 +1201,7 @@ def emit_seq(seq)#0
|
|||||||
op = op=>nextop
|
op = op=>nextop
|
||||||
loop
|
loop
|
||||||
pending_seq = cat_seq(pending_seq, seq)
|
pending_seq = cat_seq(pending_seq, seq)
|
||||||
|
//
|
||||||
// The source code comments in the output are much more logical if we don't
|
// The source code comments in the output are much more logical if we don't
|
||||||
// merge multiple sequences together. There's no value in doing this merging
|
// merge multiple sequences together. There's no value in doing this merging
|
||||||
// if we're not optimizing, and we optionally allow it to be prevented even
|
// if we're not optimizing, and we optionally allow it to be prevented even
|
||||||
@@ -818,6 +1209,8 @@ def emit_seq(seq)#0
|
|||||||
//
|
//
|
||||||
// We must also force output if the sequence includes a CS opcode, as the
|
// We must also force output if the sequence includes a CS opcode, as the
|
||||||
// associated 'constant' is only temporarily valid.
|
// associated 'constant' is only temporarily valid.
|
||||||
if !(outflags & (OPTIMIZE|OPTIMIZE2)) or (outflags & NO_COMBINE) or string
|
//
|
||||||
|
if not (outflags & (OPTIMIZE|OPTIMIZE2)) or (outflags & NO_COMBINE) or string
|
||||||
emit_pending_seq
|
emit_pending_seq
|
||||||
|
fin
|
||||||
end
|
end
|
||||||
|
@@ -216,9 +216,9 @@ end
|
|||||||
// Normal expression parsing
|
// Normal expression parsing
|
||||||
//
|
//
|
||||||
def parse_list#2
|
def parse_list#2
|
||||||
{
|
|
||||||
byte listdepth, stackdepth
|
byte listdepth, stackdepth
|
||||||
word listseq
|
word listseq
|
||||||
|
|
||||||
listseq = NULL
|
listseq = NULL
|
||||||
listdepth = 0
|
listdepth = 0
|
||||||
repeat
|
repeat
|
||||||
@@ -226,7 +226,7 @@ def parse_list#2
|
|||||||
listdepth = listdepth + stackdepth
|
listdepth = listdepth + stackdepth
|
||||||
until not listseq or token <> COMMA_TOKEN
|
until not listseq or token <> COMMA_TOKEN
|
||||||
return listseq, listdepth
|
return listseq, listdepth
|
||||||
}
|
end
|
||||||
def parse_value(codeseq, rvalue)#2
|
def parse_value(codeseq, rvalue)#2
|
||||||
byte cfnparms, cfnvals, stackdepth, deref, type, operation
|
byte cfnparms, cfnvals, stackdepth, deref, type, operation
|
||||||
word optos, idptr, value, const_offset
|
word optos, idptr, value, const_offset
|
||||||
@@ -435,7 +435,7 @@ def parse_value(codeseq, rvalue)#2
|
|||||||
wend
|
wend
|
||||||
until not operation
|
until not operation
|
||||||
//
|
//
|
||||||
//Resolve outstanding dereference pointer loads
|
// Resolve outstanding dereference pointer loads
|
||||||
//
|
//
|
||||||
while deref > rvalue
|
while deref > rvalue
|
||||||
deref--
|
deref--
|
||||||
@@ -461,11 +461,11 @@ def parse_value(codeseq, rvalue)#2
|
|||||||
fin
|
fin
|
||||||
fin
|
fin
|
||||||
//
|
//
|
||||||
//Output pre-operations
|
// Output pre-operations
|
||||||
//
|
//
|
||||||
valseq = cat_seq(valseq, uopseq)
|
valseq = cat_seq(valseq, uopseq)
|
||||||
//
|
//
|
||||||
//Wrap up LVALUE store
|
// Wrap up LVALUE store
|
||||||
//
|
//
|
||||||
if not rvalue
|
if not rvalue
|
||||||
stackdepth--
|
stackdepth--
|
||||||
@@ -514,7 +514,7 @@ def parse_expr(codeseq)#2
|
|||||||
stackdepth--
|
stackdepth--
|
||||||
loop
|
loop
|
||||||
//
|
//
|
||||||
//Look for ternary operator
|
// Look for ternary operator
|
||||||
//
|
//
|
||||||
if token == TERNARY_TOKEN
|
if token == TERNARY_TOKEN
|
||||||
if stackdepth <> 1; exit_err("Ternary op must evaluate to single value"); fin
|
if stackdepth <> 1; exit_err("Ternary op must evaluate to single value"); fin
|
||||||
@@ -1068,11 +1068,10 @@ def parse_mods
|
|||||||
if token <> END_TKN; exit_err("Missing IMPORT/END"); fin
|
if token <> END_TKN; exit_err("Missing IMPORT/END"); fin
|
||||||
scan
|
scan
|
||||||
fin
|
fin
|
||||||
if token == EOL_TOKEN
|
if token == EOL_TOKEN; return TRUE; fin
|
||||||
return TRUE
|
|
||||||
emit_moddep(0, 0)
|
emit_moddep(0, 0)
|
||||||
return FALSE
|
return FALSE
|
||||||
}
|
end
|
||||||
def parse_lambda
|
def parse_lambda
|
||||||
word func_tag
|
word func_tag
|
||||||
byte cfnparms
|
byte cfnparms
|
||||||
@@ -1080,7 +1079,7 @@ def parse_lambda
|
|||||||
if not infunc; exit_err("Lambda functions only allowed inside definitions"); fin
|
if not infunc; exit_err("Lambda functions only allowed inside definitions"); fin
|
||||||
idlocal_save
|
idlocal_save
|
||||||
//
|
//
|
||||||
//Parse parameters and return value count
|
// Parse parameters and return value count
|
||||||
//
|
//
|
||||||
cfnparms = 0
|
cfnparms = 0
|
||||||
if scan == OPEN_PAREN_TKN
|
if scan == OPEN_PAREN_TKN
|
||||||
@@ -1216,8 +1215,8 @@ def parse_module
|
|||||||
loop
|
loop
|
||||||
framesize = 0
|
framesize = 0
|
||||||
entrypoint = codeptr
|
entrypoint = codeptr
|
||||||
|
prevstmnt = 0
|
||||||
emit_enter(0)
|
emit_enter(0)
|
||||||
prevstmnt = 0
|
|
||||||
if token <> DONE_TKN
|
if token <> DONE_TKN
|
||||||
while parse_stmnt
|
while parse_stmnt
|
||||||
nextln
|
nextln
|
||||||
|
Reference in New Issue
Block a user