view runtime/builtinworkers.c @ 186:ba35ab624ec2

Add support for raw C function output from C backend as well as an option to use Boehm-GC instead of reference counting
author Mike Pavone <pavone@retrodev.com>
date Fri, 07 Oct 2011 00:10:02 -0700
parents e57c151f351e
children
line wrap: on
line source

Func(Build,
	NumParams 1,
	NumOutputs 1)
	
	Param(0, TYPE_BLUEPRINT)
	
	lv(Build, bp) = ((t_Blueprint *)(my_params(0)))->bp;
	release_ref(my_params(0));
	
	Ret(0, new_object_bp(lv(Build, bp)))
EndFunc(Build)
DISPATCH

Func(BlueprintSP_Of,
	NumParams 1,
	NumOutputs 1)
	
	lv(BlueprintSP_Of, bp) = get_blueprint(my_params(0));
	release_ref(my_params(0));
	
	Ret(0, new_object(TYPE_BLUEPRINT))
	((t_Blueprint *)my_outputs(0))->bp = lv(BlueprintSP_Of, bp);
EndFunc(BlueprintSP_Of)
DISPATCH

Func(ID, NumParams 1, NumOutputs 1)

	Param(0, TYPE_BLUEPRINT)

	lv(ID, id) = new_object(TYPE_UINT32);
	((t_UInt32 *)lv(ID, id))->Num = ((t_Blueprint *)my_params(0))->bp->type_id;
	release_ref(my_params(0));
	Ret(0, lv(ID, id))
EndFunc(ID)
DISPATCH

Func(BlueprintSP_FromSP_ID, NumParams 1, NumOutputs 2)

	Param(0, TYPE_UINT32)

	lv(BlueprintSP_FromSP_ID, type) = ((t_UInt32 *)my_params(0))->Num;
	if (lv(BlueprintSP_FromSP_ID, type) >= max_registered_type || !registered_types[lv(BlueprintSP_FromSP_ID, type)]) {
		Ret(1, my_params(0))
		Ret(0, NULL)
	} else {
		release_ref(my_params(0));	
		Ret(0, new_object(TYPE_BLUEPRINT))
		((t_Blueprint *)my_outputs(0))->bp = registered_types[lv(BlueprintSP_FromSP_ID, type)];
		Ret(1, NULL)
	}
	
EndFunc(BlueprintSP_FromSP_ID)
DISPATCH

#ifndef RAW_FUNC
FuncNoLocals(Pause, NumParams 1, NumOutputs 1)
	Param(0, TYPE_WORKER)

	ct->resume_cdata = my_cdata;
	ct->resumeable = 1;
	temp_ct = ct;
	ct = new_context();
	VCPrepCall(my_cdata->params[0], 1)
	VCSetParam(my_cdata->params[0], 0, make_Context(temp_ct))
	ValCallNoLocals(my_cdata->params[0], 1, 1, Pause)
	release_ref(my_cdata->params[0]);
	DISPATCH
	ValCallNoLocalsPostlude(1, Pause)
	for(idx = 0; idx < cdata->num_params; ++idx)
		if(cdata->params[idx])
		{ release_ref(cdata->params[idx]); }
	free_context(ct);
	ct = get_cqueue();
	if (!ct) goto NOTHING_TO_DO;
	cdata = ct->resume_cdata;
	ct->resume_cdata = NULL;
EndFuncNoLocals
DISPATCH

FuncNoLocals(Resume, NumParams 2, NumOutputs 2)
	Param(0, TYPE_CONTEXT)

	temp_ct = ((t_Context *)my_cdata->params[0])->ct;
	release_ref(my_cdata->params[0]);
	if(temp_ct->resumeable && temp_ct->resume_cdata)
	{
		temp_ct->resumeable = 0;
		temp_ct->resume_cdata->params[0] = add_ref(my_cdata->params[1]);
		my_cdata->params[0] = my_cdata->params[1];
		my_cdata->params[1] = NULL;
		if(!put_cqueue(temp_ct))
		{
			ct->resume_cdata = my_cdata;
			temp_ct->runafter = ct;
			ct = temp_ct;
			cdata = ct->resume_cdata;
			ct->resume_cdata = NULL;
		}
	} else {
		my_cdata->params[0] = NULL;
	}
EndFuncNoLocals
DISPATCH

f_RunSP_Bytecode:
sf_RunSP_Bytecode:
	Param(0, TYPE_ARRAY)
	Param(1, TYPE_BOXEDARRAY)

	if(((t_Array *)cdata->params[0])->payload.Eltype->bp->type_id != TYPE_UINT32)
	{
		printf("Array has element type of %d, but bytecode must be an array with element type UInt32\n", ((t_Array *)cdata->params[0])->payload.Eltype->bp->type_id);
		goto _exception;
	}
	my_cdata = cdata;
	bytecode = (uint32_t *)(((t_Array *)cdata->params[0])+1);
	for(idx = 2; idx < (bytecode[0]+2); ++idx)
		if(bytecode[idx+1])
		{
			Param(idx, bytecode[idx+1])
		}
	cur_instruction = bytecode+idx;
	while(idx < cdata->num_params)
		release_ref(cdata->params[idx++]);
	cdata->num_params = bytecode[0];
	interp_consts = (object **)(((t_BoxedSP_Array *)cdata->params[1])+1);
	lv_RunSP_Bytecode = alloc_stack(ct, sizeof(object *)*(bytecode[1]+1+bytecode[0]));
	memcpy(lv_RunSP_Bytecode + 1, cdata->params+2, bytecode[0]*sizeof(object *));
	
	PrepCall(bytecode[2])
	
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_call:
	*lv_RunSP_Bytecode = cur_instruction;
	
	cdata->func = RES_1_RunSP_Bytecode;
	cdata->num_params = *cur_instruction >> 24;
	cdata->vars = lv_RunSP_Bytecode;
	func = *cur_instruction >> 4 & 0xFFFFF;
	DISPATCH
r1_RunSP_Bytecode:
	my_cdata = cdata->lastframe;
	lv_RunSP_Bytecode = cdata->vars;
	
	interp_consts = (object **)(((t_BoxedSP_Array *)my_cdata->params[1])+1);
	cur_instruction = *lv_RunSP_Bytecode;
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_param:
	op1 = (*cur_instruction >> 4) & 0x3FFF;
	SetParam(*cur_instruction >> 24, op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1])
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_load:
	op1 = (*cur_instruction >> 4) & 0x3FFF;
	accum = op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1];
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_and:
	op1 = (*cur_instruction >> 4) & 0x3FFF;
	op2 = *cur_instruction >> 18;
	if (!op1)
	{
		accum = accum && (op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2]);
	} else {
		accum = (op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1]) && (op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2]);
	}
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_or:
	op1 = (*cur_instruction >> 4) & 0x3FFF;
	op2 = *cur_instruction >> 18;
	if (!op1)
	{
		accum = accum || (op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2]);
	} else {
		accum = (op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1]) || (op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2]);
	}
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_not:
	accum = !accum;
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_branch:
	if (!accum)
		if (*cur_instruction & 0x10)
			cur_instruction -= *cur_instruction >> 5;
		else
			cur_instruction += *cur_instruction >> 5;
	else
		cur_instruction++;
	goto *interp_dispatch[*cur_instruction&0xF];
interp_saveresult:
	op1 = (*cur_instruction >> 4) & 0x1FFF;
	lv_RunSP_Bytecode[op1] = cdata->params[*cur_instruction >> 24];
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_addref:
	op1 = (*cur_instruction >> 4) & 0x3FFF;
	add_ref(op1 >= 0x2000 ? interp_consts[op1-0x2000] : (object *)lv_RunSP_Bytecode[op1]);
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_release:
	op1 = (*cur_instruction >> 4) & 0x3FFF;
	release_ref(op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1]);
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_move:
	op1 = (*cur_instruction >> 4) & 0x1FFF;
	op2 = *cur_instruction >> 18;
	if (op1)
		lv_RunSP_Bytecode[op1] = op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2];
	else
		accum = op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2];
	goto *interp_dispatch[*(++cur_instruction)&0xF];
interp_nop:
	goto *interp_dispatch[*(++cur_instruction)&0xF];	
interp_return:
	FreeCall
	release_ref(my_cdata->params[0]);
	release_ref(my_cdata->params[1]);
	op1 = (*cur_instruction >> 4) & 0x3FFF;
	op2 = *cur_instruction >> 24;
	for (idx = 0; idx < op2; ++idx)
	{
		Ret(idx, lv_RunSP_Bytecode[op1+idx])
	}
EndFunc(RunSP_Bytecode)
DISPATCH
#else
FuncNoLocals(Pause, NumParams 1, NumOutputs 0)
	exit(2);
EndFuncNoLocals

FuncNoLocals(Resume, NumParams 2, NumOutputs 0)
	exit(2);
EndFuncNoLocals

FuncNoLocals(RunSP_Bytecode, NumParams 2, NumOutputs 0)
	exit(2);
EndFuncNoLocals
#endif //RAW_FUNC