Add malloc/free as intrinsic
This commit is contained in:
parent
08adc7f1bd
commit
7858c2135b
|
@ -51,16 +51,15 @@ void heapcheck(void)
|
||||||
for(i=0; i<s; i++)
|
for(i=0; i<s; i++)
|
||||||
{
|
{
|
||||||
if (p[i] != n)
|
if (p[i] != n)
|
||||||
{
|
|
||||||
printf("MemError %d at %d:%d != %d\n", k, i, n, p[i]);
|
|
||||||
exit(-2);
|
exit(-2);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
free(memp[n]);
|
free(memp[n]);
|
||||||
|
|
||||||
s = rand() % 100 + 3;
|
s = rand() % 100 + 3;
|
||||||
mems[n] = s;
|
mems[n] = s;
|
||||||
memp[n] = malloc(s);
|
memp[n] = malloc(s);
|
||||||
|
if (!memp[n])
|
||||||
|
exit(-3);
|
||||||
memset(memp[n], n, s);
|
memset(memp[n], n, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
469
include/crt.c
469
include/crt.c
|
@ -4112,3 +4112,472 @@ cmpne:
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma bytecode(BC_BINOP_CMP_S32, inp_op_cmp_s32)
|
#pragma bytecode(BC_BINOP_CMP_S32, inp_op_cmp_s32)
|
||||||
|
|
||||||
|
|
||||||
|
void HeapStart, HeapEnd;
|
||||||
|
bool HeapInit;
|
||||||
|
|
||||||
|
struct Heap {
|
||||||
|
Heap * next;
|
||||||
|
unsigned size;
|
||||||
|
} HeapNode;
|
||||||
|
|
||||||
|
#pragma section(heap, 0x0000, HeapStart, HeapEnd)
|
||||||
|
|
||||||
|
__asm malloc
|
||||||
|
{
|
||||||
|
// round size to be a multiple of four
|
||||||
|
// and make room for two additional bytes
|
||||||
|
// to store size of memory node
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda accu + 0
|
||||||
|
sta tmp + 4
|
||||||
|
adc #$05
|
||||||
|
and #$fc
|
||||||
|
sta tmp
|
||||||
|
lda accu + 1
|
||||||
|
sta tmp + 5
|
||||||
|
adc #$00
|
||||||
|
sta tmp + 1
|
||||||
|
|
||||||
|
// check if heap is initialized
|
||||||
|
|
||||||
|
lda HeapInit
|
||||||
|
bne hasHeap
|
||||||
|
|
||||||
|
// initialize heap
|
||||||
|
|
||||||
|
lda #$ff
|
||||||
|
sta HeapInit
|
||||||
|
|
||||||
|
// set next pointer to null
|
||||||
|
lda #0
|
||||||
|
sta HeapStart + 0
|
||||||
|
sta HeapStart + 1
|
||||||
|
|
||||||
|
// set size of dummy node to null
|
||||||
|
sta HeapNode + 2
|
||||||
|
sta HeapNode + 3
|
||||||
|
|
||||||
|
// set next pointer of dummy node to first free heap block
|
||||||
|
lda #<HeapStart
|
||||||
|
sta HeapNode + 0
|
||||||
|
lda #>HeapStart
|
||||||
|
sta HeapNode + 1
|
||||||
|
|
||||||
|
// set size to size of heap
|
||||||
|
sec
|
||||||
|
lda #<HeapEnd
|
||||||
|
sbc #<HeapStart
|
||||||
|
sta HeapStart + 2
|
||||||
|
lda #>HeapEnd
|
||||||
|
sbc #>HeapStart
|
||||||
|
sta HeapStart + 3
|
||||||
|
|
||||||
|
hasHeap:
|
||||||
|
// remember address of pointer to this
|
||||||
|
// heap block, to correct if block is a
|
||||||
|
// perfect fit
|
||||||
|
|
||||||
|
lda #<HeapNode
|
||||||
|
sta accu + 2
|
||||||
|
lda #>HeapNode
|
||||||
|
sta accu + 3
|
||||||
|
|
||||||
|
// Now loop over free nodes, until we find a match
|
||||||
|
loop:
|
||||||
|
// next heap block
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
lda (accu + 2), y
|
||||||
|
sta accu
|
||||||
|
iny
|
||||||
|
lda (accu + 2), y
|
||||||
|
sta accu + 1
|
||||||
|
|
||||||
|
// exit if out of blocks
|
||||||
|
|
||||||
|
beq done
|
||||||
|
// calculate remaining size of heap block
|
||||||
|
|
||||||
|
ldy #2
|
||||||
|
sec
|
||||||
|
lda (accu), y
|
||||||
|
sbc tmp
|
||||||
|
sta tmp + 2
|
||||||
|
iny
|
||||||
|
lda (accu), y
|
||||||
|
sbc tmp + 1
|
||||||
|
sta tmp + 3
|
||||||
|
|
||||||
|
// will fit
|
||||||
|
bcs avail
|
||||||
|
|
||||||
|
// prev
|
||||||
|
lda accu
|
||||||
|
sta accu + 2
|
||||||
|
lda accu + 1
|
||||||
|
sta accu + 3
|
||||||
|
jmp loop
|
||||||
|
|
||||||
|
done:
|
||||||
|
// no more heap blocks
|
||||||
|
rts
|
||||||
|
avail:
|
||||||
|
// is it a perfect fit?
|
||||||
|
lda tmp + 2
|
||||||
|
ora tmp + 3
|
||||||
|
bne nofit
|
||||||
|
|
||||||
|
// so adjust previous pointer to point to
|
||||||
|
// next heap block
|
||||||
|
ldy #0
|
||||||
|
lda (accu), y
|
||||||
|
sta (accu + 2), y
|
||||||
|
iny
|
||||||
|
lda (accu), y
|
||||||
|
sta (accu + 2), y
|
||||||
|
jmp found
|
||||||
|
|
||||||
|
nofit:
|
||||||
|
// adjust size of remaining heapblock
|
||||||
|
ldy #2
|
||||||
|
lda tmp + 2
|
||||||
|
sta (accu), y
|
||||||
|
iny
|
||||||
|
lda tmp + 3
|
||||||
|
sta (accu), y
|
||||||
|
|
||||||
|
// advance address to start of next heap block
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda accu
|
||||||
|
adc tmp + 2
|
||||||
|
sta accu
|
||||||
|
lda accu + 1
|
||||||
|
adc tmp + 3
|
||||||
|
sta accu + 1
|
||||||
|
|
||||||
|
found:
|
||||||
|
// remember size of heap block for free without size
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
lda tmp + 4
|
||||||
|
sta (accu), y
|
||||||
|
iny
|
||||||
|
lda tmp + 5
|
||||||
|
sta (accu), y
|
||||||
|
|
||||||
|
// advanve by two bytes to skip size
|
||||||
|
clc
|
||||||
|
lda accu
|
||||||
|
adc #2
|
||||||
|
sta accu
|
||||||
|
bcc page
|
||||||
|
inc accu + 1
|
||||||
|
page:
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
|
||||||
|
__asm inp_malloc
|
||||||
|
{
|
||||||
|
sty tmpy
|
||||||
|
jsr malloc
|
||||||
|
ldy tmpy
|
||||||
|
jmp startup.exec
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma bytecode(BC_MALLOC, inp_malloc)
|
||||||
|
|
||||||
|
__asm free
|
||||||
|
{
|
||||||
|
// check nullptr free
|
||||||
|
lda accu
|
||||||
|
ora accu + 1
|
||||||
|
bne notnull
|
||||||
|
rts
|
||||||
|
notnull:
|
||||||
|
// two bytes back to fix size
|
||||||
|
sec
|
||||||
|
lda accu
|
||||||
|
sbc #2
|
||||||
|
sta accu
|
||||||
|
bcs page
|
||||||
|
dec accu + 1
|
||||||
|
page:
|
||||||
|
|
||||||
|
// cache size and end of block
|
||||||
|
|
||||||
|
clc
|
||||||
|
ldy #0
|
||||||
|
lda (accu), y
|
||||||
|
adc #5
|
||||||
|
and #$fc
|
||||||
|
sta tmp
|
||||||
|
iny
|
||||||
|
lda (accu), y
|
||||||
|
adc #0
|
||||||
|
sta tmp + 1
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda tmp + 0
|
||||||
|
adc accu
|
||||||
|
sta accu + 2
|
||||||
|
lda tmp + 1
|
||||||
|
adc accu + 1
|
||||||
|
sta accu + 3
|
||||||
|
|
||||||
|
// pointer to heap block, starting with
|
||||||
|
// dummy block
|
||||||
|
|
||||||
|
lda #<HeapNode
|
||||||
|
sta tmp + 2
|
||||||
|
lda #>HeapNode
|
||||||
|
sta tmp + 3
|
||||||
|
|
||||||
|
loop:
|
||||||
|
// check if end of heap
|
||||||
|
|
||||||
|
ldy #1
|
||||||
|
lda (tmp + 2), y
|
||||||
|
beq noend
|
||||||
|
|
||||||
|
// Check if behind this block
|
||||||
|
|
||||||
|
cmp accu + 1
|
||||||
|
bcc before
|
||||||
|
bne after
|
||||||
|
|
||||||
|
dey
|
||||||
|
lda (tmp + 2), y
|
||||||
|
cmp accu + 0
|
||||||
|
bcs after
|
||||||
|
|
||||||
|
before:
|
||||||
|
ldy # 1
|
||||||
|
lda (tmp + 2), y
|
||||||
|
tax
|
||||||
|
dey
|
||||||
|
lda (tmp + 2), y
|
||||||
|
sta tmp + 2
|
||||||
|
stx tmp + 3
|
||||||
|
jmp loop
|
||||||
|
after:
|
||||||
|
|
||||||
|
// Merge with next block
|
||||||
|
|
||||||
|
ldy #1
|
||||||
|
lda accu + 3
|
||||||
|
cmp (tmp + 2), y
|
||||||
|
bne noend
|
||||||
|
dey
|
||||||
|
lda accu + 2
|
||||||
|
cmp (tmp + 2), y
|
||||||
|
bne noend
|
||||||
|
|
||||||
|
// Pointer to next next block
|
||||||
|
ldy #0
|
||||||
|
lda (accu + 2), y
|
||||||
|
sta (accu), y
|
||||||
|
iny
|
||||||
|
lda (accu + 2), y
|
||||||
|
sta (accu), y
|
||||||
|
|
||||||
|
// Add size of next block to this
|
||||||
|
iny
|
||||||
|
clc
|
||||||
|
lda tmp
|
||||||
|
adc (accu + 2), y
|
||||||
|
sta tmp
|
||||||
|
iny
|
||||||
|
lda tmp + 1
|
||||||
|
adc (accu + 2), y
|
||||||
|
sta tmp + 1
|
||||||
|
|
||||||
|
jmp start
|
||||||
|
noend:
|
||||||
|
// Link to next block
|
||||||
|
ldy #0
|
||||||
|
lda (tmp + 2), y
|
||||||
|
sta (accu), y
|
||||||
|
iny
|
||||||
|
lda (tmp + 2), y
|
||||||
|
sta (accu), y
|
||||||
|
|
||||||
|
start:
|
||||||
|
// Calculate end of free block
|
||||||
|
ldy #2
|
||||||
|
clc
|
||||||
|
lda tmp + 2
|
||||||
|
adc (tmp + 2), y
|
||||||
|
iny
|
||||||
|
tax
|
||||||
|
lda tmp + 3
|
||||||
|
adc (tmp + 2), y
|
||||||
|
|
||||||
|
// Matches start of new block
|
||||||
|
cmp accu + 1
|
||||||
|
bne nostart
|
||||||
|
cpx accu
|
||||||
|
bne nostart
|
||||||
|
|
||||||
|
// If so, increase the size and link
|
||||||
|
// to free block after
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
lda (accu), y
|
||||||
|
sta (tmp + 2), y
|
||||||
|
iny
|
||||||
|
lda (accu), y
|
||||||
|
sta (tmp + 2), y
|
||||||
|
|
||||||
|
iny
|
||||||
|
clc
|
||||||
|
lda (tmp + 2), y
|
||||||
|
adc tmp
|
||||||
|
sta (tmp + 2), y
|
||||||
|
iny
|
||||||
|
lda (tmp + 2), y
|
||||||
|
adc tmp + 1
|
||||||
|
sta (tmp + 2), y
|
||||||
|
|
||||||
|
rts
|
||||||
|
|
||||||
|
nostart:
|
||||||
|
// Link to new free block
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
lda accu
|
||||||
|
sta (tmp + 2), y
|
||||||
|
iny
|
||||||
|
lda accu + 1
|
||||||
|
sta (tmp + 2), y
|
||||||
|
iny
|
||||||
|
|
||||||
|
// Set size of free block
|
||||||
|
lda tmp
|
||||||
|
sta (accu), y
|
||||||
|
iny
|
||||||
|
lda tmp + 1
|
||||||
|
sta (accu), y
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
|
||||||
|
__asm inp_free
|
||||||
|
{
|
||||||
|
sty tmpy
|
||||||
|
jsr free
|
||||||
|
ldy tmpy
|
||||||
|
jmp startup.exec
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma bytecode(BC_FREE, inp_free)
|
||||||
|
|
||||||
|
|
||||||
|
#pragma runtime(malloc, malloc)
|
||||||
|
#pragma runtime(free, free)
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
void * malloc(unsigned int size)
|
||||||
|
{
|
||||||
|
size = (size + 7) & ~3;
|
||||||
|
if (!freeHeapInit)
|
||||||
|
{
|
||||||
|
freeHeap = (Heap *)&HeapStart;
|
||||||
|
freeHeap->next = nullptr;
|
||||||
|
freeHeap->size = (unsigned int)&HeapEnd - (unsigned int)&HeapStart;
|
||||||
|
freeHeapInit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Heap * pheap = nullptr, * heap = freeHeap;
|
||||||
|
while (heap)
|
||||||
|
{
|
||||||
|
if (size <= heap->size)
|
||||||
|
{
|
||||||
|
if (size == heap->size)
|
||||||
|
{
|
||||||
|
if (pheap)
|
||||||
|
pheap->next = heap->next;
|
||||||
|
else
|
||||||
|
freeHeap = heap->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Heap * nheap = (Heap *)((int)heap + size);
|
||||||
|
nheap->size = heap->size - size;
|
||||||
|
nheap->next = heap->next;
|
||||||
|
if (pheap)
|
||||||
|
pheap->next = nheap;
|
||||||
|
else
|
||||||
|
freeHeap = nheap;
|
||||||
|
heap->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)((int)heap + 2);
|
||||||
|
}
|
||||||
|
pheap = heap;
|
||||||
|
heap = heap->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void * ptr)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Heap * fheap = (Heap *)((int)ptr - 2);
|
||||||
|
Heap * eheap = (Heap *)((int)ptr - 2 + fheap->size);
|
||||||
|
|
||||||
|
if (freeHeap)
|
||||||
|
{
|
||||||
|
if (eheap == freeHeap)
|
||||||
|
{
|
||||||
|
fheap->size += freeHeap->size;
|
||||||
|
fheap->next = freeHeap->next;
|
||||||
|
freeHeap = fheap;
|
||||||
|
}
|
||||||
|
else if (eheap < freeHeap)
|
||||||
|
{
|
||||||
|
fheap->next = freeHeap;
|
||||||
|
freeHeap = fheap;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Heap * pheap = freeHeap;
|
||||||
|
while (pheap->next && pheap->next < fheap)
|
||||||
|
pheap = pheap->next;
|
||||||
|
Heap * nheap = (Heap *)((int)pheap + pheap->size);
|
||||||
|
|
||||||
|
if (nheap == fheap)
|
||||||
|
{
|
||||||
|
pheap->size += fheap->size;
|
||||||
|
if (pheap->next == eheap)
|
||||||
|
{
|
||||||
|
pheap->size += pheap->next->size;
|
||||||
|
pheap->next = pheap->next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pheap->next == eheap)
|
||||||
|
{
|
||||||
|
fheap->next = pheap->next->next;
|
||||||
|
fheap->size += pheap->next->size;
|
||||||
|
pheap->next = fheap;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fheap->next = pheap->next;
|
||||||
|
pheap->next = fheap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
freeHeap = fheap;
|
||||||
|
freeHeap->next = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -142,8 +142,8 @@ enum ByteCode
|
||||||
BC_BRANCHF_LE,
|
BC_BRANCHF_LE,
|
||||||
|
|
||||||
BC_LOOP_U8,
|
BC_LOOP_U8,
|
||||||
BC_UNUSED_2,
|
BC_MALLOC,
|
||||||
BC_UNUSED_3,
|
BC_FREE,
|
||||||
BC_UNUSED_4,
|
BC_UNUSED_4,
|
||||||
BC_UNUSED_5,
|
BC_UNUSED_5,
|
||||||
BC_UNUSED_6,
|
BC_UNUSED_6,
|
||||||
|
|
|
@ -524,6 +524,7 @@ void exit(int status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct Heap {
|
struct Heap {
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
Heap * next;
|
Heap * next;
|
||||||
|
@ -636,6 +637,7 @@ void free(void * ptr)
|
||||||
freeHeap->next = nullptr;
|
freeHeap->next = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void * calloc(int num, int size)
|
void * calloc(int num, int size)
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,6 +47,10 @@ unsigned int rand(void);
|
||||||
|
|
||||||
void srand(unsigned int seed);
|
void srand(unsigned int seed);
|
||||||
|
|
||||||
|
#pragma intrinsic(malloc)
|
||||||
|
|
||||||
|
#pragma intrinsic(free)
|
||||||
|
|
||||||
#pragma compile("stdlib.c")
|
#pragma compile("stdlib.c")
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -142,8 +142,8 @@ static const char* ByteCodeNames[] = {
|
||||||
"BRANCHF_LE",
|
"BRANCHF_LE",
|
||||||
|
|
||||||
"LOOP_U8",
|
"LOOP_U8",
|
||||||
nullptr,
|
"MALLOC",
|
||||||
nullptr,
|
"FREE",
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -565,6 +565,11 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used)
|
||||||
used = 0;
|
used = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BC_MALLOC:
|
||||||
|
case BC_FREE:
|
||||||
|
used = 0x0000ffff;
|
||||||
|
break;
|
||||||
|
|
||||||
case BC_BINOP_ADDA_16:
|
case BC_BINOP_ADDA_16:
|
||||||
used |= 0x0000ffff;
|
used |= 0x0000ffff;
|
||||||
break;
|
break;
|
||||||
|
@ -779,6 +784,8 @@ bool ByteCodeInstruction::UsesRegister(uint32 reg) const
|
||||||
return true;
|
return true;
|
||||||
if (mCode == BC_BINOP_ADDA_16)
|
if (mCode == BC_BINOP_ADDA_16)
|
||||||
return true;
|
return true;
|
||||||
|
if (mCode == BC_MALLOC || mCode == BC_FREE)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg == BC_REG_ADDR)
|
if (reg == BC_REG_ADDR)
|
||||||
|
@ -851,6 +858,8 @@ bool ByteCodeInstruction::ChangesRegister(uint32 reg) const
|
||||||
return true;
|
return true;
|
||||||
if (mCode == BC_LOOP_U8)
|
if (mCode == BC_LOOP_U8)
|
||||||
return true;
|
return true;
|
||||||
|
if (mCode == BC_MALLOC || mCode == BC_FREE)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg == BC_REG_ADDR)
|
if (reg == BC_REG_ADDR)
|
||||||
|
@ -869,6 +878,8 @@ bool ByteCodeInstruction::ChangesRegister(uint32 reg) const
|
||||||
{
|
{
|
||||||
if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS)
|
if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS)
|
||||||
return true;
|
return true;
|
||||||
|
if (mCode == BC_MALLOC || mCode == BC_FREE)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (mCode == BC_BINOP_DIVR_I16 || mCode == BC_BINOP_DIVR_U16 || mCode == BC_BINOP_MODR_I16 || mCode == BC_BINOP_MODR_U16 ||
|
if (mCode == BC_BINOP_DIVR_I16 || mCode == BC_BINOP_DIVR_U16 || mCode == BC_BINOP_MODR_I16 || mCode == BC_BINOP_MODR_U16 ||
|
||||||
mCode == BC_BINOP_DIV_I32 || mCode == BC_BINOP_DIV_U32 || mCode == BC_BINOP_MOD_I32 || mCode == BC_BINOP_MOD_U32 ||
|
mCode == BC_BINOP_DIV_I32 || mCode == BC_BINOP_DIV_U32 || mCode == BC_BINOP_MOD_I32 || mCode == BC_BINOP_MOD_U32 ||
|
||||||
|
@ -1149,6 +1160,8 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BC_MALLOC:
|
||||||
|
case BC_FREE:
|
||||||
case BC_CALL_ADDR:
|
case BC_CALL_ADDR:
|
||||||
block->PutCode(generator, mCode);
|
block->PutCode(generator, mCode);
|
||||||
break;
|
break;
|
||||||
|
@ -1578,6 +1591,49 @@ void ByteCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstru
|
||||||
mIns.Push(cins);
|
mIns.Push(cins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ByteCodeBasicBlock::CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins)
|
||||||
|
{
|
||||||
|
if (ins->mSrc[0].mTemp < 0)
|
||||||
|
{
|
||||||
|
ByteCodeInstruction dins(BC_CONST_16);
|
||||||
|
dins.mRegister = BC_REG_ACCU;
|
||||||
|
dins.mValue = int(ins->mSrc[0].mIntConst & 0xffff);
|
||||||
|
mIns.Push(dins);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ByteCodeInstruction dins(BC_LOAD_REG_16);
|
||||||
|
dins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
||||||
|
dins.mRegisterFinal = ins->mSrc[0].mFinal;
|
||||||
|
mIns.Push(dins);
|
||||||
|
}
|
||||||
|
ByteCodeInstruction cins(BC_MALLOC);
|
||||||
|
mIns.Push(cins);
|
||||||
|
ByteCodeInstruction bins(BC_STORE_REG_16);
|
||||||
|
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
|
||||||
|
mIns.Push(bins);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ByteCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins)
|
||||||
|
{
|
||||||
|
if (ins->mSrc[0].mTemp < 0)
|
||||||
|
{
|
||||||
|
ByteCodeInstruction dins(BC_CONST_16);
|
||||||
|
dins.mRegister = BC_REG_ACCU;
|
||||||
|
dins.mValue = int(ins->mSrc[0].mIntConst & 0xffff);
|
||||||
|
mIns.Push(dins);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ByteCodeInstruction dins(BC_LOAD_REG_16);
|
||||||
|
dins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
||||||
|
dins.mRegisterFinal = ins->mSrc[0].mFinal;
|
||||||
|
mIns.Push(dins);
|
||||||
|
}
|
||||||
|
ByteCodeInstruction cins(BC_FREE);
|
||||||
|
mIns.Push(cins);
|
||||||
|
}
|
||||||
|
|
||||||
void ByteCodeBasicBlock::StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins)
|
void ByteCodeBasicBlock::StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins)
|
||||||
{
|
{
|
||||||
if (ins->mSrc[0].mType == IT_FLOAT)
|
if (ins->mSrc[0].mType == IT_FLOAT)
|
||||||
|
@ -4259,6 +4315,12 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p
|
||||||
case IC_STRCPY:
|
case IC_STRCPY:
|
||||||
StrcpyValue(iproc, ins);
|
StrcpyValue(iproc, ins);
|
||||||
break;
|
break;
|
||||||
|
case IC_MALLOC:
|
||||||
|
CallMalloc(iproc, ins);
|
||||||
|
break;
|
||||||
|
case IC_FREE:
|
||||||
|
CallFree(iproc, ins);
|
||||||
|
break;
|
||||||
case IC_LOAD_TEMPORARY:
|
case IC_LOAD_TEMPORARY:
|
||||||
{
|
{
|
||||||
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
||||||
|
|
|
@ -143,8 +143,8 @@ enum ByteCode
|
||||||
BC_BRANCHF_LE,
|
BC_BRANCHF_LE,
|
||||||
|
|
||||||
BC_LOOP_U8,
|
BC_LOOP_U8,
|
||||||
BC_UNUSED_2,
|
BC_MALLOC,
|
||||||
BC_UNUSED_3,
|
BC_FREE,
|
||||||
BC_UNUSED_4,
|
BC_UNUSED_4,
|
||||||
BC_UNUSED_5,
|
BC_UNUSED_5,
|
||||||
BC_UNUSED_6,
|
BC_UNUSED_6,
|
||||||
|
@ -283,6 +283,8 @@ public:
|
||||||
void FloatConstToWork(double val);
|
void FloatConstToWork(double val);
|
||||||
void CopyValue(InterCodeProcedure* proc, const InterInstruction * ins);
|
void CopyValue(InterCodeProcedure* proc, const InterInstruction * ins);
|
||||||
void StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins);
|
void StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins);
|
||||||
|
void CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins);
|
||||||
|
void CallFree(InterCodeProcedure* proc, const InterInstruction* ins);
|
||||||
void LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins);
|
void LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins);
|
||||||
void StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins);
|
void StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins);
|
||||||
void LoadDirectValue(InterCodeProcedure* proc, const InterInstruction * ins);
|
void LoadDirectValue(InterCodeProcedure* proc, const InterInstruction * ins);
|
||||||
|
|
|
@ -669,6 +669,9 @@ bool Compiler::GenerateCode(void)
|
||||||
RegisterRuntime(loc, Ident::Unique("mods32"));
|
RegisterRuntime(loc, Ident::Unique("mods32"));
|
||||||
RegisterRuntime(loc, Ident::Unique("divu32"));
|
RegisterRuntime(loc, Ident::Unique("divu32"));
|
||||||
RegisterRuntime(loc, Ident::Unique("modu32"));
|
RegisterRuntime(loc, Ident::Unique("modu32"));
|
||||||
|
|
||||||
|
RegisterRuntime(loc, Ident::Unique("malloc"));
|
||||||
|
RegisterRuntime(loc, Ident::Unique("free"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register extended byte code functions
|
// Register extended byte code functions
|
||||||
|
|
|
@ -187,7 +187,7 @@ enum ExpressionType
|
||||||
EX_ASSUME,
|
EX_ASSUME,
|
||||||
EX_BANKOF,
|
EX_BANKOF,
|
||||||
EX_CONSTRUCT,
|
EX_CONSTRUCT,
|
||||||
EX_CLEANUP,
|
EX_CLEANUP
|
||||||
};
|
};
|
||||||
|
|
||||||
class Expression
|
class Expression
|
||||||
|
|
|
@ -476,6 +476,13 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank
|
||||||
fprintf(file, "CNVFS\tACCU");
|
fprintf(file, "CNVFS\tACCU");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BC_MALLOC:
|
||||||
|
fprintf(file, "MALLOC\tACCU");
|
||||||
|
break;
|
||||||
|
case BC_FREE:
|
||||||
|
fprintf(file, "FREE\tACCU");
|
||||||
|
break;
|
||||||
|
|
||||||
case BC_JUMPS:
|
case BC_JUMPS:
|
||||||
fprintf(file, "JUMP\t$%04X", start + i + 1 + int8(memory[start + i + 0]));
|
fprintf(file, "JUMP\t$%04X", start + i + 1 + int8(memory[start + i + 0]));
|
||||||
i++;
|
i++;
|
||||||
|
|
|
@ -634,7 +634,7 @@ bool InterCodeBasicBlock::CanSwapInstructions(const InterInstruction* ins0, cons
|
||||||
{
|
{
|
||||||
if (ins0->mCode == IC_CALL || ins0->mCode == IC_CALL_NATIVE || ins0->mCode == IC_ASSEMBLER ||
|
if (ins0->mCode == IC_CALL || ins0->mCode == IC_CALL_NATIVE || ins0->mCode == IC_ASSEMBLER ||
|
||||||
ins0->mCode == IC_RETURN || ins0->mCode == IC_RETURN_STRUCT || ins0->mCode == IC_RETURN_VALUE ||
|
ins0->mCode == IC_RETURN || ins0->mCode == IC_RETURN_STRUCT || ins0->mCode == IC_RETURN_VALUE ||
|
||||||
ins0->mCode == IC_PUSH_FRAME || ins0->mCode == IC_POP_FRAME)
|
ins0->mCode == IC_PUSH_FRAME || ins0->mCode == IC_POP_FRAME || ins0->mCode == IC_MALLOC || ins0->mCode == IC_FREE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ins0->mCode == IC_LOAD || ins0->mCode == IC_STORE || ins0->mCode == IC_COPY || ins0->mCode == IC_STRCPY)
|
if (ins0->mCode == IC_LOAD || ins0->mCode == IC_STORE || ins0->mCode == IC_COPY || ins0->mCode == IC_STRCPY)
|
||||||
|
@ -643,13 +643,30 @@ bool InterCodeBasicBlock::CanSwapInstructions(const InterInstruction* ins0, cons
|
||||||
if (ins0->mCode == IC_CALL || ins0->mCode == IC_CALL_NATIVE || ins0->mCode == IC_ASSEMBLER)
|
if (ins0->mCode == IC_CALL || ins0->mCode == IC_CALL_NATIVE || ins0->mCode == IC_ASSEMBLER)
|
||||||
{
|
{
|
||||||
if (ins1->mCode == IC_RETURN || ins1->mCode == IC_RETURN_STRUCT || ins1->mCode == IC_RETURN_VALUE ||
|
if (ins1->mCode == IC_RETURN || ins1->mCode == IC_RETURN_STRUCT || ins1->mCode == IC_RETURN_VALUE ||
|
||||||
ins1->mCode == IC_PUSH_FRAME || ins1->mCode == IC_POP_FRAME)
|
ins1->mCode == IC_PUSH_FRAME || ins1->mCode == IC_POP_FRAME || ins1->mCode == IC_MALLOC || ins1->mCode == IC_FREE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ins1->mCode == IC_LOAD || ins1->mCode == IC_STORE || ins1->mCode == IC_COPY || ins1->mCode == IC_STRCPY)
|
if (ins1->mCode == IC_LOAD || ins1->mCode == IC_STORE || ins1->mCode == IC_COPY || ins1->mCode == IC_STRCPY)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ins0->mCode == IC_MALLOC || ins0->mCode == IC_FREE)
|
||||||
|
{
|
||||||
|
if (ins1->mCode == IC_MALLOC || ins1->mCode == IC_FREE)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ins0->mCode == IC_FREE)
|
||||||
|
{
|
||||||
|
if (ins1->mCode == IC_LOAD || ins1->mCode == IC_STORE || ins1->mCode == IC_COPY || ins1->mCode == IC_STRCPY)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ins1->mCode == IC_FREE)
|
||||||
|
{
|
||||||
|
if (ins0->mCode == IC_LOAD || ins0->mCode == IC_STORE || ins0->mCode == IC_COPY || ins0->mCode == IC_STRCPY)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check frame pointer
|
// Check frame pointer
|
||||||
if (ins0->mCode == IC_PUSH_FRAME || ins0->mCode == IC_POP_FRAME)
|
if (ins0->mCode == IC_PUSH_FRAME || ins0->mCode == IC_POP_FRAME)
|
||||||
{
|
{
|
||||||
|
@ -1151,17 +1168,17 @@ void ValueSet::InsertValue(InterInstruction * ins)
|
||||||
|
|
||||||
static bool HasSideEffect(InterCode code)
|
static bool HasSideEffect(InterCode code)
|
||||||
{
|
{
|
||||||
return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER;
|
return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_MALLOC || code == IC_FREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsObservable(InterCode code)
|
static bool IsObservable(InterCode code)
|
||||||
{
|
{
|
||||||
return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_STORE || code == IC_COPY || code == IC_STRCPY;
|
return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_STORE || code == IC_COPY || code == IC_STRCPY || code == IC_MALLOC || code == IC_FREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsMoveable(InterCode code)
|
static bool IsMoveable(InterCode code)
|
||||||
{
|
{
|
||||||
if (HasSideEffect(code) || code == IC_COPY || code == IC_STRCPY || code == IC_STORE || code == IC_BRANCH || code == IC_POP_FRAME || code == IC_PUSH_FRAME)
|
if (HasSideEffect(code) || code == IC_COPY || code == IC_STRCPY || code == IC_STORE || code == IC_BRANCH || code == IC_POP_FRAME || code == IC_PUSH_FRAME || code == IC_MALLOC || code == IC_FREE)
|
||||||
return false;
|
return false;
|
||||||
if (code == IC_RETURN || code == IC_RETURN_STRUCT || code == IC_RETURN_VALUE)
|
if (code == IC_RETURN || code == IC_RETURN_STRUCT || code == IC_RETURN_VALUE)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2762,12 +2779,43 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
|
||||||
case IC_BRANCH:
|
case IC_BRANCH:
|
||||||
if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT)
|
if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT)
|
||||||
{
|
{
|
||||||
if (tvalue[ins->mSrc[0].mTemp]->mConst.mIntConst)
|
InterInstruction* tins = tvalue[ins->mSrc[0].mTemp];
|
||||||
ins->mCode = IC_JUMP;
|
if (IsIntegerType(tins->mConst.mType) || tins->mConst.mType == IT_BOOL)
|
||||||
else
|
{
|
||||||
ins->mCode = IC_JUMPF;
|
if (tins->mConst.mIntConst)
|
||||||
ins->mSrc[0].mTemp = -1;
|
ins->mCode = IC_JUMP;
|
||||||
ins->mNumOperands = 0;
|
else
|
||||||
|
ins->mCode = IC_JUMPF;
|
||||||
|
ins->mSrc[0].mTemp = -1;
|
||||||
|
ins->mNumOperands = 0;
|
||||||
|
}
|
||||||
|
else if (tins->mConst.mType == IT_POINTER)
|
||||||
|
{
|
||||||
|
if (tins->mConst.mMemory == IM_ABSOLUTE)
|
||||||
|
{
|
||||||
|
if (tins->mConst.mIntConst)
|
||||||
|
ins->mCode = IC_JUMP;
|
||||||
|
else
|
||||||
|
ins->mCode = IC_JUMPF;
|
||||||
|
ins->mSrc[0].mTemp = -1;
|
||||||
|
ins->mNumOperands = 0;
|
||||||
|
}
|
||||||
|
else if (tins->mConst.mMemory == IM_GLOBAL || tins->mConst.mMemory == IM_LOCAL || tins->mConst.mMemory == IM_PARAM || tins->mConst.mMemory == IM_FPARAM)
|
||||||
|
{
|
||||||
|
ins->mCode = IC_JUMP;
|
||||||
|
ins->mSrc[0].mTemp = -1;
|
||||||
|
ins->mNumOperands = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tins->mConst.mType == IT_FLOAT)
|
||||||
|
{
|
||||||
|
if (tins->mConst.mFloatConst)
|
||||||
|
ins->mCode = IC_JUMP;
|
||||||
|
else
|
||||||
|
ins->mCode = IC_JUMPF;
|
||||||
|
ins->mSrc[0].mTemp = -1;
|
||||||
|
ins->mNumOperands = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IC_PUSH_FRAME:
|
case IC_PUSH_FRAME:
|
||||||
|
@ -4214,6 +4262,16 @@ void InterInstruction::Disassemble(FILE* file)
|
||||||
else
|
else
|
||||||
fprintf(file, "COPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]);
|
fprintf(file, "COPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IC_MALLOC:
|
||||||
|
assert(mNumOperands == 1);
|
||||||
|
fprintf(file, "MALLOC");
|
||||||
|
break;
|
||||||
|
case IC_FREE:
|
||||||
|
assert(mNumOperands == 1);
|
||||||
|
fprintf(file, "FREE");
|
||||||
|
break;
|
||||||
|
|
||||||
case IC_STRCPY:
|
case IC_STRCPY:
|
||||||
fprintf(file, "STRCPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]);
|
fprintf(file, "STRCPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]);
|
||||||
break;
|
break;
|
||||||
|
@ -7696,7 +7754,7 @@ bool InterCodeBasicBlock::CalculateSingleAssignmentTemps(FastNumberSet& tassigne
|
||||||
bool valid = j == ins->mNumOperands;
|
bool valid = j == ins->mNumOperands;
|
||||||
if (valid)
|
if (valid)
|
||||||
{
|
{
|
||||||
if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_ASSEMBLER)
|
if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_ASSEMBLER || ins->mCode == IC_MALLOC || ins->mCode == IC_FREE)
|
||||||
valid = false;
|
valid = false;
|
||||||
else if (ins->mCode == IC_LOAD)
|
else if (ins->mCode == IC_LOAD)
|
||||||
{
|
{
|
||||||
|
@ -16035,7 +16093,7 @@ void InterCodeProcedure::Close(void)
|
||||||
{
|
{
|
||||||
GrowingTypeArray tstack(IT_NONE);
|
GrowingTypeArray tstack(IT_NONE);
|
||||||
|
|
||||||
CheckFunc = !strcmp(mIdent->mString, "test");
|
CheckFunc = !strcmp(mIdent->mString, "main");
|
||||||
|
|
||||||
mEntryBlock = mBlocks[0];
|
mEntryBlock = mBlocks[0];
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@ enum InterCode
|
||||||
IC_LEA,
|
IC_LEA,
|
||||||
IC_COPY,
|
IC_COPY,
|
||||||
IC_STRCPY,
|
IC_STRCPY,
|
||||||
|
IC_MALLOC,
|
||||||
|
IC_FREE,
|
||||||
IC_TYPECAST,
|
IC_TYPECAST,
|
||||||
IC_CONSTANT,
|
IC_CONSTANT,
|
||||||
IC_BRANCH,
|
IC_BRANCH,
|
||||||
|
|
|
@ -2429,6 +2429,30 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
}
|
}
|
||||||
mErrors->Error(exp->mLocation, ERRR_CANNOT_FIND_BANK_OF_EXPRESSION, "Cannot find bank of expressiohn");
|
mErrors->Error(exp->mLocation, ERRR_CANNOT_FIND_BANK_OF_EXPRESSION, "Cannot find bank of expressiohn");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case TK_NEW:
|
||||||
|
{
|
||||||
|
ins->mCode = IC_MALLOC;
|
||||||
|
ins->mSrc[0].mType = InterTypeOf(vl.mType);
|
||||||
|
ins->mSrc[0].mTemp = vl.mTemp;
|
||||||
|
ins->mDst.mType = IT_POINTER;
|
||||||
|
ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
|
||||||
|
block->Append(ins);
|
||||||
|
return ExValue(exp->mDecType, ins->mDst.mTemp, 0);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TK_DELETE:
|
||||||
|
{
|
||||||
|
vl = Dereference(proc, exp, block, vl, 0);
|
||||||
|
|
||||||
|
ins->mCode = IC_FREE;
|
||||||
|
ins->mSrc[0].mType = IT_POINTER;
|
||||||
|
ins->mSrc[0].mTemp = vl.mTemp;
|
||||||
|
block->Append(ins);
|
||||||
|
return ExValue(TheConstVoidTypeDeclaration, -1);
|
||||||
|
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ins->mSrc[0].mType = InterTypeOf(vl.mType);
|
ins->mSrc[0].mType = InterTypeOf(vl.mType);
|
||||||
|
@ -2611,6 +2635,42 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
|
|
||||||
return ExValue(TheFloatTypeDeclaration, ins->mDst.mTemp);
|
return ExValue(TheFloatTypeDeclaration, ins->mDst.mTemp);
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(iname->mString, "malloc"))
|
||||||
|
{
|
||||||
|
vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper);
|
||||||
|
vr = Dereference(proc, exp, block, vr);
|
||||||
|
|
||||||
|
if (decf->mBase->mParams->CanAssign(vr.mType))
|
||||||
|
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
|
||||||
|
vr = CoerceType(proc, exp, block, vr, decf->mBase->mParams);
|
||||||
|
|
||||||
|
InterInstruction* ins = new InterInstruction(exp->mLocation, IC_MALLOC);
|
||||||
|
ins->mSrc[0].mType = IT_INT16;
|
||||||
|
ins->mSrc[0].mTemp = vr.mTemp;
|
||||||
|
ins->mNumOperands = 1;
|
||||||
|
ins->mDst.mType = IT_POINTER;
|
||||||
|
ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
|
||||||
|
block->Append(ins);
|
||||||
|
|
||||||
|
return ExValue(TheVoidPointerTypeDeclaration, ins->mDst.mTemp);
|
||||||
|
}
|
||||||
|
else if (!strcmp(iname->mString, "free"))
|
||||||
|
{
|
||||||
|
vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper);
|
||||||
|
vr = Dereference(proc, exp, block, vr);
|
||||||
|
|
||||||
|
if (decf->mBase->mParams->CanAssign(vr.mType))
|
||||||
|
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
|
||||||
|
vr = CoerceType(proc, exp, block, vr, decf->mBase->mParams);
|
||||||
|
|
||||||
|
InterInstruction* ins = new InterInstruction(exp->mLocation, IC_FREE);
|
||||||
|
ins->mSrc[0].mType = IT_POINTER;
|
||||||
|
ins->mSrc[0].mTemp = vr.mTemp;
|
||||||
|
ins->mNumOperands = 1;
|
||||||
|
block->Append(ins);
|
||||||
|
|
||||||
|
return ExValue(TheVoidTypeDeclaration, 0);
|
||||||
|
}
|
||||||
else if (!strcmp(iname->mString, "strcpy"))
|
else if (!strcmp(iname->mString, "strcpy"))
|
||||||
{
|
{
|
||||||
if (exp->mRight->mType == EX_LIST)
|
if (exp->mRight->mType == EX_LIST)
|
||||||
|
|
|
@ -489,8 +489,8 @@ void Linker::Link(void)
|
||||||
|
|
||||||
if (lsec->mType == LST_HEAP)
|
if (lsec->mType == LST_HEAP)
|
||||||
{
|
{
|
||||||
lsec->mStart = lrgn->mStart + lrgn->mUsed;
|
lsec->mStart = (lrgn->mStart + lrgn->mUsed + 3) & ~3;
|
||||||
lsec->mEnd = lrgn->mEnd;
|
lsec->mEnd = lrgn->mEnd & ~3;
|
||||||
|
|
||||||
if (lsec->mStart + lsec->mSize > lsec->mEnd)
|
if (lsec->mStart + lsec->mSize > lsec->mEnd)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7346,6 +7346,54 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeCodeBasicBlock::CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc)
|
||||||
|
{
|
||||||
|
if (ins->mSrc[0].mTemp < 0)
|
||||||
|
{
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("malloc")));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER));
|
||||||
|
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc)
|
||||||
|
{
|
||||||
|
if (ins->mSrc[0].mTemp < 0)
|
||||||
|
{
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("free")));
|
||||||
|
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NativeCodeBasicBlock* NativeCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc)
|
NativeCodeBasicBlock* NativeCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc)
|
||||||
{
|
{
|
||||||
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||||
|
@ -17338,10 +17386,13 @@ bool NativeCodeBasicBlock::CombineZPPair(int at, int r0, int r1, bool use0, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ins.ChangesZeroPage(r0))
|
else
|
||||||
valid0 = false;
|
{
|
||||||
else if (ins.ChangesZeroPage(r1))
|
if (ins.ChangesZeroPage(r0))
|
||||||
valid1 = false;
|
valid0 = false;
|
||||||
|
if (ins.ChangesZeroPage(r1))
|
||||||
|
valid1 = false;
|
||||||
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -40093,7 +40144,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
mInterProc = proc;
|
mInterProc = proc;
|
||||||
|
|
||||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "strlen");
|
CheckFunc = !strcmp(mInterProc->mIdent->mString, "heapcheck");
|
||||||
|
|
||||||
int nblocks = proc->mBlocks.Size();
|
int nblocks = proc->mBlocks.Size();
|
||||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||||
|
@ -40881,7 +40932,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (step == 5)
|
if (step == 5 && cnt < 10)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (mEntryBlock->RemoveDoubleZPStore())
|
if (mEntryBlock->RemoveDoubleZPStore())
|
||||||
|
@ -41703,6 +41754,14 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
|
||||||
case IC_STRCPY:
|
case IC_STRCPY:
|
||||||
block = block->StrcpyValue(iproc, ins, this);
|
block = block->StrcpyValue(iproc, ins, this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IC_MALLOC:
|
||||||
|
block->CallMalloc(iproc, ins, this);
|
||||||
|
break;
|
||||||
|
case IC_FREE:
|
||||||
|
block->CallFree(iproc, ins, this);
|
||||||
|
break;
|
||||||
|
|
||||||
case IC_LOAD_TEMPORARY:
|
case IC_LOAD_TEMPORARY:
|
||||||
{
|
{
|
||||||
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
||||||
|
|
|
@ -336,6 +336,9 @@ public:
|
||||||
NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc);
|
NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc);
|
||||||
void AddAsrSignedByte(InterCodeProcedure* proc, const InterInstruction* ains, const InterInstruction* sins);
|
void AddAsrSignedByte(InterCodeProcedure* proc, const InterInstruction* ains, const InterInstruction* sins);
|
||||||
|
|
||||||
|
void CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc);
|
||||||
|
void CallFree(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc);
|
||||||
|
|
||||||
void LoadByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
|
void LoadByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
|
||||||
void StoreByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
|
void StoreByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
|
||||||
|
|
||||||
|
|
|
@ -4470,7 +4470,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
|
||||||
{
|
{
|
||||||
if (mScanner->mToken == TK_SUB || mScanner->mToken == TK_BINARY_NOT || mScanner->mToken == TK_LOGICAL_NOT ||
|
if (mScanner->mToken == TK_SUB || mScanner->mToken == TK_BINARY_NOT || mScanner->mToken == TK_LOGICAL_NOT ||
|
||||||
mScanner->mToken == TK_MUL || mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC || mScanner->mToken == TK_BINARY_AND ||
|
mScanner->mToken == TK_MUL || mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC || mScanner->mToken == TK_BINARY_AND ||
|
||||||
mScanner->mToken == TK_BANKOF)
|
mScanner->mToken == TK_BANKOF || mScanner->mToken == TK_NEW || mScanner->mToken == TK_DELETE)
|
||||||
{
|
{
|
||||||
Expression* nexp;
|
Expression* nexp;
|
||||||
if (mScanner->mToken == TK_LOGICAL_NOT)
|
if (mScanner->mToken == TK_LOGICAL_NOT)
|
||||||
|
@ -4487,6 +4487,127 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
|
||||||
nexp->mLeft = ParsePrefixExpression(false);;
|
nexp->mLeft = ParsePrefixExpression(false);;
|
||||||
nexp->mDecType = nexp->mLeft->mDecType;
|
nexp->mDecType = nexp->mLeft->mDecType;
|
||||||
}
|
}
|
||||||
|
else if (mScanner->mToken == TK_NEW)
|
||||||
|
{
|
||||||
|
nexp = new Expression(mScanner->mLocation, EX_PREFIX);
|
||||||
|
nexp->mToken = TK_NEW;
|
||||||
|
mScanner->NextToken();
|
||||||
|
Declaration * dec = ParseBaseTypeDeclaration(0);
|
||||||
|
|
||||||
|
Declaration* sconst = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
|
||||||
|
sconst->mBase = TheUnsignedIntTypeDeclaration;
|
||||||
|
sconst->mInteger = dec->mSize;
|
||||||
|
|
||||||
|
Expression* sexp = new Expression(mScanner->mLocation, EX_CONSTANT);
|
||||||
|
sexp->mDecValue = sconst;
|
||||||
|
sexp->mDecType = TheUnsignedIntTypeDeclaration;
|
||||||
|
|
||||||
|
nexp->mLeft = sexp;
|
||||||
|
nexp->mDecType = dec->BuildPointer(mScanner->mLocation);
|
||||||
|
|
||||||
|
if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor)
|
||||||
|
{
|
||||||
|
Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE);
|
||||||
|
vdec->mVarIndex = mLocalIndex++;
|
||||||
|
vdec->mBase = nexp->mDecType;
|
||||||
|
vdec->mSize = 2;
|
||||||
|
|
||||||
|
Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE);
|
||||||
|
vexp->mDecType = vdec->mBase;
|
||||||
|
vexp->mDecValue = vdec;
|
||||||
|
|
||||||
|
Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION);
|
||||||
|
iexp->mToken = TK_ASSIGN;
|
||||||
|
iexp->mLeft = vexp;
|
||||||
|
iexp->mRight = nexp;
|
||||||
|
iexp->mDecType = nexp->mDecType;
|
||||||
|
|
||||||
|
Declaration* mdec = dec->mDefaultConstructor;
|
||||||
|
Expression* pexp = iexp;
|
||||||
|
|
||||||
|
if (ConsumeTokenIf(TK_OPEN_PARENTHESIS))
|
||||||
|
{
|
||||||
|
if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS))
|
||||||
|
{
|
||||||
|
pexp = ParseListExpression();
|
||||||
|
|
||||||
|
mdec = dec->mScope->Lookup(dec->mIdent);
|
||||||
|
|
||||||
|
ConsumeToken(TK_CLOSE_PARENTHESIS);
|
||||||
|
|
||||||
|
Expression* lexp = new Expression(mScanner->mLocation, EX_LIST);
|
||||||
|
lexp->mLeft = iexp;
|
||||||
|
lexp->mRight = pexp;
|
||||||
|
pexp = lexp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
|
||||||
|
cexp->mDecValue = mdec;
|
||||||
|
cexp->mDecType = cexp->mDecValue->mBase;
|
||||||
|
|
||||||
|
Expression* dexp = new Expression(mScanner->mLocation, EX_CALL);
|
||||||
|
dexp->mLeft = cexp;
|
||||||
|
dexp->mRight = pexp;
|
||||||
|
|
||||||
|
ResolveOverloadCall(cexp, pexp);
|
||||||
|
|
||||||
|
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||||
|
|
||||||
|
sexp->mLeft = dexp;
|
||||||
|
sexp->mRight = vexp;
|
||||||
|
|
||||||
|
nexp = sexp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mScanner->mToken == TK_DELETE)
|
||||||
|
{
|
||||||
|
nexp = new Expression(mScanner->mLocation, EX_PREFIX);
|
||||||
|
nexp->mToken = TK_DELETE;
|
||||||
|
mScanner->NextToken();
|
||||||
|
nexp->mLeft = ParsePrefixExpression(false);
|
||||||
|
nexp->mDecType = TheVoidTypeDeclaration;
|
||||||
|
if (nexp->mLeft->mDecType->mType == DT_TYPE_POINTER)
|
||||||
|
{
|
||||||
|
Declaration* dec = nexp->mLeft->mDecType->mBase;
|
||||||
|
if (dec->mDestructor)
|
||||||
|
{
|
||||||
|
Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE);
|
||||||
|
vdec->mVarIndex = mLocalIndex++;
|
||||||
|
vdec->mBase = nexp->mLeft->mDecType;
|
||||||
|
vdec->mSize = 2;
|
||||||
|
|
||||||
|
Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE);
|
||||||
|
vexp->mDecType = vdec->mBase;
|
||||||
|
vexp->mDecValue = vdec;
|
||||||
|
|
||||||
|
Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION);
|
||||||
|
iexp->mToken = TK_ASSIGN;
|
||||||
|
iexp->mLeft = vexp;
|
||||||
|
iexp->mRight = nexp->mLeft;
|
||||||
|
iexp->mDecType = nexp->mLeft->mDecType;
|
||||||
|
|
||||||
|
Declaration* mdec = dec->mDestructor;
|
||||||
|
|
||||||
|
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
|
||||||
|
cexp->mDecValue = mdec;
|
||||||
|
cexp->mDecType = cexp->mDecValue->mBase;
|
||||||
|
|
||||||
|
Expression* dexp = new Expression(mScanner->mLocation, EX_CALL);
|
||||||
|
dexp->mLeft = cexp;
|
||||||
|
dexp->mRight = iexp;
|
||||||
|
|
||||||
|
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||||
|
|
||||||
|
sexp->mLeft = dexp;
|
||||||
|
sexp->mRight = nexp;
|
||||||
|
|
||||||
|
nexp->mLeft = iexp;
|
||||||
|
|
||||||
|
nexp = sexp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nexp = new Expression(mScanner->mLocation, EX_PREFIX);
|
nexp = new Expression(mScanner->mLocation, EX_PREFIX);
|
||||||
|
|
|
@ -158,6 +158,8 @@ const char* TokenNames[] =
|
||||||
"'public'",
|
"'public'",
|
||||||
"'protected'",
|
"'protected'",
|
||||||
"'private'",
|
"'private'",
|
||||||
|
"'new'",
|
||||||
|
"'delete'",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1406,6 +1408,10 @@ void Scanner::NextRawToken(void)
|
||||||
mToken = TK_PROTECTED;
|
mToken = TK_PROTECTED;
|
||||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "private"))
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "private"))
|
||||||
mToken = TK_PRIVATE;
|
mToken = TK_PRIVATE;
|
||||||
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "new"))
|
||||||
|
mToken = TK_NEW;
|
||||||
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "delete"))
|
||||||
|
mToken = TK_DELETE;
|
||||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator"))
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator"))
|
||||||
{
|
{
|
||||||
NextRawToken();
|
NextRawToken();
|
||||||
|
|
|
@ -157,6 +157,8 @@ enum Token
|
||||||
TK_PUBLIC,
|
TK_PUBLIC,
|
||||||
TK_PROTECTED,
|
TK_PROTECTED,
|
||||||
TK_PRIVATE,
|
TK_PRIVATE,
|
||||||
|
TK_NEW,
|
||||||
|
TK_DELETE,
|
||||||
|
|
||||||
NUM_TOKENS
|
NUM_TOKENS
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue