Skip to content

Commit 725a58a

Browse files
author
razziana
committed
Full function stack and x86 core merge.
1 parent 921af2d commit 725a58a

24 files changed

+1440
-97
lines changed

visscript-hackground/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CC = gcc
22
CFLAGS = -O6 -ggdb3 -Wall
33
LIBS = `pkg-config --cflags --libs libvisual`
44

5-
OBJS = avs_lexer.o avs_parser.o avs_test.o avs_compiler.o avs_il_tree.o avs_il_assembler.o avs_runnable.o avs_functions.o avs_stack.o avs_blob.o avs_blob_pool.o avs_x86_opcode.o avs_il_register.o avs_il_instruction.o avs_ix_compiler.o avs_ix_machine.o avs_il_core.o avs_x86_compiler.o
5+
OBJS = avs_lexer.o avs_parser.o avs_test.o avs_compiler.o avs_il_tree.o avs_il_assembler.o avs_runnable.o avs_functions.o avs_stack.o avs_blob.o avs_blob_pool.o avs_x86_opcode.o avs_il_register.o avs_il_instruction.o avs_ix_compiler.o avs_ix_machine.o avs_il_core.o avs_x86_compiler.o avs_il_tree_node.o
66

77
#avs_x86_opcode.o avs_x86_assembler.o
88

visscript-hackground/avs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ struct _AvsRunnable;
1717
typedef struct _AvsRunnable AvsRunnable;
1818
struct _AvsRunnableVariable;
1919
typedef struct _AvsRunnableVariable AvsRunnableVariable;
20+
struct _AvsRunnableFunction;
21+
typedef struct _AvsRunnableFunction AvsRunnableFunction;
2022

2123
/* Internal numeric representation */
2224
typedef float AvsNumber;

visscript-hackground/avs_functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ AVS_BUILTIN_FUNCTION(rand, 0xdeadbeaf * *args[0]);
3636
AVS_BUILTIN_FUNCTION(band, AVS_VALUEBOOL(*args[0]) && AVS_VALUEBOOL(*args[1]));
3737
AVS_BUILTIN_FUNCTION(bor, AVS_VALUEBOOL(*args[0]) || AVS_VALUEBOOL(*args[1]));
3838
AVS_BUILTIN_FUNCTION(bnot, !AVS_VALUEBOOL(*args[0]));
39-
AVS_BUILTIN_FUNCTION(equal, AVS_VALUEBOOL(*args[0] - *args[1]) ? 1.0 : 0.0)
39+
AVS_BUILTIN_FUNCTION(equal, AVS_VALUEBOOL(*args[0] - *args[1]) ? 0.0 : 1.0)
4040
AVS_BUILTIN_FUNCTION(above, *args[0] > *args[1] ? 1.0 : 0.0)
4141
AVS_BUILTIN_FUNCTION(below, *args[0] < *args[1] ? 1.0 : 0.0)
4242

visscript-hackground/avs_il_assembler.c

Lines changed: 302 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,265 @@
66

77
#include "avs.h"
88

9+
static int emit_assign(
10+
AvsILAssemblerContext *ctx,
11+
AvsRunnable *obj,
12+
AvsCompilerInstruction insn,
13+
AvsCompilerArgument *retval,
14+
AvsCompilerArgument *args,
15+
int count)
16+
{
17+
ILRegister *reg[3];
18+
ILInstruction *is;
19+
20+
reg[1] = avs_il_register_load_from_argument(ctx, obj, &args[0]);
21+
reg[2] = avs_il_register_load_from_argument(ctx, obj, &args[1]);
22+
reg[0] = avs_il_register_load_worker(ctx, obj, retval);
23+
24+
if (reg[1]->flags & ILRegisterPointer)
25+
is = avs_il_instruction_emit_triplet(ctx, obj, ILInstructionStoreReference, reg[0], reg[1], reg[2]);
26+
else
27+
is = avs_il_instruction_emit_triplet(ctx, obj, ILInstructionAssign, reg[0], reg[1], reg[2]);
28+
29+
avs_il_tree_add(&ctx->tree, is);
30+
return VISUAL_OK;
31+
}
32+
33+
static int emit_loop(
34+
AvsILAssemblerContext *ctx,
35+
AvsRunnable *obj,
36+
AvsCompilerInstruction insn,
37+
AvsCompilerArgument *retval,
38+
AvsCompilerArgument *args,
39+
int count)
40+
{
41+
AvsILTreeNodeIterator iter;
42+
AvsILTreeNode *base;
43+
ILRegister *pds, *lhs, *rhs;
44+
ILInstruction *is, *iloop, *mm;
45+
int argc;
46+
47+
48+
argc = avs_il_tree_node_level_count(&ctx->tree);
49+
avs_debug(print("il: Loop function, dumping argument context (count: %d)", argc));
50+
51+
if(argc < 2) {
52+
avs_debug(print("il: Need more parameters for 'loop' function"));
53+
exit(1);
54+
}
55+
56+
/* Level down */
57+
avs_il_tree_node_level_down(&ctx->tree, &iter);
58+
59+
/* Retrieve stack variables, order IS important */
60+
lhs = avs_il_register_load_from_argument(ctx, obj, &args[1]);
61+
rhs = avs_il_register_load_from_argument(ctx, obj, &args[2]);
62+
pds = avs_il_register_load_worker(ctx, obj, retval);
63+
64+
/* Load counter */
65+
avs_il_tree_merge(&ctx->tree, avs_il_tree_node_iterator_next(&iter));
66+
iloop = avs_il_instruction_emit_twin(ctx, obj, ILInstructionLoopInit, pds, lhs);
67+
avs_il_tree_add(&ctx->tree, iloop);
68+
69+
/* Merge loop statement */
70+
base = avs_il_tree_node_iterator_next(&iter);
71+
if (!base) {
72+
fprintf(stderr, "No loop statement to execute!\n");
73+
exit(1);
74+
}
75+
avs_il_tree_merge(&ctx->tree, base);
76+
77+
/* Emit loop instruction */
78+
is = avs_il_instruction_emit(ctx, obj, ILInstructionLoop);
79+
is->ex.jmp.pointer = base->insn.base;
80+
avs_il_tree_add(&ctx->tree, is);
81+
82+
/* Emit merge marker */
83+
mm = avs_il_instruction_emit(ctx, obj, ILInstructionMergeMarker);
84+
mm->ex.merge.type = AvsILInstructionMergeTypeLoop;
85+
mm->ex.merge.from[0] = iloop;
86+
mm->ex.merge.from[1] = base->insn.base;
87+
mm->ex.merge.from[2] = is;
88+
avs_il_tree_add(&ctx->tree, mm);
89+
90+
return VISUAL_OK;
91+
}
92+
93+
static int emit_if(
94+
AvsILAssemblerContext *ctx,
95+
AvsRunnable *obj,
96+
AvsCompilerInstruction insn,
97+
AvsCompilerArgument *retval,
98+
AvsCompilerArgument *args,
99+
int count)
100+
{
101+
AvsILTreeNodeIterator iter;
102+
AvsILTreeNode *base[3];
103+
ILRegister *reg[4];
104+
ILInstruction *jpt0, *jpt1, *mm;
105+
int argc;
106+
107+
argc = avs_il_tree_node_level_count(&ctx->tree);
108+
avs_debug(print("il: If function, dumpring argument context (count: %d)", argc));
109+
110+
if (argc < 3) {
111+
avs_debug(print("il: Need more parameters for 'if' function"));
112+
exit(1);
113+
}
114+
115+
/* Level down */
116+
avs_il_tree_node_level_down(&ctx->tree, &iter);
117+
118+
/* Retrieve stack variables, order IS important */
119+
reg[1] = avs_il_register_load_from_argument(ctx, obj, &args[1]);
120+
reg[2] = avs_il_register_load_from_argument(ctx, obj, &args[2]);
121+
reg[3] = avs_il_register_load_from_argument(ctx, obj, &args[3]);
122+
reg[0] = avs_il_register_load_worker(ctx, obj, retval);
123+
124+
/* Load instruction contexts */
125+
base[0] = avs_il_tree_node_iterator_next(&iter);
126+
base[1] = avs_il_tree_node_iterator_next(&iter);
127+
base[2] = avs_il_tree_node_iterator_next(&iter);
128+
129+
/* Merge condition statement */
130+
avs_il_tree_merge(&ctx->tree, base[0]);
131+
132+
/* Jump to valtrue or valfalse statement */
133+
jpt0 = avs_il_instruction_emit_single(ctx, obj, ILInstructionJumpTrue, reg[1]);
134+
avs_il_tree_add(&ctx->tree, jpt0);
135+
136+
/* Handle special case of assign(if(..., x, y), ...) */
137+
if (!base[1]->insn.base && !base[2]->insn.base) {
138+
reg[0]->flags |= ILRegisterPointer;
139+
140+
/* Emit valfalse statement */
141+
avs_il_tree_add(&ctx->tree, avs_il_instruction_emit_twin(ctx, obj, ILInstructionLoadReference, reg[0], reg[3]));
142+
jpt1 = avs_il_instruction_emit(ctx, obj, ILInstructionJump);
143+
avs_il_tree_add(&ctx->tree, jpt1);
144+
145+
/* Emit valtrue statement */
146+
avs_il_tree_add(&ctx->tree, avs_il_instruction_emit_twin(ctx, obj, ILInstructionLoadReference, reg[0], reg[2]));
147+
jpt0->ex.jmp.pointer = ctx->tree.current->insn.end;
148+
149+
/* Emit merge marker */
150+
mm = avs_il_instruction_emit(ctx, obj, ILInstructionMergeMarker);
151+
avs_il_tree_add(&ctx->tree, mm);
152+
jpt1->ex.jmp.pointer = mm;
153+
mm->ex.merge.type = AvsILInstructionMergeTypeJumpConditional;
154+
mm->ex.merge.from[0] = jpt1;
155+
return VISUAL_OK;
156+
}
157+
158+
/* Emit valfalse statement */
159+
avs_il_tree_merge(&ctx->tree, base[2]);
160+
avs_il_tree_add(&ctx->tree, avs_il_instruction_emit_triplet(ctx, obj, ILInstructionAssign, reg[0], reg[3], reg[3]));
161+
jpt1 = avs_il_instruction_emit(ctx, obj, ILInstructionJump);
162+
avs_il_tree_add(&ctx->tree, jpt1);
163+
164+
/* Emit valtrue statement */
165+
avs_il_tree_merge(&ctx->tree, base[1]);
166+
avs_il_tree_add(&ctx->tree, avs_il_instruction_emit_triplet(ctx, obj, ILInstructionAssign, reg[0], reg[2], reg[2]));
167+
jpt0->ex.jmp.pointer = base[1]->insn.base;
168+
169+
/* Emit merge marker */
170+
mm = avs_il_instruction_emit(ctx, obj, ILInstructionMergeMarker);
171+
avs_il_tree_add(&ctx->tree, mm);
172+
jpt1->ex.jmp.pointer = mm;
173+
mm->ex.merge.type = AvsILInstructionMergeTypeJumpConditional;
174+
mm->ex.merge.from[0] = jpt1;
175+
176+
return VISUAL_OK;
177+
}
178+
179+
static void emit_trampoline(
180+
AvsILAssemblerContext *ctx,
181+
AvsRunnable *obj,
182+
AvsCompilerArgument *retval,
183+
AvsCompilerArgument *args,
184+
int count,
185+
AvsRunnableFunction *fn)
186+
{
187+
ILInstruction *insn;
188+
ILRegister *reg;
189+
int i;
190+
191+
/* Note: retrieving the result value before retrieving the function arguments
192+
* is normally dangerous, because it'll overwrite the first argument.
193+
* but since the first stack value is equal to the function name
194+
* it isn't a problem in this instance. */
195+
reg = avs_il_register_load_worker(ctx, obj, retval);
196+
insn = avs_il_instruction_emit_single(ctx, obj, ILInstructionCall, reg);
197+
198+
insn->ex.call.call = fn;
199+
insn->ex.call.argc = count - 1;
200+
insn->ex.call.argv = malloc(sizeof(ILRegister **) * insn->ex.call.argc);
201+
202+
/* Load function arguments */
203+
for (i=1; i < count; i++)
204+
insn->ex.call.argv[i-1] = avs_il_register_load_from_argument(ctx, obj, &args[i]);
205+
206+
avs_il_tree_add(&ctx->tree, insn);
207+
return;
208+
}
209+
210+
static int emit_call(
211+
AvsILAssemblerContext *ctx,
212+
AvsRunnable *obj,
213+
AvsCompilerInstruction insn,
214+
AvsCompilerArgument *retval,
215+
AvsCompilerArgument *args,
216+
int count)
217+
{
218+
AvsBuiltinFunctionType type;
219+
char *name;
220+
221+
/* Retrieve function name from compiler argument stack */
222+
name = args[0].value.identifier;
223+
type = avs_builtin_function_type(name);
224+
225+
switch (type) {
226+
case AVS_BUILTIN_FUNCTION_ASSIGN:
227+
emit_assign(ctx, obj, insn, retval, args + 1, count - 1);
228+
break;
229+
230+
case AVS_BUILTIN_FUNCTION_EXEC2:
231+
*retval = args[2];
232+
break;
233+
234+
case AVS_BUILTIN_FUNCTION_EXEC3:
235+
*retval = args[3];
236+
break;
237+
238+
case AVS_BUILTIN_FUNCTION_LOOP:
239+
emit_loop(ctx, obj, insn, retval, args, count);
240+
break;
241+
242+
case AVS_BUILTIN_FUNCTION_IF:
243+
emit_if(ctx, obj, insn, retval, args, count);
244+
break;
245+
246+
default: {
247+
AvsRunnableFunction *fn = avs_builtin_function_lookup(type);
248+
if (!fn)
249+
avs_debug(print("il: Unable to find builtin function: %s", name));
250+
251+
if (fn->param_count && fn->param_count != count - 1) {
252+
avs_debug(print("il: Incorrect parameter count for function: %s, needed: %d parameters, received: %d parameters",
253+
fn->name, fn->param_count, count - 1));
254+
exit(1);
255+
}
256+
257+
avs_debug(print("il: Call to function: %s", fn->name));
258+
emit_trampoline(ctx, obj, retval, args, count, fn);
259+
}
260+
}
261+
262+
/* Descrese nesting level */
263+
ctx->nestlevel--;
264+
265+
return VISUAL_OK;
266+
}
267+
9268
/**
10269
* Emit a single compiler instruction to IL Assembler.
11270
*
@@ -31,12 +290,25 @@ int avs_il_emit_instruction(
31290
break;
32291

33292
case AvsCompilerInstructionCall:
293+
emit_call(ctx, obj, insn, retval, args, count);
34294
break;
35295

36-
case AvsCompilerInstructionNegate:
296+
case AvsCompilerInstructionNegate: {
297+
ILRegister *pds, *rhs;
298+
299+
rhs = avs_il_register_load_from_argument(ctx, obj, &args[0]);
300+
pds = avs_il_register_load_worker(ctx, obj, retval);
301+
302+
avs_il_tree_add(&ctx->tree,
303+
avs_il_instruction_emit_twin(ctx, obj, ILInstructionNegate,
304+
pds, rhs));
37305
break;
38-
306+
}
307+
39308
case AvsCompilerInstructionAssign:
309+
emit_assign(ctx, obj, insn, retval, args, count);
310+
break;
311+
40312
case AvsCompilerInstructionAdd:
41313
case AvsCompilerInstructionSub:
42314
case AvsCompilerInstructionMul:
@@ -92,9 +364,32 @@ int avs_il_emit_marker(
92364
{
93365
switch (marker) {
94366
case AvsCompilerMarkerFunction:
367+
/* Function marker: notifies start of function (and thus function argumentation) */
368+
avs_debug(print("il: Function marker for function: %s", name));
369+
ctx->nestlevel++;
370+
371+
switch (avs_builtin_function_type(name)) {
372+
case AVS_BUILTIN_FUNCTION_IF:
373+
case AVS_BUILTIN_FUNCTION_LOOP:
374+
avs_debug(print("il: Function marker: leveling-up!"));
375+
avs_il_tree_node_level_up(&ctx->tree, AvsILTreeNodeTypeFunction);
376+
avs_il_tree_node_level_mark(&ctx->tree, ctx->nestlevel);
377+
break;
378+
379+
default:
380+
break;
381+
}
95382
break;
96383

97384
case AvsCompilerMarkerArgument:
385+
avs_debug(print("il: Argument marker: nestlevel = %d, level depth = %d, mark = %d",
386+
ctx->nestlevel, avs_il_tree_node_level_depth(&ctx->tree),
387+
avs_il_tree_node_level_get_mark(&ctx->tree)));
388+
if (!ctx->nestlevel || ctx->nestlevel != avs_il_tree_node_level_get_mark(&ctx->tree))
389+
break;
390+
391+
avs_debug(print("il: Argument marker!"));
392+
avs_il_tree_node_up(&ctx->tree, AvsILTreeNodeTypeFunctionArgument);
98393
break;
99394

100395
case AvsCompilerMarkerSequencePoint:
@@ -136,13 +431,15 @@ int avs_il_runnable_finish(AvsILAssemblerContext *ctx, AvsRunnable *obj)
136431
{
137432
ILInstruction *insn;
138433
static char *insnname[] = {
139-
"nop", "load", "loadconstant", "negate", "assign",
140-
"add", "sub", "mul", "div", "mod", "and", "or", "count"
434+
"nop", "call", "negate", "assign",
435+
"add", "sub", "mul", "div", "mod", "and", "or",
436+
"loopinit", "loop", "jump", "jumptrue", "mergemarker",
437+
"loadreference", "storereference", "count"
141438
};
142439

143440
avs_print("il: finished! (count: %d)", (ILInstruction*)avs_stack_end(ctx->tree.ixstack) - (ILInstruction*)avs_stack_begin(ctx->tree.ixstack));
144441

145-
for (insn=ctx->tree.base; insn != NULL; insn = insn->next) {
442+
for (insn=avs_il_tree_base(&ctx->tree); insn != NULL; insn = insn->next) {
146443
avs_print("il: instruction %p %s %p, %p, %p", insn, insnname[insn->type], insn->reg[0], insn->reg[1], insn->reg[2]);
147444

148445
}

0 commit comments

Comments
 (0)