End of an Era
This commit is contained in:
parent
5c5187f0ff
commit
db08fcbd27
6
Makefile
6
Makefile
@ -8,15 +8,15 @@ DEPS := $(patsubst build/%.o,build/%.d,$(OBJECTS))
|
|||||||
|
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
|
|
||||||
CFLAGS = $(if $(DEBUGA),-DDEBUG=1,) -Wall $(if $(ASAN),-fsanitize=address,) -fno-PIE -no-pie -std=gnu11 $(if $(DEBUG),-O0 -g,-Os -s) -fms-extensions -Isrc -Wno-array-bounds -MMD -MP -flto
|
CFLAGS = $(if $(DEBUGA),-DDEBUG=1,) -Wall $(if $(ASAN),-fsanitize=address,) -fno-PIE -no-pie -std=gnu11 $(if $(DEBUG),-O0 -g,-Os -s) -fms-extensions -Isrc -Wno-array-bounds -MMD -MP -flto -Wno-format-zero-length
|
||||||
|
|
||||||
.PHONY: install clean
|
.PHONY: install clean
|
||||||
|
|
||||||
build/%.o: src/%.c
|
build/%.o: src/%.c
|
||||||
cc -c $(CFLAGS) -o $@ $<
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
ntc: $(OBJECTS)
|
ntc: $(OBJECTS)
|
||||||
cc $(CFLAGS) -o ntc $(OBJECTS)
|
$(CC) $(CFLAGS) -o ntc $(OBJECTS)
|
||||||
|
|
||||||
install: ntc
|
install: ntc
|
||||||
cp ./ntc $(PREFIX)/bin
|
cp ./ntc $(PREFIX)/bin
|
||||||
|
14
README.md
14
README.md
@ -31,7 +31,19 @@ This will be ported into a man page later:
|
|||||||
|
|
||||||
Unknown arguments are ignored.
|
Unknown arguments are ignored.
|
||||||
|
|
||||||
# Example
|
# Example 1
|
||||||
|
|
||||||
|
$ ntc < tests/parsenum.nct > out.asm
|
||||||
|
$ nasm -f elf -o out.o out.asm
|
||||||
|
$ ld -dynamic-linker /lib/ld-linux.so.2 -m elf_i386 -o parsenum out.o -lc
|
||||||
|
$ printf "123" | ./parsenum
|
||||||
|
$ echo $?
|
||||||
|
123
|
||||||
|
$ printf "05" | ./parsenum
|
||||||
|
$ echo $?
|
||||||
|
5
|
||||||
|
|
||||||
|
# Example 2
|
||||||
|
|
||||||
$ ntc < tests/bf.nct > out.asm
|
$ ntc < tests/bf.nct > out.asm
|
||||||
$ nasm -f elf -o out.o out.asm
|
$ nasm -f elf -o out.o out.asm
|
||||||
|
5
examples/Allocator.nct
Normal file
5
examples/Allocator.nct
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
record Allocator {
|
||||||
|
u8* userdata;
|
||||||
|
u8*(u8* userdata, u8* original, u32 size) realloc;
|
||||||
|
}
|
||||||
|
|
8
examples/FarPointer.nct
Normal file
8
examples/FarPointer.nct
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
u8 @far* x;
|
||||||
|
u8 @far* y;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
u8 v = *x;
|
||||||
|
*y = v;
|
||||||
|
x.offset = x.offset + 1;
|
||||||
|
}
|
14
examples/ScalarReplacementOptimization.nct
Normal file
14
examples/ScalarReplacementOptimization.nct
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
record X {
|
||||||
|
u32 a;
|
||||||
|
u32 b;
|
||||||
|
}
|
||||||
|
|
||||||
|
main: u0() -> {
|
||||||
|
X x;
|
||||||
|
x.a = 5;
|
||||||
|
x.b = 6;
|
||||||
|
|
||||||
|
u32 c = x.a + x.b;
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
@ -6,6 +6,7 @@ use ListDLC;
|
|||||||
@instantiate ListDLC_add[u32, u32; 9];
|
@instantiate ListDLC_add[u32, u32; 9];
|
||||||
|
|
||||||
main: u0() -> {
|
main: u0() -> {
|
||||||
|
ListDLC[u32, u32; 9] list;
|
||||||
ListDLC_add[u32, u32; 9](&list, 1234);
|
ListDLC_add[u32, u32; 9](&list, 1234);
|
||||||
ListDLC_add[u32, u32; 9](&list, 4321);
|
ListDLC_add[u32, u32; 9](&list, 4321);
|
||||||
ListDLC_add[u32, u32; 9](&list, 7777);
|
ListDLC_add[u32, u32; 9](&list, 7777);
|
||||||
@ -15,5 +16,3 @@ main: u0() -> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@section(".bss");
|
@section(".bss");
|
||||||
|
|
||||||
ListDLC[u32, u32; 9] list:;
|
|
48
examples/countwords.nct
Normal file
48
examples/countwords.nct
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
@section(".data");
|
||||||
|
|
||||||
|
local u8[33] finalstring: "The amount of words in stdin is: ";
|
||||||
|
|
||||||
|
local u8[4] answer: "0000";
|
||||||
|
|
||||||
|
@section(".text");
|
||||||
|
|
||||||
|
extern s32() getchar;
|
||||||
|
extern s32(s32, u8*, u32) write;
|
||||||
|
|
||||||
|
increase: u0() -> {
|
||||||
|
answer[3] = answer[3] + 1;
|
||||||
|
if(answer[3] > 57) {
|
||||||
|
answer[3] = 48;
|
||||||
|
answer[2] = answer[2] + 1;
|
||||||
|
if(answer[2] > 57) {
|
||||||
|
answer[2] = 48;
|
||||||
|
answer[1] = answer[1] + 1;
|
||||||
|
if(answer[1] > 57) {
|
||||||
|
answer[1] = 48;
|
||||||
|
answer[0] = answer[0] + 1;
|
||||||
|
if(answer[0] > 57) {
|
||||||
|
answer[0] = 48;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
main: u0() -> {
|
||||||
|
loop {
|
||||||
|
s32 c = getchar();
|
||||||
|
if(c == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(c == 32) {
|
||||||
|
increase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write(1, &finalstring, 33);
|
||||||
|
write(1, &answer, 4);
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
@ -1,9 +1,11 @@
|
|||||||
u8 a;
|
u8 a;
|
||||||
|
|
||||||
|
a = 2;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
a = 3;
|
a = 3;
|
||||||
|
|
||||||
u8 b = 1;
|
u8 b = 1;
|
||||||
|
|
||||||
u8 c = 2;
|
u8 c = 2;
|
||||||
}
|
}
|
23
examples/parsenum.nct
Normal file
23
examples/parsenum.nct
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
@section(".data");
|
||||||
|
|
||||||
|
u8 buf: 0;
|
||||||
|
|
||||||
|
@section(".text");
|
||||||
|
|
||||||
|
extern u0(u32) exit;
|
||||||
|
extern s32(u32, u8*, u32) read;
|
||||||
|
|
||||||
|
_start: u0() -> {
|
||||||
|
u16 value = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if(read(0, &buf, 1) != 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf = buf - 48;
|
||||||
|
value = value * 10;
|
||||||
|
value = value + buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(value);
|
||||||
|
};
|
342
src/ast.c
342
src/ast.c
@ -8,6 +8,7 @@
|
|||||||
#include"ntc.h"
|
#include"ntc.h"
|
||||||
#include"reporting.h"
|
#include"reporting.h"
|
||||||
#include"utils.h"
|
#include"utils.h"
|
||||||
|
#include"x86/arch.h"
|
||||||
|
|
||||||
const char *AST_KIND_STR[] = { AST_KINDS(GEN_STRI) };
|
const char *AST_KIND_STR[] = { AST_KINDS(GEN_STRI) };
|
||||||
|
|
||||||
@ -118,7 +119,7 @@ int ast_stmt_is_after(const AST *chunk, const AST *s1, const AST *s2) {
|
|||||||
while(1) {
|
while(1) {
|
||||||
if(s && s->nodeKind == AST_STMT_LOOP) {
|
if(s && s->nodeKind == AST_STMT_LOOP) {
|
||||||
int i = ast_stmt_is_after(s->stmtLoop.body, s1, s2);
|
int i = ast_stmt_is_after(s->stmtLoop.body, s1, s2);
|
||||||
if(i != -1) {
|
if(i == 1 || (i == 0 && s1 != NULL)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +135,7 @@ int ast_stmt_is_after(const AST *chunk, const AST *s1, const AST *s2) {
|
|||||||
|
|
||||||
if(s->nodeKind == AST_STMT_IF) {
|
if(s->nodeKind == AST_STMT_IF) {
|
||||||
int i = ast_stmt_is_after(s->stmtIf.then, s1, s2);
|
int i = ast_stmt_is_after(s->stmtIf.then, s1, s2);
|
||||||
if(i != -1) {
|
if(i == 1 || (i == 0 && s1 != NULL)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,11 +234,19 @@ static void adduse(ScopeItem *vte, AST *use, AST *whole) {
|
|||||||
|
|
||||||
while(rd && rd->defCount == 0) rd = rd->parent;
|
while(rd && rd->defCount == 0) rd = rd->parent;
|
||||||
|
|
||||||
if(!rd) return;
|
if(rd) {
|
||||||
|
for(size_t d = 0; d < rd->defCount; d++) {
|
||||||
for(size_t d = 0; d < rd->defCount; d++) {
|
UseDef *ud = calloc(1, sizeof(*ud));
|
||||||
|
ud->def = rd->defs[d];
|
||||||
|
ud->use = use;
|
||||||
|
ud->stmt = whole;
|
||||||
|
ud->next = NULL;
|
||||||
|
|
||||||
|
rawadduse(vte, ud);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
UseDef *ud = calloc(1, sizeof(*ud));
|
UseDef *ud = calloc(1, sizeof(*ud));
|
||||||
ud->def = rd->defs[d];
|
ud->def = NULL;
|
||||||
ud->use = use;
|
ud->use = use;
|
||||||
ud->stmt = whole;
|
ud->stmt = whole;
|
||||||
ud->next = NULL;
|
ud->next = NULL;
|
||||||
@ -316,9 +325,9 @@ static void mergedefsloop(AST *tlc, ScopeItem *vte, AST *daLoopStmt) {
|
|||||||
udnew->use = ud->use;
|
udnew->use = ud->use;
|
||||||
udnew->stmt = ud->stmt;
|
udnew->stmt = ud->stmt;
|
||||||
|
|
||||||
if(udnew->next == NULL) {
|
/*if(udnew->next == NULL) {
|
||||||
vte->data.var.usedefLast = udnew;
|
vte->data.var.usedefLast = udnew;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
ud = ud->next;
|
ud = ud->next;
|
||||||
@ -334,22 +343,47 @@ static void mergedefsloopall(AST *tlc, AST *daLoopStmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ast_usedef_pass(AST *tlc, AST *a, AST *wholestmt) {
|
struct UsedefPassState {
|
||||||
|
size_t loopDepth;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ast_usedef_pass(struct UsedefPassState *state, AST *tlc, AST *a, AST *wholestmt) {
|
||||||
if(a->nodeKind == AST_CHUNK) {
|
if(a->nodeKind == AST_CHUNK) {
|
||||||
for(AST *s = a->chunk.statementFirst; s; s = s->statement.next) {
|
for(AST *s = a->chunk.statementFirst; s; s = s->statement.next) {
|
||||||
ast_usedef_pass(tlc, s, s);
|
ast_usedef_pass(state, tlc, s, s);
|
||||||
}
|
}
|
||||||
} else if(a->nodeKind == AST_STMT_IF) {
|
} else if(a->nodeKind == AST_STMT_IF) {
|
||||||
pushdefsall(tlc);
|
pushdefsall(tlc);
|
||||||
|
|
||||||
ast_usedef_pass(tlc, a->stmtIf.expression, wholestmt);
|
ast_usedef_pass(state, tlc, a->stmtIf.expression, wholestmt);
|
||||||
ast_usedef_pass(tlc, a->stmtIf.then, wholestmt);
|
ast_usedef_pass(state, tlc, a->stmtIf.then, wholestmt);
|
||||||
|
|
||||||
mergedefsall(tlc);
|
mergedefsall(tlc);
|
||||||
} else if(a->nodeKind == AST_STMT_LOOP) {
|
} else if(a->nodeKind == AST_STMT_LOOP) {
|
||||||
pushdefsall(tlc);
|
pushdefsall(tlc);
|
||||||
|
|
||||||
ast_usedef_pass(tlc, a->stmtLoop.body, wholestmt);
|
state->loopDepth++;
|
||||||
|
|
||||||
|
ast_usedef_pass(state, tlc, a->stmtLoop.body, wholestmt);
|
||||||
|
|
||||||
|
state->loopDepth--;
|
||||||
|
|
||||||
|
if(state->loopDepth == 0) {
|
||||||
|
for(size_t vi = 0; vi < tlc->chunk.varCount; vi++) {
|
||||||
|
ScopeItem *si = tlc->chunk.vars[vi];
|
||||||
|
|
||||||
|
if(si->data.var.usedInLoop) {
|
||||||
|
if(ast_stmt_is_after(a->stmtLoop.body, si->data.var.declaration, si->data.var.declaration) == -1) {
|
||||||
|
if(ast_stmt_is_after(tlc, a, si->data.var.liveRangeStart) == 0) {
|
||||||
|
si->data.var.liveRangeStart = a;
|
||||||
|
}
|
||||||
|
si->data.var.liveRangeEnd = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
si->data.var.usedInLoop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mergedefsloopall(tlc, a);
|
mergedefsloopall(tlc, a);
|
||||||
} else if(a->nodeKind == AST_STMT_ASSIGN) {
|
} else if(a->nodeKind == AST_STMT_ASSIGN) {
|
||||||
@ -357,32 +391,43 @@ static void ast_usedef_pass(AST *tlc, AST *a, AST *wholestmt) {
|
|||||||
overwritedefs(a->stmtAssign.what->exprVar.thing, a);
|
overwritedefs(a->stmtAssign.what->exprVar.thing, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_usedef_pass(tlc, a->stmtAssign.what, wholestmt);
|
ast_usedef_pass(state, tlc, a->stmtAssign.what, wholestmt);
|
||||||
|
|
||||||
if(a->stmtAssign.to) {
|
if(a->stmtAssign.to) {
|
||||||
ast_usedef_pass(tlc, a->stmtAssign.to, wholestmt);
|
ast_usedef_pass(state, tlc, a->stmtAssign.to, wholestmt);
|
||||||
}
|
}
|
||||||
} else if(a->nodeKind == AST_STMT_EXPR) {
|
} else if(a->nodeKind == AST_STMT_EXPR) {
|
||||||
ast_usedef_pass(tlc, a->stmtExpr.expr, wholestmt);
|
ast_usedef_pass(state, tlc, a->stmtExpr.expr, wholestmt);
|
||||||
} else if(a->nodeKind == AST_EXPR_VAR) {
|
} else if(a->nodeKind == AST_EXPR_VAR) {
|
||||||
if(a->exprVar.thing->kind == SCOPEITEM_VAR) {
|
ScopeItem *si = a->exprVar.thing;
|
||||||
adduse(a->exprVar.thing, a, wholestmt);
|
|
||||||
|
if(si->kind == SCOPEITEM_VAR) {
|
||||||
|
if(state->loopDepth > 0) {
|
||||||
|
si->data.var.usedInLoop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
adduse(si, a, wholestmt);
|
||||||
|
|
||||||
|
if(si->data.var.liveRangeStart == NULL) {
|
||||||
|
si->data.var.liveRangeStart = wholestmt;
|
||||||
|
}
|
||||||
|
si->data.var.liveRangeEnd = wholestmt;
|
||||||
}
|
}
|
||||||
} else if(a->nodeKind == AST_EXPR_BINARY_OP) {
|
} else if(a->nodeKind == AST_EXPR_BINARY_OP) {
|
||||||
ast_usedef_pass(tlc, a->exprBinOp.operands[0], wholestmt);
|
ast_usedef_pass(state, tlc, a->exprBinOp.operands[0], wholestmt);
|
||||||
ast_usedef_pass(tlc, a->exprBinOp.operands[1], wholestmt);
|
ast_usedef_pass(state, tlc, a->exprBinOp.operands[1], wholestmt);
|
||||||
} else if(a->nodeKind == AST_EXPR_UNARY_OP) {
|
} else if(a->nodeKind == AST_EXPR_UNARY_OP) {
|
||||||
ast_usedef_pass(tlc, a->exprUnOp.operand, wholestmt);
|
ast_usedef_pass(state, tlc, a->exprUnOp.operand, wholestmt);
|
||||||
} else if(a->nodeKind == AST_EXPR_CALL) {
|
} else if(a->nodeKind == AST_EXPR_CALL) {
|
||||||
ast_usedef_pass(tlc, a->exprCall.what, wholestmt);
|
ast_usedef_pass(state, tlc, a->exprCall.what, wholestmt);
|
||||||
|
|
||||||
for(size_t p = 0; p < a->exprCall.what->expression.type->function.argCount; p++) {
|
for(size_t p = 0; p < a->exprCall.what->expression.type->function.argCount; p++) {
|
||||||
ast_usedef_pass(tlc, a->exprCall.args[p], wholestmt);
|
ast_usedef_pass(state, tlc, a->exprCall.args[p], wholestmt);
|
||||||
}
|
}
|
||||||
} else if(a->nodeKind == AST_EXPR_PRIMITIVE) {
|
} else if(a->nodeKind == AST_EXPR_PRIMITIVE) {
|
||||||
} else if(a->nodeKind == AST_EXPR_STRING_LITERAL) {
|
} else if(a->nodeKind == AST_EXPR_STRING_LITERAL) {
|
||||||
} else if(a->nodeKind == AST_EXPR_CAST) {
|
} else if(a->nodeKind == AST_EXPR_CAST) {
|
||||||
ast_usedef_pass(tlc, a->exprCast.what, wholestmt);
|
ast_usedef_pass(state, tlc, a->exprCast.what, wholestmt);
|
||||||
} else if(a->nodeKind == AST_EXPR_STACK_POINTER) {
|
} else if(a->nodeKind == AST_EXPR_STACK_POINTER) {
|
||||||
} else if(a->nodeKind == AST_EXPR_EXT_SALLOC) {
|
} else if(a->nodeKind == AST_EXPR_EXT_SALLOC) {
|
||||||
} else if(a->nodeKind == AST_STMT_BREAK) {
|
} else if(a->nodeKind == AST_STMT_BREAK) {
|
||||||
@ -391,20 +436,26 @@ static void ast_usedef_pass(AST *tlc, AST *a, AST *wholestmt) {
|
|||||||
} else if(a->nodeKind == AST_STMT_EXT_ORG) {
|
} else if(a->nodeKind == AST_STMT_EXT_ORG) {
|
||||||
} else if(a->nodeKind == AST_STMT_EXT_SECTION) {
|
} else if(a->nodeKind == AST_STMT_EXT_SECTION) {
|
||||||
} else if(a->nodeKind == AST_STMT_DECL) {
|
} else if(a->nodeKind == AST_STMT_DECL) {
|
||||||
assert(a->stmtDecl.thing->kind != SCOPEITEM_VAR || a->stmtDecl.expression);
|
ScopeItem *si = a->stmtDecl.thing;
|
||||||
|
|
||||||
|
//assert(si->kind != SCOPEITEM_VAR || a->stmtDecl.expression);
|
||||||
|
|
||||||
|
if(si->kind == SCOPEITEM_VAR) {
|
||||||
|
assert(!si->data.var.declaration || si->data.var.declaration == a);
|
||||||
|
si->data.var.declaration = a;
|
||||||
|
}
|
||||||
} else if(a->nodeKind == AST_STMT_RETURN) {
|
} else if(a->nodeKind == AST_STMT_RETURN) {
|
||||||
if(a->stmtReturn.val) {
|
if(a->stmtReturn.val) {
|
||||||
ast_usedef_pass(tlc, a->stmtReturn.val, wholestmt);
|
ast_usedef_pass(state, tlc, a->stmtReturn.val, wholestmt);
|
||||||
}
|
|
||||||
} else if (a->nodeKind == AST_EXPR_EXT_SIZEOF) {
|
|
||||||
if (a->exprExtSizeOf.ofExpr) {
|
|
||||||
ast_usedef_pass(tlc, a->exprExtSizeOf.ofExpr, wholestmt);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stahp_node(a, "ast_usedef_pass: unhandled %s", AST_KIND_STR[a->nodeKind]);
|
stahp_node(a, "ast_usedef_pass: unhandled %s", AST_KIND_STR[a->nodeKind]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *ast_dump(AST *tlc);
|
||||||
|
char *ast_dumpc(AST *tlc, AST *chu);
|
||||||
|
|
||||||
void ast_usedef_reset(AST *chu) {
|
void ast_usedef_reset(AST *chu) {
|
||||||
for(size_t i = 0; i < chu->chunk.varCount; i++) {
|
for(size_t i = 0; i < chu->chunk.varCount; i++) {
|
||||||
ScopeItem *vte = chu->chunk.vars[i];
|
ScopeItem *vte = chu->chunk.vars[i];
|
||||||
@ -414,11 +465,78 @@ void ast_usedef_reset(AST *chu) {
|
|||||||
vte->data.var.reachingDefs = NULL;
|
vte->data.var.reachingDefs = NULL;
|
||||||
vte->data.var.usedefFirst = NULL;
|
vte->data.var.usedefFirst = NULL;
|
||||||
vte->data.var.usedefLast = NULL;
|
vte->data.var.usedefLast = NULL;
|
||||||
|
vte->data.var.liveRangeStart = NULL;
|
||||||
|
vte->data.var.liveRangeEnd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pushdefsall(chu);
|
pushdefsall(chu);
|
||||||
|
|
||||||
return ast_usedef_pass(chu, chu, NULL);
|
struct UsedefPassState state = {};
|
||||||
|
|
||||||
|
ast_usedef_pass(&state, chu, chu, NULL);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < chu->chunk.varCount; i++) {
|
||||||
|
ScopeItem *vte = chu->chunk.vars[i];
|
||||||
|
|
||||||
|
assert(vte->kind == SCOPEITEM_VAR);
|
||||||
|
|
||||||
|
assert(!!vte->data.var.usedefFirst == !!vte->data.var.usedefLast);
|
||||||
|
assert(!!vte->data.var.usedefFirst == !!vte->data.var.liveRangeStart);
|
||||||
|
//assert(!!vte->data.var.liveRangeStart == !!vte->data.var.liveRangeEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ntc_get_int("pdbg")) {
|
||||||
|
char *astdump = ast_dump(chu);
|
||||||
|
fprintf(stderr, "### USEDEF GENERATED ###\n%s\n", astdump);
|
||||||
|
free(astdump);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ast_tlc_add_var(AST *tlc, ScopeItem *si) {
|
||||||
|
tlc->chunk.vars = realloc(tlc->chunk.vars, sizeof(*tlc->chunk.vars) * ++tlc->chunk.varCount);
|
||||||
|
tlc->chunk.vars[tlc->chunk.varCount - 1] = si;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Split away complex expression into a new local variable */
|
||||||
|
static AST *varify(AST *tlc, AST *chunk, AST **stmtPrev, AST *stmt, AST *e) {
|
||||||
|
static size_t idx = 0;
|
||||||
|
|
||||||
|
ScopeItem *vte = calloc(1, sizeof(*vte));
|
||||||
|
vte->kind = SCOPEITEM_VAR;
|
||||||
|
vte->type = e->expression.type;
|
||||||
|
vte->data.var.name = malp("$varify_%lu", idx++);
|
||||||
|
|
||||||
|
ast_tlc_add_var(tlc, vte);
|
||||||
|
|
||||||
|
// Alter AST
|
||||||
|
|
||||||
|
ASTExprVar *ev[2];
|
||||||
|
for(int i = 0; i < 2; i++) {
|
||||||
|
ev[i] = calloc(1, sizeof(ASTExprVar));
|
||||||
|
ev[i]->nodeKind = AST_EXPR_VAR;
|
||||||
|
ev[i]->type = e->expression.type;
|
||||||
|
ev[i]->thing = vte;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTStmtAssign *assign = calloc(1, sizeof(*assign));
|
||||||
|
assign->nodeKind = AST_STMT_ASSIGN;
|
||||||
|
assign->what = (AST*) ev[0];
|
||||||
|
assign->to = e;
|
||||||
|
|
||||||
|
if(*stmtPrev) {
|
||||||
|
(*stmtPrev)->statement.next = (AST*) assign;
|
||||||
|
} else {
|
||||||
|
chunk->chunk.statementFirst = (AST*) assign;
|
||||||
|
}
|
||||||
|
assign->next = stmt;
|
||||||
|
*stmtPrev = (AST*) assign;
|
||||||
|
|
||||||
|
// Reset ud-chain
|
||||||
|
|
||||||
|
vte->data.var.usedefFirst = NULL;
|
||||||
|
vte->data.var.usedefLast = NULL;
|
||||||
|
|
||||||
|
return (AST*) ev[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
char *type_to_string(Type *t) {
|
char *type_to_string(Type *t) {
|
||||||
@ -456,7 +574,7 @@ char *type_to_string(Type *t) {
|
|||||||
return strdup("@unimp");
|
return strdup("@unimp");
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ast_dumpe(AST *e) {
|
static char *ast_dumpe(AST *tlc, AST *e) {
|
||||||
if(e->nodeKind == AST_EXPR_PRIMITIVE) {
|
if(e->nodeKind == AST_EXPR_PRIMITIVE) {
|
||||||
return malp("%i", e->exprPrim.val);
|
return malp("%i", e->exprPrim.val);
|
||||||
} else if(e->nodeKind == AST_EXPR_VAR) {
|
} else if(e->nodeKind == AST_EXPR_VAR) {
|
||||||
@ -485,13 +603,13 @@ static char *ast_dumpe(AST *e) {
|
|||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
char *c = ast_dumpe(e->exprUnOp.operand);
|
char *c = ast_dumpe(tlc, e->exprUnOp.operand);
|
||||||
char *r = malp("%s%s", op, c);
|
char *r = malp("%s%s", op, c);
|
||||||
free(c);
|
free(c);
|
||||||
return r;
|
return r;
|
||||||
} else if(e->nodeKind == AST_EXPR_BINARY_OP) {
|
} else if(e->nodeKind == AST_EXPR_BINARY_OP) {
|
||||||
char *a = ast_dumpe(e->exprBinOp.operands[0]);
|
char *a = ast_dumpe(tlc, e->exprBinOp.operands[0]);
|
||||||
char *b = ast_dumpe(e->exprBinOp.operands[1]);
|
char *b = ast_dumpe(tlc, e->exprBinOp.operands[1]);
|
||||||
const char *op;
|
const char *op;
|
||||||
switch(e->exprBinOp.operator) {
|
switch(e->exprBinOp.operator) {
|
||||||
case BINOP_ADD:
|
case BINOP_ADD:
|
||||||
@ -568,7 +686,7 @@ static char *ast_dumpe(AST *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
char *choonk = ast_dump(e->exprFunc.chunk);
|
char *choonk = ast_dumpc(tlc, e->exprFunc.chunk);
|
||||||
char *out2 = malp("%s) {\n%s}", out, choonk);
|
char *out2 = malp("%s) {\n%s}", out, choonk);
|
||||||
free(out);
|
free(out);
|
||||||
free(choonk);
|
free(choonk);
|
||||||
@ -577,12 +695,12 @@ static char *ast_dumpe(AST *e) {
|
|||||||
|
|
||||||
return out;
|
return out;
|
||||||
} else if(e->nodeKind == AST_EXPR_CALL) {
|
} else if(e->nodeKind == AST_EXPR_CALL) {
|
||||||
char *w = ast_dumpe(e->exprCall.what);
|
char *w = ast_dumpe(tlc, e->exprCall.what);
|
||||||
char *out = malp("%s(", w);
|
char *out = malp("%s(", w);
|
||||||
free(w);
|
free(w);
|
||||||
size_t argCount = e->exprCall.what->expression.type->function.argCount;
|
size_t argCount = e->exprCall.what->expression.type->function.argCount;
|
||||||
for(size_t i = 0; i < argCount; i++) {
|
for(size_t i = 0; i < argCount; i++) {
|
||||||
char *a = ast_dumpe(e->exprCall.args[i]);
|
char *a = ast_dumpe(tlc, e->exprCall.args[i]);
|
||||||
char *out2 = malp(i == argCount - 1 ? "%s%s)" : "%s%s, ", out, a);
|
char *out2 = malp(i == argCount - 1 ? "%s%s)" : "%s%s, ", out, a);
|
||||||
free(a);
|
free(a);
|
||||||
free(out);
|
free(out);
|
||||||
@ -595,14 +713,14 @@ static char *ast_dumpe(AST *e) {
|
|||||||
free(w);
|
free(w);
|
||||||
return out;
|
return out;
|
||||||
} else if(e->nodeKind == AST_EXPR_CAST) {
|
} else if(e->nodeKind == AST_EXPR_CAST) {
|
||||||
char *a = ast_dumpe(e->exprCast.what);
|
char *a = ast_dumpe(tlc, e->exprCast.what);
|
||||||
char *b = type_to_string(e->exprCast.to);
|
char *b = type_to_string(e->exprCast.to);
|
||||||
char *out = malp("(%s as %s)", a, b);
|
char *out = malp("(%s as %s)", a, b);
|
||||||
free(a);
|
free(a);
|
||||||
free(b);
|
free(b);
|
||||||
return out;
|
return out;
|
||||||
} else if(e->nodeKind == AST_EXPR_DOT) {
|
} else if(e->nodeKind == AST_EXPR_DOT) {
|
||||||
char *a = ast_dumpe(e->exprDot.a);
|
char *a = ast_dumpe(tlc, e->exprDot.a);
|
||||||
char *out = malp(e->nodeKind == AST_EXPR_BINARY_OP ? "(%s).%s" : "%s.%s", a, e->exprDot.b);
|
char *out = malp(e->nodeKind == AST_EXPR_BINARY_OP ? "(%s).%s" : "%s.%s", a, e->exprDot.b);
|
||||||
free(a);
|
free(a);
|
||||||
return out;
|
return out;
|
||||||
@ -611,43 +729,41 @@ static char *ast_dumpe(AST *e) {
|
|||||||
return malp("@unimp:%s", AST_KIND_STR[e->nodeKind]);
|
return malp("@unimp:%s", AST_KIND_STR[e->nodeKind]);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ast_dump(AST *tlc);
|
static char *ast_dumps(AST *tlc, AST *s) {
|
||||||
|
|
||||||
static char *ast_dumps(AST *s) {
|
|
||||||
if(s->nodeKind == AST_STMT_DECL) {
|
if(s->nodeKind == AST_STMT_DECL) {
|
||||||
ScopeItem *vte = s->stmtDecl.thing;
|
ScopeItem *vte = s->stmtDecl.thing;
|
||||||
|
|
||||||
if(vte->kind == SCOPEITEM_SYMBOL) {
|
if(vte->kind == SCOPEITEM_SYMBOL) {
|
||||||
char *t = type_to_string(vte->type);
|
char *t = type_to_string(vte->type);
|
||||||
char *e = s->stmtDecl.expression ? ast_dumpe(s->stmtDecl.expression) : strdup("");
|
char *e = s->stmtDecl.expression ? ast_dumpe(tlc, s->stmtDecl.expression) : strdup("");
|
||||||
char *r = malp("%s%s %s: %s;\n", vte->data.symbol.isExternal ? "external " : "", t, vte->data.symbol.name, e);
|
char *r = malp("%s%s %s: %s;", vte->data.symbol.isExternal ? "external " : "", t, vte->data.symbol.name, e);
|
||||||
free(t);
|
free(t);
|
||||||
free(e);
|
free(e);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
} else if(s->nodeKind == AST_STMT_ASSIGN) {
|
} else if(s->nodeKind == AST_STMT_ASSIGN) {
|
||||||
if(s->stmtAssign.to) {
|
if(s->stmtAssign.to) {
|
||||||
char *a = ast_dumpe(s->stmtAssign.what);
|
char *a = ast_dumpe(tlc, s->stmtAssign.what);
|
||||||
char *b = ast_dumpe(s->stmtAssign.to);
|
char *b = ast_dumpe(tlc, s->stmtAssign.to);
|
||||||
char *r = malp("%s = %s;\n", a, b);
|
char *r = malp("%s = %s;", a, b);
|
||||||
free(a);
|
free(a);
|
||||||
free(b);
|
free(b);
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
char *a = ast_dumpe(s->stmtAssign.what);
|
char *a = ast_dumpe(tlc, s->stmtAssign.what);
|
||||||
char *r = malp("%s = ; /* fake def */\n", a);
|
char *r = malp("%s = ; /* fake def */", a);
|
||||||
free(a);
|
free(a);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
} else if(s->nodeKind == AST_STMT_LOOP) {
|
} else if(s->nodeKind == AST_STMT_LOOP) {
|
||||||
char *inner = ast_dump(s->stmtLoop.body);
|
char *inner = ast_dumpc(tlc, s->stmtLoop.body);
|
||||||
char *c = malp("loop {\n%s}\n", inner);
|
char *c = malp("loop {\n%s}", inner);
|
||||||
free(inner);
|
free(inner);
|
||||||
return c;
|
return c;
|
||||||
} else if(s->nodeKind == AST_STMT_IF) {
|
} else if(s->nodeKind == AST_STMT_IF) {
|
||||||
char *cond = ast_dumpe(s->stmtIf.expression);
|
char *cond = ast_dumpe(tlc, s->stmtIf.expression);
|
||||||
char *inner = ast_dump(s->stmtIf.then);
|
char *inner = ast_dumpc(tlc, s->stmtIf.then);
|
||||||
char *c = malp("if(%s) {\n%s}\n", cond, inner);
|
char *c = malp("if(%s) {\n%s}", cond, inner);
|
||||||
free(cond);
|
free(cond);
|
||||||
free(inner);
|
free(inner);
|
||||||
return c;
|
return c;
|
||||||
@ -660,33 +776,55 @@ static char *ast_dumps(AST *s) {
|
|||||||
name = s->stmtExpr.expr->exprVar.thing->data.symbol.name;
|
name = s->stmtExpr.expr->exprVar.thing->data.symbol.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return malp("%s; /* loop guard */\n", name);
|
return malp("%s; /* loop guard */", name);
|
||||||
} else if(s->nodeKind == AST_STMT_EXPR) {
|
} else if(s->nodeKind == AST_STMT_EXPR) {
|
||||||
return ast_dumpe(s->stmtExpr.expr);
|
return ast_dumpe(tlc, s->stmtExpr.expr);
|
||||||
} else if(s->nodeKind == AST_STMT_RETURN) {
|
} else if(s->nodeKind == AST_STMT_RETURN) {
|
||||||
if(s->stmtReturn.val) {
|
if(s->stmtReturn.val) {
|
||||||
char *e = ast_dumpe(s->stmtReturn.val);
|
char *e = ast_dumpe(tlc, s->stmtReturn.val);
|
||||||
char *c = malp("return %s;\n", e);
|
char *c = malp("return %s;", e);
|
||||||
free(e);
|
free(e);
|
||||||
return c;
|
return c;
|
||||||
} else {
|
} else {
|
||||||
return malp("return;\n");
|
return malp("return;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return malp("@unimp:%s\n", AST_KIND_STR[s->nodeKind]);
|
return malp("@unimp:%s;", AST_KIND_STR[s->nodeKind]);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ast_dump(AST *tlc) {
|
static char *stmt_live_range_dbgs(AST *tlc, AST *stmt) {
|
||||||
AST *stmt = tlc->chunk.statementFirst;
|
char *ret = malp("");
|
||||||
|
for(size_t v = 0; v < tlc->chunk.varCount; v++) {
|
||||||
|
ScopeItem *si = tlc->chunk.vars[v];
|
||||||
|
|
||||||
|
if(si->data.var.liveRangeStart == stmt) {
|
||||||
|
char *ret2 = malp("%s (%s start)", ret, si->data.var.name);
|
||||||
|
free(ret);
|
||||||
|
ret = ret2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(si->data.var.liveRangeEnd == stmt) {
|
||||||
|
char *ret2 = malp("%s (%s end)", ret, si->data.var.name);
|
||||||
|
free(ret);
|
||||||
|
ret = ret2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ast_dumpc(AST *tlc, AST *chu) {
|
||||||
|
AST *stmt = chu->chunk.statementFirst;
|
||||||
|
|
||||||
char *ret = malp("");
|
char *ret = malp("");
|
||||||
|
|
||||||
while(stmt) {
|
while(stmt) {
|
||||||
char *new = ast_dumps(stmt);
|
char *new = ast_dumps(tlc, stmt);
|
||||||
char *ret2 = malp("%s%s", ret, new);
|
char *users = stmt_live_range_dbgs(tlc, stmt);
|
||||||
|
char *ret2 = malp("%s%s%s\n", ret, new, users);
|
||||||
free(ret);
|
free(ret);
|
||||||
free(new);
|
free(new);
|
||||||
|
free(users);
|
||||||
ret = ret2;
|
ret = ret2;
|
||||||
|
|
||||||
stmt = stmt->statement.next;
|
stmt = stmt->statement.next;
|
||||||
@ -695,6 +833,10 @@ char *ast_dump(AST *tlc) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *ast_dump(AST *tlc) {
|
||||||
|
return ast_dumpc(tlc, tlc);
|
||||||
|
}
|
||||||
|
|
||||||
static void *memdup(void *a, size_t len) {
|
static void *memdup(void *a, size_t len) {
|
||||||
void *r = malloc(len);
|
void *r = malloc(len);
|
||||||
memcpy(r, a, len);
|
memcpy(r, a, len);
|
||||||
@ -712,7 +854,10 @@ AST *ast_deep_copy(AST *src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AST *ast_cast_expr(AST *what, Type *to) {
|
AST *ast_cast_expr(AST *what, Type *to) {
|
||||||
if(what == NULL) goto fail;
|
if(what == NULL) {
|
||||||
|
stahp(0, 0, "NULL what passed to ast_cast_expr");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* Only exists at parse-time, hence not part of type system and is handled separately */
|
/* Only exists at parse-time, hence not part of type system and is handled separately */
|
||||||
if(what->nodeKind == AST_EXPR_STRING_LITERAL) {
|
if(what->nodeKind == AST_EXPR_STRING_LITERAL) {
|
||||||
@ -977,7 +1122,7 @@ static void ast_decompose_automatic_record(AST *tlc, ScopeItem *target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ast_sroa(AST *tlc) {
|
void ast_sroa(AST *tlc) {
|
||||||
for(size_t i = 0; i < tlc->chunk.varCount; i++) {
|
for(int i = 0; i < tlc->chunk.varCount; i++) {
|
||||||
ScopeItem *si = tlc->chunk.vars[i];
|
ScopeItem *si = tlc->chunk.vars[i];
|
||||||
|
|
||||||
if(!is_sroa_candidate(si)) {
|
if(!is_sroa_candidate(si)) {
|
||||||
@ -994,6 +1139,67 @@ void ast_sroa(AST *tlc) {
|
|||||||
tlc->chunk.varCount--;
|
tlc->chunk.varCount--;
|
||||||
|
|
||||||
/* Restart */
|
/* Restart */
|
||||||
i = 0;
|
i = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ast_segmented_dereference_visitor(AST **aptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
||||||
|
if(tlc != ud) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AST *n = *aptr;
|
||||||
|
if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_DEREF && type_is_segmented_pointer(n->exprUnOp.operand->expression.type)) {
|
||||||
|
static size_t idx = 0;
|
||||||
|
|
||||||
|
AST *v;
|
||||||
|
if(n->exprUnOp.operand->nodeKind == AST_EXPR_VAR)
|
||||||
|
v = n->exprUnOp.operand;
|
||||||
|
else
|
||||||
|
v = varify(tlc, chunk, &stmtPrev, stmt, n->exprUnOp.operand);
|
||||||
|
|
||||||
|
ScopeItem *si = calloc(1, sizeof(*si));
|
||||||
|
si->kind = SCOPEITEM_VAR;
|
||||||
|
si->type = primitive_parse("u16");
|
||||||
|
si->data.var.preclassed = true;
|
||||||
|
si->data.var.registerClass = REG_CLASS_DATASEGS;
|
||||||
|
si->data.var.precolored = true;
|
||||||
|
si->data.var.color = 0;
|
||||||
|
si->data.var.name = malp("$segtemp_%lu", idx++);
|
||||||
|
ast_tlc_add_var(tlc, si);
|
||||||
|
|
||||||
|
ASTExprVar *ev = calloc(1, sizeof(*ev));
|
||||||
|
ev->nodeKind = AST_EXPR_VAR;
|
||||||
|
ev->type = si->type;
|
||||||
|
ev->thing = si;
|
||||||
|
|
||||||
|
ASTExprDot *edseg = calloc(1, sizeof(*edseg));
|
||||||
|
edseg->type = n->exprUnOp.operand->expression.type->record.fieldTypes[0];
|
||||||
|
edseg->nodeKind = AST_EXPR_DOT;
|
||||||
|
edseg->a = v;
|
||||||
|
edseg->b = strdup("segment");
|
||||||
|
|
||||||
|
ASTStmtAssign *ass = calloc(1, sizeof(*ass));
|
||||||
|
ass->nodeKind = AST_STMT_ASSIGN;
|
||||||
|
ass->what = (AST*) ev;
|
||||||
|
ass->to = (AST*) edseg;
|
||||||
|
ass->next = (AST*) stmt;
|
||||||
|
if(stmtPrev)
|
||||||
|
stmtPrev->statement.next = (AST*) ass;
|
||||||
|
else
|
||||||
|
chunk->chunk.statementFirst = (AST*) ass;
|
||||||
|
stmtPrev = (AST*) ass;
|
||||||
|
|
||||||
|
ASTExprDot *ed = calloc(1, sizeof(*ed));
|
||||||
|
ed->type = n->exprUnOp.operand->expression.type->record.fieldTypes[1];
|
||||||
|
ed->nodeKind = AST_EXPR_DOT;
|
||||||
|
ed->a = ast_deep_copy(v);
|
||||||
|
ed->b = strdup("offset");
|
||||||
|
|
||||||
|
n->exprUnOp.operand = (AST*) ed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_segmented_dereference(AST *tlc) {
|
||||||
|
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, ast_segmented_dereference_visitor, NULL);
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#define GEN_STRI(x) #x,
|
#define GEN_STRI(x) #x,
|
||||||
|
|
||||||
#define AST_KINDS(K) \
|
#define AST_KINDS(K) \
|
||||||
|
K(AST_MISSING) \
|
||||||
K(AST_CHUNK) \
|
K(AST_CHUNK) \
|
||||||
K(AST_STMT_DECL) \
|
K(AST_STMT_DECL) \
|
||||||
K(AST_EXPR_PRIMITIVE) \
|
K(AST_EXPR_PRIMITIVE) \
|
||||||
@ -361,4 +362,8 @@ void ast_commutativity_pass(AST *tlc);
|
|||||||
|
|
||||||
void ast_sroa(AST *tlc);
|
void ast_sroa(AST *tlc);
|
||||||
|
|
||||||
|
// Convert segmented derefences like *x into segment move and *x.offset.
|
||||||
|
// Must be done before ast_sroa.
|
||||||
|
void ast_segmented_dereference(AST *tlc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -94,6 +94,7 @@ int main(int argc_, char **argv_) {
|
|||||||
free(astdump);
|
free(astdump);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast_segmented_dereference(chunk);
|
||||||
ast_sroa(chunk);
|
ast_sroa(chunk);
|
||||||
dumben_pre(chunk);
|
dumben_pre(chunk);
|
||||||
dumben_go(chunk);
|
dumben_go(chunk);
|
||||||
|
85
src/parse.c
85
src/parse.c
@ -9,6 +9,7 @@
|
|||||||
#include<stdint.h>
|
#include<stdint.h>
|
||||||
#include<signal.h>
|
#include<signal.h>
|
||||||
#include"ntc.h"
|
#include"ntc.h"
|
||||||
|
#include"x86/arch.h"
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
static inline int __builtin_clzl(unsigned long x) {
|
static inline int __builtin_clzl(unsigned long x) {
|
||||||
@ -39,8 +40,6 @@ typedef struct {
|
|||||||
|
|
||||||
// Used to place guard variable uses after loops to stop reg allocation from fucking up
|
// Used to place guard variable uses after loops to stop reg allocation from fucking up
|
||||||
Scope *loopScope;
|
Scope *loopScope;
|
||||||
size_t guardedVarCount;
|
|
||||||
ASTExprVar **guardedVars;
|
|
||||||
|
|
||||||
// Used for generating statements that load & store arguments
|
// Used for generating statements that load & store arguments
|
||||||
int isInFunction;
|
int isInFunction;
|
||||||
@ -144,7 +143,7 @@ static AST *exprvar(Parser *P, ScopeItem *v) {
|
|||||||
a->exprVar.type = v->type;
|
a->exprVar.type = v->type;
|
||||||
a->exprVar.thing = v;
|
a->exprVar.thing = v;
|
||||||
|
|
||||||
if(P->loopScope) {
|
/*if(P->loopScope) {
|
||||||
// XXX: O(n)!!!!!!!!!
|
// XXX: O(n)!!!!!!!!!
|
||||||
|
|
||||||
int inloop = 0;
|
int inloop = 0;
|
||||||
@ -172,7 +171,7 @@ static AST *exprvar(Parser *P, ScopeItem *v) {
|
|||||||
P->guardedVars[P->guardedVarCount++] = ev;
|
P->guardedVars[P->guardedVarCount++] = ev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@ -354,7 +353,13 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
astop->nodeKind = AST_EXPR_UNARY_OP;
|
astop->nodeKind = AST_EXPR_UNARY_OP;
|
||||||
astop->operator = UNOP_DEREF;
|
astop->operator = UNOP_DEREF;
|
||||||
astop->operand = nct_parse_expression(P, lOP); /* Not +1! */
|
astop->operand = nct_parse_expression(P, lOP); /* Not +1! */
|
||||||
astop->type = astop->operand->expression.type->pointer.of;
|
|
||||||
|
if(type_is_segmented_pointer(astop->operand->expression.type)) {
|
||||||
|
astop->type = astop->operand->expression.type->record.fieldTypes[1]->pointer.of;
|
||||||
|
} else {
|
||||||
|
assert(astop->operand->expression.type->type == TYPE_TYPE_POINTER);
|
||||||
|
astop->type = astop->operand->expression.type->pointer.of;
|
||||||
|
}
|
||||||
|
|
||||||
return (AST*) astop;
|
return (AST*) astop;
|
||||||
} else if(maybe(P, TOKEN_AMPERSAND)) {
|
} else if(maybe(P, TOKEN_AMPERSAND)) {
|
||||||
@ -743,8 +748,34 @@ static Type *nct_parse_typename(Parser *P) {
|
|||||||
goto backtrack;
|
goto backtrack;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(peek(P, 0).type == TOKEN_PAREN_L || peek(P, 0).type == TOKEN_STAR || peek(P, 0).type == TOKEN_SQUAREN_L) {
|
while(peek(P, 0).type == TOKEN_PAREN_L
|
||||||
if(maybe(P, TOKEN_STAR)) {
|
|| peek(P, 0).type == TOKEN_STAR
|
||||||
|
|| peek(P, 0).type == TOKEN_SQUAREN_L
|
||||||
|
|| (peek(P, 0).type == TOKEN_IDENTIFIER && !strcmp(peek(P, 0).content, "@far"))) {
|
||||||
|
|
||||||
|
if(maybe(P, TOKEN_IDENTIFIER)) {
|
||||||
|
expect(P, TOKEN_STAR);
|
||||||
|
|
||||||
|
TypeRecord *rec = calloc(1, sizeof(*rec));
|
||||||
|
rec->type = TYPE_TYPE_RECORD;
|
||||||
|
rec->name = malp("%s @far*", type_to_string(ret));
|
||||||
|
|
||||||
|
rec->fieldCount = 2;
|
||||||
|
|
||||||
|
rec->fieldTypes = calloc(2, sizeof(*rec->fieldTypes));
|
||||||
|
rec->fieldTypes[0] = primitive_parse("u16");
|
||||||
|
rec->fieldTypes[1] = type_pointer_wrap(ret);
|
||||||
|
|
||||||
|
rec->fieldNames = calloc(2, sizeof(*rec->fieldNames));
|
||||||
|
rec->fieldNames[0] = malp("segment");
|
||||||
|
rec->fieldNames[1] = malp("offset");
|
||||||
|
|
||||||
|
rec->fieldOffsets = calloc(2, sizeof(*rec->fieldOffsets));
|
||||||
|
rec->fieldOffsets[0] = 0;
|
||||||
|
rec->fieldOffsets[1] = 2;
|
||||||
|
|
||||||
|
ret = (Type*) rec;
|
||||||
|
} else if(maybe(P, TOKEN_STAR)) {
|
||||||
TypePointer *ptr = calloc(1, sizeof(*ptr));
|
TypePointer *ptr = calloc(1, sizeof(*ptr));
|
||||||
ptr->type = TYPE_TYPE_POINTER;
|
ptr->type = TYPE_TYPE_POINTER;
|
||||||
ptr->of = ret;
|
ptr->of = ret;
|
||||||
@ -844,6 +875,7 @@ static Type *nct_parse_typename(Parser *P) {
|
|||||||
P->scope = P->scope->parent;
|
P->scope = P->scope->parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(generics) {
|
if(generics) {
|
||||||
@ -899,17 +931,22 @@ static AST *parse_declaration(Parser *P) {
|
|||||||
entry->data.var.priority = 1;
|
entry->data.var.priority = 1;
|
||||||
entry->data.var.color = -1;
|
entry->data.var.color = -1;
|
||||||
|
|
||||||
ASTStmtAssign *assign = alloc_node(P, sizeof(*assign));
|
//ASTStmtAssign *assign = alloc_node(P, sizeof(*assign));
|
||||||
assign->nodeKind = AST_STMT_ASSIGN;
|
//assign->nodeKind = AST_STMT_ASSIGN;
|
||||||
assign->next = NULL;
|
//assign->next = NULL;
|
||||||
|
|
||||||
//entry->data.var.reachingDefs = reachingdefs_push(NULL);
|
//assign->what = exprvar(P, entry);
|
||||||
//reachingdefs_set(entry->data.var.reachingDefs, (AST*) assign);
|
|
||||||
|
|
||||||
assign->what = exprvar(P, entry);
|
AST *expr = peek(P, 0).type == TOKEN_SEMICOLON ? NULL : ast_cast_expr(nct_parse_expression(P, 0), entry->type);
|
||||||
assign->to = peek(P, 0).type == TOKEN_SEMICOLON ? NULL : ast_cast_expr(nct_parse_expression(P, 0), assign->what->expression.type);
|
//assign->to = expr;
|
||||||
|
|
||||||
ret = (AST*) assign;
|
ASTStmtDecl *decl = alloc_node(P, sizeof(*ret));
|
||||||
|
decl->nodeKind = AST_STMT_DECL;
|
||||||
|
decl->thing = entry;
|
||||||
|
decl->next = NULL;
|
||||||
|
decl->expression = expr;
|
||||||
|
|
||||||
|
ret = (AST*) decl;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ASTStmtDecl *decl = alloc_node(P, sizeof(*ret));
|
ASTStmtDecl *decl = alloc_node(P, sizeof(*ret));
|
||||||
@ -1066,7 +1103,7 @@ static void nct_parse_statement(Parser *P) {
|
|||||||
if(isFirstLoop) {
|
if(isFirstLoop) {
|
||||||
P->loopScope = NULL;
|
P->loopScope = NULL;
|
||||||
|
|
||||||
for(size_t i = 0; i < P->guardedVarCount; i++) {
|
/*for(size_t i = 0; i < P->guardedVarCount; i++) {
|
||||||
ASTExprVar *ev = P->guardedVars[i];
|
ASTExprVar *ev = P->guardedVars[i];
|
||||||
|
|
||||||
AST *es = alloc_node(P, sizeof(ASTStmtExpr));
|
AST *es = alloc_node(P, sizeof(ASTStmtExpr));
|
||||||
@ -1078,7 +1115,7 @@ static void nct_parse_statement(Parser *P) {
|
|||||||
|
|
||||||
P->guardedVarCount = 0;
|
P->guardedVarCount = 0;
|
||||||
free(P->guardedVars);
|
free(P->guardedVars);
|
||||||
P->guardedVars = NULL;
|
P->guardedVars = NULL;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1290,6 +1327,18 @@ static void nct_parse_statement(Parser *P) {
|
|||||||
// Don't pass declaration statements for generic functions, because they're useless
|
// Don't pass declaration statements for generic functions, because they're useless
|
||||||
if(decl->nodeKind != AST_STMT_DECL || !type_is_generic(decl->stmtDecl.thing->type)) {
|
if(decl->nodeKind != AST_STMT_DECL || !type_is_generic(decl->stmtDecl.thing->type)) {
|
||||||
pushstat(P, decl);
|
pushstat(P, decl);
|
||||||
|
|
||||||
|
if(decl->stmtDecl.thing->kind == SCOPEITEM_VAR && decl->stmtDecl.expression) {
|
||||||
|
AST *expr = decl->stmtDecl.expression;
|
||||||
|
decl->stmtDecl.expression = NULL;
|
||||||
|
|
||||||
|
ASTStmtAssign *ass = alloc_node(P, sizeof(*ass));
|
||||||
|
ass->nodeKind = AST_STMT_ASSIGN;
|
||||||
|
ass->next = NULL;
|
||||||
|
ass->what = exprvar(P, decl->stmtDecl.thing);
|
||||||
|
ass->to = expr;
|
||||||
|
pushstat(P, ass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1596,6 +1645,8 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize, Scope *t
|
|||||||
|
|
||||||
/* Now actual parsing. */
|
/* Now actual parsing. */
|
||||||
|
|
||||||
|
arch_add_hidden_variables(P->scope);
|
||||||
|
|
||||||
while(peek(P, 0).type != TOKEN_EOF && peek(P, 0).type != TOKEN_SQUIGGLY_R) {
|
while(peek(P, 0).type != TOKEN_EOF && peek(P, 0).type != TOKEN_SQUIGGLY_R) {
|
||||||
nct_parse_statement(P);
|
nct_parse_statement(P);
|
||||||
}
|
}
|
||||||
|
10
src/scope.h
10
src/scope.h
@ -65,14 +65,16 @@ typedef struct ScopeItem {
|
|||||||
bool precolored, preclassed;
|
bool precolored, preclassed;
|
||||||
int registerClass;
|
int registerClass;
|
||||||
|
|
||||||
// Used during parsing
|
// Used by ast_usedef_pass
|
||||||
|
union AST *declaration;
|
||||||
ReachingDefs *reachingDefs;
|
ReachingDefs *reachingDefs;
|
||||||
|
bool usedInLoop;
|
||||||
// Optimizations
|
|
||||||
|
|
||||||
UseDef *usedefFirst;
|
UseDef *usedefFirst;
|
||||||
UseDef *usedefLast;
|
UseDef *usedefLast;
|
||||||
|
|
||||||
|
union AST *liveRangeStart;
|
||||||
|
union AST *liveRangeEnd;
|
||||||
} var;
|
} var;
|
||||||
struct {
|
struct {
|
||||||
Type *ptr;
|
Type *ptr;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include<stddef.h>
|
#include<stddef.h>
|
||||||
#include<stdint.h>
|
#include<stdint.h>
|
||||||
#include<stdbool.h>
|
#include<stdbool.h>
|
||||||
|
#include<string.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TYPE_TYPE_PRIMITIVE, TYPE_TYPE_RECORD, TYPE_TYPE_POINTER, TYPE_TYPE_FUNCTION, TYPE_TYPE_ARRAY, TYPE_TYPE_GENERIC, TYPE_TYPE_ERROR
|
TYPE_TYPE_PRIMITIVE, TYPE_TYPE_RECORD, TYPE_TYPE_POINTER, TYPE_TYPE_FUNCTION, TYPE_TYPE_ARRAY, TYPE_TYPE_GENERIC, TYPE_TYPE_ERROR
|
||||||
@ -109,4 +110,8 @@ Type *type_shallow_copy(Type *t);
|
|||||||
|
|
||||||
bool type_is_generic(Type *t);
|
bool type_is_generic(Type *t);
|
||||||
|
|
||||||
|
static inline bool type_is_segmented_pointer(Type *type) {
|
||||||
|
return type->type == TYPE_TYPE_RECORD && !!strstr(type->record.name, " @far*");
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,15 +9,15 @@ RegisterClass REG_CLASSES[] = {
|
|||||||
},
|
},
|
||||||
[REG_CLASS_NOT_8] = {
|
[REG_CLASS_NOT_8] = {
|
||||||
.rMask = HWR_GPR, .w = 2, .p = 4,
|
.rMask = HWR_GPR, .w = 2, .p = 4,
|
||||||
.rs = {HWR_AX, HWR_EAX, HWR_BX, HWR_EBX, HWR_CX, HWR_ECX, HWR_DX, HWR_EDX, HWR_DI, HWR_EDI, HWR_SI, HWR_ESI},
|
.rs = {HWR_AX, HWR_EAX, HWR_BX, HWR_EBX, HWR_CX, HWR_ECX, HWR_DX, HWR_EDX, HWR_DI, HWR_EDI, HWR_SI, HWR_ESI, HWR_BP, HWR_EBP},
|
||||||
.rsN = {"ax", "eax", "bx", "ebx", "cx", "ecx", "dx", "edx", "di", "edi", "si", "esi"},
|
.rsN = {"ax", "eax", "bx", "ebx", "cx", "ecx", "dx", "edx", "di", "edi", "si", "esi", "bp", "ebp"},
|
||||||
.rsS = {2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4},
|
.rsS = {2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4},
|
||||||
},
|
},
|
||||||
[REG_CLASS_16_32] = {
|
[REG_CLASS_16_32] = {
|
||||||
.rMask = HWR_GPR, .w = 2, .p = 4,
|
.rMask = HWR_GPR, .w = 2, .p = 4,
|
||||||
.rs = {HWR_AX, HWR_EAX, HWR_BX, HWR_EBX, HWR_CX, HWR_ECX, HWR_DX, HWR_EDX},
|
.rs = {HWR_AX, HWR_EAX, HWR_BX, HWR_EBX, HWR_CX, HWR_ECX, HWR_DX, HWR_EDX, HWR_BP, HWR_EBP},
|
||||||
.rsN = {"ax", "eax", "bx", "ebx", "cx", "ecx", "dx", "edx"},
|
.rsN = {"ax", "eax", "bx", "ebx", "cx", "ecx", "dx", "edx", "bp", "ebp"},
|
||||||
.rsS = {2, 4, 2, 4, 2, 4, 2, 4},
|
.rsS = {2, 4, 2, 4, 2, 4, 2, 4, 2, 4},
|
||||||
},
|
},
|
||||||
[REG_CLASS_IND] = {
|
[REG_CLASS_IND] = {
|
||||||
.rMask = HWR_IND, .w = 2, .p = 2,
|
.rMask = HWR_IND, .w = 2, .p = 2,
|
||||||
@ -27,15 +27,15 @@ RegisterClass REG_CLASSES[] = {
|
|||||||
},
|
},
|
||||||
[REG_CLASS_IA16_PTRS] = {
|
[REG_CLASS_IA16_PTRS] = {
|
||||||
.rMask = HWR_IND | HWR_BX,
|
.rMask = HWR_IND | HWR_BX,
|
||||||
.rs = {HWR_DI, HWR_SI, HWR_BX},
|
.rs = {HWR_DI, HWR_SI, HWR_BX, HWR_BP},
|
||||||
.rsN = {"di", "si", "bx"},
|
.rsN = {"di", "si", "bx", "bp"},
|
||||||
.rsS = {2, 2, 2},
|
.rsS = {2, 2, 2, 2},
|
||||||
},
|
},
|
||||||
[REG_CLASS_DATASEGS] = {
|
[REG_CLASS_DATASEGS] = {
|
||||||
.rMask = HWR_IND | HWR_BX,
|
.rMask = HWR_SEGREGS,
|
||||||
.rs = {HWR_DS, HWR_ES, HWR_FS, HWR_GS},
|
.rs = {HWR_DS, HWR_ES, HWR_FS, HWR_GS},
|
||||||
.rsN = {"ds", "es", "fs", "gs"},
|
.rsN = {"ds", "es", "fs", "gs"},
|
||||||
.rsS = {2, 2, 2},
|
.rsS = {2, 2, 2, 2},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,11 +17,12 @@
|
|||||||
#define HWR_DH 128
|
#define HWR_DH 128
|
||||||
#define HWR_DI 256
|
#define HWR_DI 256
|
||||||
#define HWR_SI 512
|
#define HWR_SI 512
|
||||||
|
#define HWR_BP 1024
|
||||||
|
|
||||||
#define HWR_DS 1024
|
#define HWR_DS 2048
|
||||||
#define HWR_ES 2048
|
#define HWR_ES 4096
|
||||||
#define HWR_FS 4096
|
#define HWR_FS 8192
|
||||||
#define HWR_GS 8192
|
#define HWR_GS 16384
|
||||||
|
|
||||||
#define HWR_AX (HWR_AL | HWR_AH)
|
#define HWR_AX (HWR_AL | HWR_AH)
|
||||||
#define HWR_BX (HWR_BL | HWR_BH)
|
#define HWR_BX (HWR_BL | HWR_BH)
|
||||||
@ -35,12 +36,15 @@
|
|||||||
|
|
||||||
#define HWR_EDI HWR_DI
|
#define HWR_EDI HWR_DI
|
||||||
#define HWR_ESI HWR_SI
|
#define HWR_ESI HWR_SI
|
||||||
|
#define HWR_EBP HWR_BP
|
||||||
|
|
||||||
#define HWR_GPR (HWR_EAX | HWR_EBX | HWR_ECX | HWR_EDX)
|
#define HWR_GPR (HWR_EAX | HWR_EBX | HWR_ECX | HWR_EDX | HWR_EDI | HWR_ESI | HWR_EBP)
|
||||||
#define HWR_IND (HWR_EDI | HWR_ESI)
|
#define HWR_IND (HWR_EDI | HWR_ESI)
|
||||||
#define HWR_ALL (HWR_GPR | HWR_IND)
|
#define HWR_ALL (HWR_GPR | HWR_IND)
|
||||||
|
|
||||||
#define MAX_REGS_PER_CLASS 12
|
#define HWR_SEGREGS (HWR_DS | HWR_ES | HWR_FS | HWR_GS)
|
||||||
|
|
||||||
|
#define MAX_REGS_PER_CLASS 16
|
||||||
typedef struct RegisterClass {
|
typedef struct RegisterClass {
|
||||||
uint32_t rMask;
|
uint32_t rMask;
|
||||||
uint16_t w;
|
uint16_t w;
|
||||||
@ -286,3 +290,16 @@ static inline WhysItBad_Huh x86_test_mul(AST *stmtPrev, AST *stmt) {
|
|||||||
|
|
||||||
return GUCCI;
|
return GUCCI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void arch_add_hidden_variables(Scope *scope) {
|
||||||
|
/*if(!scope_find(scope, "@seg_ds")) {
|
||||||
|
ScopeItem *si = calloc(1, sizeof(*si));
|
||||||
|
si->type = primitive_parse("u16");
|
||||||
|
si->kind = SCOPEITEM_VAR;
|
||||||
|
si->data.var.preclassed = true;
|
||||||
|
si->data.var.registerClass = REG_CLASS_DATASEGS;
|
||||||
|
si->data.var.precolored = true;
|
||||||
|
si->data.var.color = 0;
|
||||||
|
scope_set(scope, "@seg_ds", si);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
116
src/x86/cg.c
116
src/x86/cg.c
@ -215,11 +215,11 @@ static const char *xop(AST *tlc, AST *e) {
|
|||||||
return xop_sz(tlc, e, type_size(e->expression.type));
|
return xop_sz(tlc, e, type_size(e->expression.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ud_empty(ScopeItem *a) {
|
static int lr_empty(ScopeItem *a) {
|
||||||
assert(a->kind == SCOPEITEM_VAR);
|
assert(a->kind == SCOPEITEM_VAR);
|
||||||
assert(!a->data.var.usedefFirst == !a->data.var.usedefLast);
|
//assert(!a->data.var.liveRangeStart == !a->data.var.liveRangeEnd);
|
||||||
|
|
||||||
return !a->data.var.usedefFirst;
|
return !a->data.var.liveRangeStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cg_chunk(CGState *cg, AST *a) {
|
void cg_chunk(CGState *cg, AST *a) {
|
||||||
@ -250,61 +250,71 @@ void cg_chunk(CGState *cg, AST *a) {
|
|||||||
printf("align %u\n", val);
|
printf("align %u\n", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if(s->nodeKind == AST_STMT_DECL && s->stmtDecl.thing->kind == SCOPEITEM_SYMBOL) {
|
} else if(s->nodeKind == AST_STMT_DECL) {
|
||||||
|
|
||||||
ScopeItem *v = s->stmtDecl.thing;
|
ScopeItem *v = s->stmtDecl.thing;
|
||||||
|
|
||||||
if(v->data.symbol.isExternal) {
|
if(v->kind == SCOPEITEM_SYMBOL) {
|
||||||
// Do nothing.
|
|
||||||
// All external symbols are handled at once in the top-level chunk.
|
|
||||||
//printf("extern %s\n", v->data.symbol.name);
|
|
||||||
} else {
|
|
||||||
if(!v->data.symbol.isLocal) {
|
|
||||||
printf("global %s\n", v->data.symbol.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s->stmtDecl.expression) {
|
if(v->data.symbol.isExternal) {
|
||||||
printf("%s:", v->data.symbol.name);
|
// Do nothing.
|
||||||
if(v->type->type == TYPE_TYPE_PRIMITIVE) {
|
// All external symbols are handled at once in the top-level chunk.
|
||||||
|
//printf("extern %s\n", v->data.symbol.name);
|
||||||
|
} else {
|
||||||
|
if(!v->data.symbol.isLocal) {
|
||||||
|
printf("global %s\n", v->data.symbol.name);
|
||||||
|
}
|
||||||
|
|
||||||
assert(s->stmtDecl.expression->nodeKind == AST_EXPR_PRIMITIVE);
|
if(s->stmtDecl.expression) {
|
||||||
|
printf("%s:", v->data.symbol.name);
|
||||||
|
if(v->type->type == TYPE_TYPE_PRIMITIVE) {
|
||||||
|
|
||||||
printf("%s %i", direct(type_size(v->type)), s->stmtDecl.expression->exprPrim.val);
|
assert(s->stmtDecl.expression->nodeKind == AST_EXPR_PRIMITIVE);
|
||||||
|
|
||||||
} else if(v->type->type == TYPE_TYPE_ARRAY && v->type->array.of->type == TYPE_TYPE_PRIMITIVE) {
|
|
||||||
|
|
||||||
printf("%s ", direct(type_size(v->type->array.of)));
|
|
||||||
for(size_t i = 0; i < v->type->array.length; i++) {
|
|
||||||
printf("%i,", s->stmtDecl.expression->exprArray.items[i]->exprPrim.val);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(v->type->type == TYPE_TYPE_FUNCTION) {
|
|
||||||
|
|
||||||
putchar('\n');
|
|
||||||
|
|
||||||
assert(s->stmtDecl.expression->nodeKind == AST_EXPR_FUNC);
|
|
||||||
|
|
||||||
// Generic functions have non-NULL code blocks
|
|
||||||
if(!type_is_generic(s->stmtDecl.expression->expression.type)) {
|
|
||||||
|
|
||||||
ast_sroa(s->stmtDecl.expression->exprFunc.chunk);
|
printf("%s %i", direct(type_size(v->type)), s->stmtDecl.expression->exprPrim.val);
|
||||||
|
|
||||||
dumben_pre(s->stmtDecl.expression->exprFunc.chunk);
|
} else if(v->type->type == TYPE_TYPE_ARRAY && v->type->array.of->type == TYPE_TYPE_PRIMITIVE) {
|
||||||
|
|
||||||
dumben_go(s->stmtDecl.expression->exprFunc.chunk);
|
printf("%s ", direct(type_size(v->type->array.of)));
|
||||||
while(!cg_go(s->stmtDecl.expression->exprFunc.chunk)) {
|
for(size_t i = 0; i < v->type->array.length; i++) {
|
||||||
dumben_go(s->stmtDecl.expression->exprFunc.chunk);
|
printf("%i,", s->stmtDecl.expression->exprArray.items[i]->exprPrim.val);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else if(v->type->type == TYPE_TYPE_FUNCTION) {
|
||||||
|
|
||||||
} else abort();
|
putchar('\n');
|
||||||
putchar('\n');
|
|
||||||
} else {
|
assert(s->stmtDecl.expression->nodeKind == AST_EXPR_FUNC);
|
||||||
|
|
||||||
printf("%s resb %lu\n", v->data.symbol.name, type_size(s->stmtDecl.thing->type));
|
// Generic functions have non-NULL code blocks
|
||||||
|
if(!type_is_generic(s->stmtDecl.expression->expression.type)) {
|
||||||
|
|
||||||
|
ast_segmented_dereference(s->stmtDecl.expression->exprFunc.chunk);
|
||||||
|
|
||||||
|
ast_sroa(s->stmtDecl.expression->exprFunc.chunk);
|
||||||
|
|
||||||
|
dumben_pre(s->stmtDecl.expression->exprFunc.chunk);
|
||||||
|
|
||||||
|
dumben_go(s->stmtDecl.expression->exprFunc.chunk);
|
||||||
|
while(!cg_go(s->stmtDecl.expression->exprFunc.chunk)) {
|
||||||
|
dumben_go(s->stmtDecl.expression->exprFunc.chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else abort();
|
||||||
|
putchar('\n');
|
||||||
|
} else {
|
||||||
|
|
||||||
|
printf("%s resb %lu\n", v->data.symbol.name, type_size(s->stmtDecl.thing->type));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if(v->kind == SCOPEITEM_VAR) {
|
||||||
|
assert(s->stmtDecl.expression == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if(s->nodeKind == AST_STMT_ASSIGN && s->stmtAssign.to && s->stmtAssign.what->nodeKind == AST_EXPR_VAR && s->stmtAssign.what->exprVar.thing->kind == SCOPEITEM_VAR && s->stmtAssign.to->nodeKind == AST_EXPR_CALL) {
|
} else if(s->nodeKind == AST_STMT_ASSIGN && s->stmtAssign.to && s->stmtAssign.what->nodeKind == AST_EXPR_VAR && s->stmtAssign.what->exprVar.thing->kind == SCOPEITEM_VAR && s->stmtAssign.to->nodeKind == AST_EXPR_CALL) {
|
||||||
|
|
||||||
AST *e = s->stmtAssign.to;
|
AST *e = s->stmtAssign.to;
|
||||||
@ -502,13 +512,13 @@ typedef ScopeItem *Adjacency[2];
|
|||||||
|
|
||||||
static bool var_collision(AST *tlc, ScopeItem *v1, ScopeItem *v2) {
|
static bool var_collision(AST *tlc, ScopeItem *v1, ScopeItem *v2) {
|
||||||
/* 1D intersection test */
|
/* 1D intersection test */
|
||||||
bool liveRangeIntersection = !ud_empty(v1) && !ud_empty(v2) && (
|
bool liveRangeIntersection = !lr_empty(v1) && !lr_empty(v2) && (v1->data.var.liveRangeStart == v2->data.var.liveRangeStart || (
|
||||||
(ast_stmt_is_after(tlc, v1->data.var.usedefFirst->stmt, v2->data.var.usedefFirst->stmt) == 1
|
(ast_stmt_is_after(tlc, v1->data.var.liveRangeStart, v2->data.var.liveRangeStart) == 1
|
||||||
&& ast_stmt_is_after(tlc, v2->data.var.usedefLast->stmt, v1->data.var.usedefFirst->stmt) == 1)
|
&& ast_stmt_is_after(tlc, v2->data.var.liveRangeEnd, v1->data.var.liveRangeStart) == 1)
|
||||||
||
|
||
|
||||||
(ast_stmt_is_after(tlc, v1->data.var.usedefLast->stmt, v2->data.var.usedefFirst->stmt) == 1
|
(ast_stmt_is_after(tlc, v1->data.var.liveRangeEnd, v2->data.var.liveRangeStart) == 1
|
||||||
&& ast_stmt_is_after(tlc, v2->data.var.usedefLast->stmt, v1->data.var.usedefLast->stmt) == 1)
|
&& ast_stmt_is_after(tlc, v2->data.var.liveRangeEnd, v1->data.var.liveRangeEnd) == 1)
|
||||||
);
|
));
|
||||||
|
|
||||||
bool resourceIntersection = (REG_CLASSES[v1->data.var.registerClass].rMask & REG_CLASSES[v2->data.var.registerClass].rMask) != 0;
|
bool resourceIntersection = (REG_CLASSES[v1->data.var.registerClass].rMask & REG_CLASSES[v2->data.var.registerClass].rMask) != 0;
|
||||||
|
|
||||||
@ -840,7 +850,7 @@ cont:;
|
|||||||
|
|
||||||
ScopeItem *chosen = NULL;
|
ScopeItem *chosen = NULL;
|
||||||
for(ssize_t i = a->chunk.varCount - 1; i >= 0; i--) {
|
for(ssize_t i = a->chunk.varCount - 1; i >= 0; i--) {
|
||||||
if(!vars[i]->data.var.precolored && vars[i]->data.var.registerClass == mustSpillRegisterClass) {
|
if(vars[i]->data.var.registerClass == mustSpillRegisterClass && !vars[i]->data.var.precolored) {
|
||||||
chosen = vars[i];
|
chosen = vars[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -85,11 +85,14 @@ static void mark_ptr(AST *a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct DumbenState {
|
struct DumbenState {
|
||||||
|
AST *targetTLC;
|
||||||
int effective;
|
int effective;
|
||||||
};
|
};
|
||||||
static void dumben_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, void *ud) {
|
static void dumben_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, void *ud) {
|
||||||
struct DumbenState *this = ud;
|
struct DumbenState *this = ud;
|
||||||
|
|
||||||
|
if(this->targetTLC != tlc) return;
|
||||||
|
|
||||||
AST *s = *nptr;
|
AST *s = *nptr;
|
||||||
|
|
||||||
if(s->nodeKind == AST_STMT_IF) {
|
if(s->nodeKind == AST_STMT_IF) {
|
||||||
@ -540,13 +543,19 @@ void dumben_pre(AST *tlc) {
|
|||||||
free(astdump);
|
free(astdump);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success;
|
struct DenoopState state = {.targetTLC = tlc};
|
||||||
do {
|
do {
|
||||||
success = false;
|
state.success = false;
|
||||||
generic_visitor(&tlc, NULL, NULL, tlc, tlc, &success, denoop_visitor, NULL);
|
generic_visitor(&tlc, NULL, NULL, tlc, tlc, &state, denoop_visitor, NULL);
|
||||||
} while(success);
|
} while(state.success);
|
||||||
|
|
||||||
ast_commutativity_pass(tlc);
|
ast_commutativity_pass(tlc);
|
||||||
|
|
||||||
|
if(ntc_get_int("pdbg")) {
|
||||||
|
char *astdump = ast_dump(tlc);
|
||||||
|
fprintf(stderr, "### AFTER DENOOP ###\n%s\n", astdump);
|
||||||
|
free(astdump);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumben_go(AST* tlc) {
|
void dumben_go(AST* tlc) {
|
||||||
@ -556,8 +565,7 @@ void dumben_go(AST* tlc) {
|
|||||||
stahp(0, 0, "TOO MANY DUMBS. TOO MANY DUMBS.");
|
stahp(0, 0, "TOO MANY DUMBS. TOO MANY DUMBS.");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DumbenState state;
|
struct DumbenState state = {.targetTLC = tlc};
|
||||||
memset(&state, 0, sizeof(state));
|
|
||||||
|
|
||||||
generic_visitor(&tlc, NULL, NULL, tlc, tlc, &state, dumben_visitor, NULL);
|
generic_visitor(&tlc, NULL, NULL, tlc, tlc, &state, dumben_visitor, NULL);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user