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++)
|
||||
{
|
||||
if (p[i] != n)
|
||||
{
|
||||
printf("MemError %d at %d:%d != %d\n", k, i, n, p[i]);
|
||||
exit(-2);
|
||||
}
|
||||
}
|
||||
free(memp[n]);
|
||||
|
||||
s = rand() % 100 + 3;
|
||||
mems[n] = s;
|
||||
memp[n] = malloc(s);
|
||||
if (!memp[n])
|
||||
exit(-3);
|
||||
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)
|
||||
|
||||
|
||||
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_LOOP_U8,
|
||||
BC_UNUSED_2,
|
||||
BC_UNUSED_3,
|
||||
BC_MALLOC,
|
||||
BC_FREE,
|
||||
BC_UNUSED_4,
|
||||
BC_UNUSED_5,
|
||||
BC_UNUSED_6,
|
||||
|
|
|
@ -524,6 +524,7 @@ void exit(int status)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct Heap {
|
||||
unsigned int size;
|
||||
Heap * next;
|
||||
|
@ -636,6 +637,7 @@ void free(void * ptr)
|
|||
freeHeap->next = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void * calloc(int num, int size)
|
||||
{
|
||||
|
|
|
@ -47,6 +47,10 @@ unsigned int rand(void);
|
|||
|
||||
void srand(unsigned int seed);
|
||||
|
||||
#pragma intrinsic(malloc)
|
||||
|
||||
#pragma intrinsic(free)
|
||||
|
||||
#pragma compile("stdlib.c")
|
||||
|
||||
#endif
|
||||
|
|
|
@ -142,8 +142,8 @@ static const char* ByteCodeNames[] = {
|
|||
"BRANCHF_LE",
|
||||
|
||||
"LOOP_U8",
|
||||
nullptr,
|
||||
nullptr,
|
||||
"MALLOC",
|
||||
"FREE",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
|
@ -565,6 +565,11 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used)
|
|||
used = 0;
|
||||
break;
|
||||
|
||||
case BC_MALLOC:
|
||||
case BC_FREE:
|
||||
used = 0x0000ffff;
|
||||
break;
|
||||
|
||||
case BC_BINOP_ADDA_16:
|
||||
used |= 0x0000ffff;
|
||||
break;
|
||||
|
@ -779,6 +784,8 @@ bool ByteCodeInstruction::UsesRegister(uint32 reg) const
|
|||
return true;
|
||||
if (mCode == BC_BINOP_ADDA_16)
|
||||
return true;
|
||||
if (mCode == BC_MALLOC || mCode == BC_FREE)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (reg == BC_REG_ADDR)
|
||||
|
@ -851,6 +858,8 @@ bool ByteCodeInstruction::ChangesRegister(uint32 reg) const
|
|||
return true;
|
||||
if (mCode == BC_LOOP_U8)
|
||||
return true;
|
||||
if (mCode == BC_MALLOC || mCode == BC_FREE)
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
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 ||
|
||||
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);
|
||||
break;
|
||||
|
||||
case BC_MALLOC:
|
||||
case BC_FREE:
|
||||
case BC_CALL_ADDR:
|
||||
block->PutCode(generator, mCode);
|
||||
break;
|
||||
|
@ -1578,6 +1591,49 @@ void ByteCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstru
|
|||
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)
|
||||
{
|
||||
if (ins->mSrc[0].mType == IT_FLOAT)
|
||||
|
@ -4259,6 +4315,12 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p
|
|||
case IC_STRCPY:
|
||||
StrcpyValue(iproc, ins);
|
||||
break;
|
||||
case IC_MALLOC:
|
||||
CallMalloc(iproc, ins);
|
||||
break;
|
||||
case IC_FREE:
|
||||
CallFree(iproc, ins);
|
||||
break;
|
||||
case IC_LOAD_TEMPORARY:
|
||||
{
|
||||
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
||||
|
|
|
@ -143,8 +143,8 @@ enum ByteCode
|
|||
BC_BRANCHF_LE,
|
||||
|
||||
BC_LOOP_U8,
|
||||
BC_UNUSED_2,
|
||||
BC_UNUSED_3,
|
||||
BC_MALLOC,
|
||||
BC_FREE,
|
||||
BC_UNUSED_4,
|
||||
BC_UNUSED_5,
|
||||
BC_UNUSED_6,
|
||||
|
@ -283,6 +283,8 @@ public:
|
|||
void FloatConstToWork(double val);
|
||||
void CopyValue(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 StoreDirectValue(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("divu32"));
|
||||
RegisterRuntime(loc, Ident::Unique("modu32"));
|
||||
|
||||
RegisterRuntime(loc, Ident::Unique("malloc"));
|
||||
RegisterRuntime(loc, Ident::Unique("free"));
|
||||
}
|
||||
|
||||
// Register extended byte code functions
|
||||
|
|
|
@ -187,7 +187,7 @@ enum ExpressionType
|
|||
EX_ASSUME,
|
||||
EX_BANKOF,
|
||||
EX_CONSTRUCT,
|
||||
EX_CLEANUP,
|
||||
EX_CLEANUP
|
||||
};
|
||||
|
||||
class Expression
|
||||
|
|
|
@ -476,6 +476,13 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank
|
|||
fprintf(file, "CNVFS\tACCU");
|
||||
break;
|
||||
|
||||
case BC_MALLOC:
|
||||
fprintf(file, "MALLOC\tACCU");
|
||||
break;
|
||||
case BC_FREE:
|
||||
fprintf(file, "FREE\tACCU");
|
||||
break;
|
||||
|
||||
case BC_JUMPS:
|
||||
fprintf(file, "JUMP\t$%04X", start + i + 1 + int8(memory[start + i + 0]));
|
||||
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 ||
|
||||
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;
|
||||
|
||||
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 (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;
|
||||
|
||||
if (ins1->mCode == IC_LOAD || ins1->mCode == IC_STORE || ins1->mCode == IC_COPY || ins1->mCode == IC_STRCPY)
|
||||
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
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
if (code == IC_RETURN || code == IC_RETURN_STRUCT || code == IC_RETURN_VALUE)
|
||||
return false;
|
||||
|
@ -2762,13 +2779,44 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
|
|||
case IC_BRANCH:
|
||||
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];
|
||||
if (IsIntegerType(tins->mConst.mType) || tins->mConst.mType == IT_BOOL)
|
||||
{
|
||||
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.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;
|
||||
case IC_PUSH_FRAME:
|
||||
case IC_POP_FRAME:
|
||||
|
@ -4214,6 +4262,16 @@ void InterInstruction::Disassemble(FILE* file)
|
|||
else
|
||||
fprintf(file, "COPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]);
|
||||
break;
|
||||
|
||||
case IC_MALLOC:
|
||||
assert(mNumOperands == 1);
|
||||
fprintf(file, "MALLOC");
|
||||
break;
|
||||
case IC_FREE:
|
||||
assert(mNumOperands == 1);
|
||||
fprintf(file, "FREE");
|
||||
break;
|
||||
|
||||
case IC_STRCPY:
|
||||
fprintf(file, "STRCPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]);
|
||||
break;
|
||||
|
@ -7696,7 +7754,7 @@ bool InterCodeBasicBlock::CalculateSingleAssignmentTemps(FastNumberSet& tassigne
|
|||
bool valid = j == ins->mNumOperands;
|
||||
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;
|
||||
else if (ins->mCode == IC_LOAD)
|
||||
{
|
||||
|
@ -16035,7 +16093,7 @@ void InterCodeProcedure::Close(void)
|
|||
{
|
||||
GrowingTypeArray tstack(IT_NONE);
|
||||
|
||||
CheckFunc = !strcmp(mIdent->mString, "test");
|
||||
CheckFunc = !strcmp(mIdent->mString, "main");
|
||||
|
||||
mEntryBlock = mBlocks[0];
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ enum InterCode
|
|||
IC_LEA,
|
||||
IC_COPY,
|
||||
IC_STRCPY,
|
||||
IC_MALLOC,
|
||||
IC_FREE,
|
||||
IC_TYPECAST,
|
||||
IC_CONSTANT,
|
||||
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");
|
||||
} 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);
|
||||
|
@ -2611,6 +2635,42 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
|
||||
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"))
|
||||
{
|
||||
if (exp->mRight->mType == EX_LIST)
|
||||
|
|
|
@ -489,8 +489,8 @@ void Linker::Link(void)
|
|||
|
||||
if (lsec->mType == LST_HEAP)
|
||||
{
|
||||
lsec->mStart = lrgn->mStart + lrgn->mUsed;
|
||||
lsec->mEnd = lrgn->mEnd;
|
||||
lsec->mStart = (lrgn->mStart + lrgn->mUsed + 3) & ~3;
|
||||
lsec->mEnd = lrgn->mEnd & ~3;
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
if (ins.ChangesZeroPage(r0))
|
||||
valid0 = false;
|
||||
else if (ins.ChangesZeroPage(r1))
|
||||
if (ins.ChangesZeroPage(r1))
|
||||
valid1 = false;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
@ -40093,7 +40144,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
{
|
||||
mInterProc = proc;
|
||||
|
||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "strlen");
|
||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "heapcheck");
|
||||
|
||||
int nblocks = proc->mBlocks.Size();
|
||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||
|
@ -40881,7 +40932,7 @@ void NativeCodeProcedure::Optimize(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (step == 5)
|
||||
if (step == 5 && cnt < 10)
|
||||
{
|
||||
ResetVisited();
|
||||
if (mEntryBlock->RemoveDoubleZPStore())
|
||||
|
@ -41703,6 +41754,14 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
|
|||
case IC_STRCPY:
|
||||
block = block->StrcpyValue(iproc, ins, this);
|
||||
break;
|
||||
|
||||
case IC_MALLOC:
|
||||
block->CallMalloc(iproc, ins, this);
|
||||
break;
|
||||
case IC_FREE:
|
||||
block->CallFree(iproc, ins, this);
|
||||
break;
|
||||
|
||||
case IC_LOAD_TEMPORARY:
|
||||
{
|
||||
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
||||
|
|
|
@ -336,6 +336,9 @@ public:
|
|||
NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc);
|
||||
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 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 ||
|
||||
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;
|
||||
if (mScanner->mToken == TK_LOGICAL_NOT)
|
||||
|
@ -4487,6 +4487,127 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
|
|||
nexp->mLeft = ParsePrefixExpression(false);;
|
||||
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
|
||||
{
|
||||
nexp = new Expression(mScanner->mLocation, EX_PREFIX);
|
||||
|
|
|
@ -158,6 +158,8 @@ const char* TokenNames[] =
|
|||
"'public'",
|
||||
"'protected'",
|
||||
"'private'",
|
||||
"'new'",
|
||||
"'delete'",
|
||||
};
|
||||
|
||||
|
||||
|
@ -1406,6 +1408,10 @@ void Scanner::NextRawToken(void)
|
|||
mToken = TK_PROTECTED;
|
||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "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"))
|
||||
{
|
||||
NextRawToken();
|
||||
|
|
|
@ -157,6 +157,8 @@ enum Token
|
|||
TK_PUBLIC,
|
||||
TK_PROTECTED,
|
||||
TK_PRIVATE,
|
||||
TK_NEW,
|
||||
TK_DELETE,
|
||||
|
||||
NUM_TOKENS
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue