1
0
mirror of https://github.com/ksherlock/x65.git synced 2024-06-11 01:29:26 +00:00

Label pools are 32 bit, added sizeof directive for structs, destructor for Symbol Stacks

This commit is contained in:
Carl-Henrik Skårstedt 2020-01-10 20:52:02 -08:00
parent 4b7e679b20
commit eb3df4de88
2 changed files with 57 additions and 19 deletions

View File

@ -1,6 +1,6 @@
; TEST CODE FROM EXOMIZER ; TEST CODE FROM EXOMIZER
cpu 65816
.org $2000 .org $52000
.REPT 7 .REPT 7
dc.b rept dc.b rept
@ -19,7 +19,7 @@ eval Pull original: test_stack
eval Checking symbol is not const (0): .const(test_stack) eval Checking symbol is not const (0): .const(test_stack)
const ConstAddress = $1000 const ConstAddress = $1000
eval Checking symbol is const (0): .const(ConstAddress) eval Checking symbol is const (1): .const(ConstAddress)
eval This should be blank (1): .blank() eval This should be blank (1): .blank()
eval This should be blank (1): .blank({}) eval This should be blank (1): .blank({})
@ -33,6 +33,13 @@ eval Checking ifconst with non-const symbol, should not print:
eval Checking ifconst with const symbol, this should print: eval Checking ifconst with const symbol, this should print:
.endif .endif
struct MyStruct {
word addr
byte value
}
eval Size of MyStruct (3): .sizeof(MyStruct)
zp_len_lo = $a7 zp_len_lo = $a7
zp_len_hi = $a8 zp_len_hi = $a8

63
x65.cpp
View File

@ -323,6 +323,7 @@ enum EvalFuncs {
EF_REFERENCED, // REFERENCED(label) 1 if label has been referenced in this file EF_REFERENCED, // REFERENCED(label) 1 if label has been referenced in this file
EF_BLANK, // BLANK() 1 if the contents within the parenthesis is empty EF_BLANK, // BLANK() 1 if the contents within the parenthesis is empty
EF_CONST, // CONST(label) 1 if label is a const label EF_CONST, // CONST(label) 1 if label is a const label
EF_SIZEOF, // SIZEOF(struct) returns size of structs
EF_SIN, // SIN(index, period, amplitude) EF_SIN, // SIN(index, period, amplitude)
}; };
@ -1029,6 +1030,7 @@ DirectiveName aDirectiveNames[] {
{ "DUMMY", AD_DUMMY }, { "DUMMY", AD_DUMMY },
{ "DUMMY_END", AD_DUMMY_END }, { "DUMMY_END", AD_DUMMY_END },
{ "DS", AD_DS }, // Define space { "DS", AD_DS }, // Define space
{ "RES", AD_DS }, // Reserve space
{ "SCOPE", AD_SCOPE }, // SCOPE: Begin ca65 style scope { "SCOPE", AD_SCOPE }, // SCOPE: Begin ca65 style scope
{ "ENDSCOPE", AD_ENDSCOPE },// ENDSCOPR: End ca65 style scope { "ENDSCOPE", AD_ENDSCOPE },// ENDSCOPR: End ca65 style scope
{ "PUSH", AD_PUSH }, { "PUSH", AD_PUSH },
@ -1084,6 +1086,7 @@ EvalFuncNames aEvalFunctions[] = {
{ "REFERENCED", EF_REFERENCED }, // REFERENCED(label) 1 if label has been referenced in this file { "REFERENCED", EF_REFERENCED }, // REFERENCED(label) 1 if label has been referenced in this file
{ "BLANK", EF_BLANK }, // BLANK() 1 if the contents within the parenthesis is empty { "BLANK", EF_BLANK }, // BLANK() 1 if the contents within the parenthesis is empty
{ "CONST", EF_CONST }, // CONST(label) 1 if label is a const label { "CONST", EF_CONST }, // CONST(label) 1 if label is a const label
{ "SIZEOF", EF_SIZEOF}, // SIZEOF(struct) returns size of structs
{ "TRIGSIN", EF_SIN }, // TRIGSIN(index, period, amplitude) { "TRIGSIN", EF_SIN }, // TRIGSIN(index, period, amplitude)
}; };
@ -1617,10 +1620,10 @@ typedef struct sLabelPool {
strref pool_name; strref pool_name;
int16_t numRanges; // normally 1 range, support multiple for ease of use int16_t numRanges; // normally 1 range, support multiple for ease of use
int16_t depth; // Required for scope closure cleanup int16_t depth; // Required for scope closure cleanup
uint16_t start; uint32_t start;
uint16_t end; uint32_t end;
uint16_t scopeUsed[MAX_SCOPE_DEPTH][2]; // last address assigned + scope depth uint32_t scopeUsed[MAX_SCOPE_DEPTH][2]; // last address assigned + scope depth
StatusCode Reserve(uint16_t numBytes, uint16_t &ret_addr, uint16_t scope); StatusCode Reserve(uint32_t numBytes, uint32_t &ret_addr, uint16_t scope);
void ExitScope(uint16_t scope); void ExitScope(uint16_t scope);
} LabelPool; } LabelPool;
@ -1711,6 +1714,7 @@ public:
StatusCode PullSymbol(Label* symbol); StatusCode PullSymbol(Label* symbol);
void PushSymbol(StringSymbol* string); void PushSymbol(StringSymbol* string);
StatusCode PullSymbol(StringSymbol* string); StatusCode PullSymbol(StringSymbol* string);
~SymbolStackTable();
}; };
// The state of the assembler // The state of the assembler
@ -2017,6 +2021,17 @@ StatusCode SymbolStackTable::PullSymbol(StringSymbol* string)
return STATUS_OK; return STATUS_OK;
} }
SymbolStackTable::~SymbolStackTable()
{
for (size_t i = 0; i < size; ++i) {
if (keys[i] && values[i]) {
delete values[i];
values[i] = nullptr;
keys[i] = 0;
}
}
}
// Clean up work allocations // Clean up work allocations
@ -3474,7 +3489,7 @@ bool Asm::EvalFunction(strref function, strref& expression, int &value)
case EF_REFERENCED: case EF_REFERENCED:
expression = expRet; expression = expRet;
if (Label* label = GetLabel(params, true)) { value = label->referenced; return true; } if (Label* label = GetLabel(params, true)) { value = label->referenced; return true; }
return false; return true;
case EF_BLANK: case EF_BLANK:
expression = expRet; expression = expRet;
if (params.get_first() == '{') { params = params.scoped_block_comment_skip(); } if (params.get_first() == '{') { params = params.scoped_block_comment_skip(); }
@ -3484,9 +3499,25 @@ bool Asm::EvalFunction(strref function, strref& expression, int &value)
case EF_CONST: case EF_CONST:
expression = expRet; expression = expRet;
if (Label* label = GetLabel(params, true)) { if (Label* label = GetLabel(params, true)) {
return label->constant; value = label->constant ? 1 : 0;
} }
return false; return true;
case EF_SIZEOF:
{
expression = expRet;
uint32_t hash = params.fnv1a();
uint32_t index = FindLabelIndex(hash, labelStructs.getKeys(), labelStructs.count());
value = 0;
while (index < labelStructs.count() && labelStructs.getKey(index) == hash) {
if (params.same_str_case(labelStructs.getValue(index).name)) {
value = (labelStructs.getValues() + index)->size;
break;
}
++index;
}
return true;
}
case EF_SIN: case EF_SIN:
expression = expRet; expression = expRet;
value = 0; // TODO: implement trigsin value = 0; // TODO: implement trigsin
@ -4299,7 +4330,7 @@ StatusCode Asm::AddLabelPool(strref name, strref args) {
// check that there is at least one valid address // check that there is at least one valid address
int ranges = 0; int ranges = 0;
int num32 = 0; int num32 = 0;
uint16_t aRng[256]; uint32_t aRng[256];
struct EvalContext etx; struct EvalContext etx;
SetEvalCtxDefaults(etx); SetEvalCtxDefaults(etx);
while (strref arg = args.split_token_trim(',')) { while (strref arg = args.split_token_trim(',')) {
@ -4314,8 +4345,8 @@ StatusCode Asm::AddLabelPool(strref name, strref args) {
if (addr1<=addr0||addr0<0) { if (addr1<=addr0||addr0<0) {
return ERROR_POOL_RANGE_EXPRESSION_EVAL; return ERROR_POOL_RANGE_EXPRESSION_EVAL;
} }
aRng[ranges++] = (uint16_t)addr0; aRng[ranges++] = (uint32_t)addr0;
aRng[ranges++] = (uint16_t)addr1; aRng[ranges++] = (uint32_t)addr1;
num32 += (addr1-addr0+15)>>4; num32 += (addr1-addr0+15)>>4;
if (ranges>2||num32>((MAX_POOL_BYTES+15)>>4)) { if (ranges>2||num32>((MAX_POOL_BYTES+15)>>4)) {
return ERROR_POOL_RANGE_EXPRESSION_EVAL; return ERROR_POOL_RANGE_EXPRESSION_EVAL;
@ -4345,10 +4376,10 @@ StatusCode Asm::AssignPoolLabel(LabelPool &pool, strref label) {
strref size = label; strref size = label;
label = size.split_label(); label = size.split_label();
if (strref::is_number(size.get_first())) { if (strref::is_number(size.get_first())) {
uint16_t bytes = (uint16_t)size.atoi(); uint32_t bytes = (uint32_t)size.atoi();
if (!bytes) { return ERROR_POOL_RANGE_EXPRESSION_EVAL; } if (!bytes) { return ERROR_POOL_RANGE_EXPRESSION_EVAL; }
if (!GetLabelPool(label)) { if (!GetLabelPool(label)) {
uint16_t addr; uint32_t addr;
StatusCode error = pool.Reserve(bytes, addr, (uint16_t)brace_depth); StatusCode error = pool.Reserve(bytes, addr, (uint16_t)brace_depth);
if( error == STATUS_OK ) { if( error == STATUS_OK ) {
// permanently remove this chunk from the parent pool // permanently remove this chunk from the parent pool
@ -4370,13 +4401,13 @@ StatusCode Asm::AssignPoolLabel(LabelPool &pool, strref label) {
return ERROR_POOL_RANGE_EXPRESSION_EVAL; return ERROR_POOL_RANGE_EXPRESSION_EVAL;
} }
strref type = label; strref type = label;
uint16_t bytes = 1; uint32_t bytes = 1;
int sz = label.find_at( '.', 1 ); int sz = label.find_at( '.', 1 );
if (sz > 0) { if (sz > 0) {
label = type.split( sz ); label = type.split( sz );
++type; ++type;
if (strref::is_number(type.get_first())) { if (strref::is_number(type.get_first())) {
bytes = (uint16_t)type.atoi(); bytes = (uint32_t)type.atoi();
} else { } else {
switch (strref::tolower(type.get_first())) { switch (strref::tolower(type.get_first())) {
case 'l': bytes = 4; break; case 'l': bytes = 4; break;
@ -4387,7 +4418,7 @@ StatusCode Asm::AssignPoolLabel(LabelPool &pool, strref label) {
} }
} }
if (GetLabel(label)) { return ERROR_POOL_LABEL_ALREADY_DEFINED; } if (GetLabel(label)) { return ERROR_POOL_LABEL_ALREADY_DEFINED; }
uint16_t addr; uint32_t addr;
StatusCode error = pool.Reserve(bytes, addr, (uint16_t)brace_depth); StatusCode error = pool.Reserve(bytes, addr, (uint16_t)brace_depth);
if (error!=STATUS_OK) { return error; } if (error!=STATUS_OK) { return error; }
Label *pLabel = AddLabel(label.fnv1a()); Label *pLabel = AddLabel(label.fnv1a());
@ -4412,7 +4443,7 @@ StatusCode Asm::AssignPoolLabel(LabelPool &pool, strref label) {
} }
// Request a label from a pool // Request a label from a pool
StatusCode sLabelPool::Reserve(uint16_t numBytes, uint16_t &ret_addr, uint16_t scope) { StatusCode sLabelPool::Reserve(uint32_t numBytes, uint32_t &ret_addr, uint16_t scope) {
if (numBytes>(end-start)||depth==MAX_SCOPE_DEPTH) { return ERROR_OUT_OF_LABELS_IN_POOL; } if (numBytes>(end-start)||depth==MAX_SCOPE_DEPTH) { return ERROR_OUT_OF_LABELS_IN_POOL; }
if (!depth||scope!=scopeUsed[depth-1][1]) { if (!depth||scope!=scopeUsed[depth-1][1]) {
scopeUsed[depth][0] = end; scopeUsed[depth][0] = end;