⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slang_assemble.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	}

	slang_storage_aggregate_construct (&agg);
	if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs))
	{
		slang_storage_aggregate_destruct (&agg);
		slang_assembly_typeinfo_destruct (&ti);
		return 0;
	}

	size = _slang_sizeof_aggregate (&agg);
	result = dereference_aggregate (file, &agg, 0, &size, info);

	slang_storage_aggregate_destruct (&agg);
	slang_assembly_typeinfo_destruct (&ti);
	return result;
}

static int call_function (slang_assembly_file *file, slang_function *fun, slang_operation *params,
	unsigned int param_count, int assignment, slang_assembly_name_space *space,
	slang_assembly_local_info *info)
{
	unsigned int i;
	slang_assembly_stack_info stk;

	/* make room for the return value, if any */
	if (fun->header.type.specifier.type != slang_spec_void)
	{
		unsigned int ret_size = 0;
		if (!sizeof_variable (&fun->header.type.specifier, slang_qual_none, NULL, space, &ret_size))
			return 0;
		if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, ret_size))
			return 0;
	}

	/* push the actual parameters on the stack */
	for (i = 0; i < param_count; i++)
	{
		slang_assembly_flow_control flow;

		if (fun->parameters->variables[i].type.qualifier == slang_qual_inout ||
			fun->parameters->variables[i].type.qualifier == slang_qual_out)
		{
			if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp, 4))
				return 0;
			/* TODO: optimize the "out" parameter case */
			/* TODO: inspect stk */
			if (!_slang_assemble_operation (file, params + i, 1, &flow, space, info, &stk))
				return 0;
			if (!slang_assembly_file_push (file, slang_asm_addr_copy))
				return 0;
			if (!slang_assembly_file_push (file, slang_asm_addr_deref))
				return 0;
			if (i == 0 && assignment)
			{
				if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp,
					4))
					return 0;
				if (!slang_assembly_file_push (file, slang_asm_addr_deref))
					return 0;
			}
			if (!dereference (file, params, space, info))
				return 0;
		}
		else
		{
			/* TODO: for "out" and "inout" parameters also push the address (first) */
			/* TODO: optimize the "out" parameter case */
			/* TODO: inspect stk */
			if (!_slang_assemble_operation (file, params + i, 0, &flow, space, info, &stk))
				return 0;
		}
	}

	/* call the function */
	if (!slang_assembly_file_push_label (file, slang_asm_call, fun->address))
		return 0;

	/* pop the parameters from the stack */
	for (i = param_count; i > 0; i--)
	{
		unsigned int j = i - 1;
		if (fun->parameters->variables[j].type.qualifier == slang_qual_inout ||
			fun->parameters->variables[j].type.qualifier == slang_qual_out)
		{
			if (!_slang_assemble_assignment (file, params + j, space, info))
				return 0;
			if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))
				return 0;
		}
		else
		{
			if (!_slang_cleanup_stack (file, params + j, 0, space))
				return 0;
		}
	}

	return 1;
}

int call_function_name (slang_assembly_file *file, const char *name, slang_operation *params,
	unsigned int param_count, int assignment, slang_assembly_name_space *space,
	slang_assembly_local_info *info)
{
	slang_function *fun = _slang_locate_function (name, params, param_count, space);
	if (fun == NULL)
		return 0;
	return call_function (file, fun, params, param_count, assignment, space, info);
}

static int call_function_name_dummyint (slang_assembly_file *file, const char *name,
	slang_operation *params, slang_assembly_name_space *space, slang_assembly_local_info *info)
{
	slang_operation p2[2];
	int result;

	p2[0] = *params;
	if (!slang_operation_construct_a (p2 + 1))
		return 0;
	p2[1].type = slang_oper_literal_int;
	result = call_function_name (file, name, p2, 2, 0, space, info);
	slang_operation_destruct (p2 + 1);
	return result;
}

static int call_asm_instruction (slang_assembly_file *file, const char *name)
{
	const struct
	{
		const char *name;
		slang_assembly_type code1, code2;
	} inst[] = {
		{ "float_to_int",   slang_asm_float_to_int,   slang_asm_int_copy },
		{ "int_to_float",   slang_asm_int_to_float,   slang_asm_float_copy },
		{ "float_copy",     slang_asm_float_copy,     slang_asm_none },
		{ "int_copy",       slang_asm_int_copy,       slang_asm_none },
		{ "bool_copy",      slang_asm_bool_copy,      slang_asm_none },
		{ "float_add",      slang_asm_float_add,      slang_asm_float_copy },
		{ "float_multiply", slang_asm_float_multiply, slang_asm_float_copy },
		{ "float_divide",   slang_asm_float_divide,   slang_asm_float_copy },
		{ "float_negate",   slang_asm_float_negate,   slang_asm_float_copy },
		{ "float_less",     slang_asm_float_less,     slang_asm_bool_copy },
		{ "float_equal",    slang_asm_float_equal,    slang_asm_bool_copy },
		{ NULL,             slang_asm_none,           slang_asm_none }
	};
	unsigned int i;

	for (i = 0; inst[i].name != NULL; i++)
		if (slang_string_compare (name, inst[i].name) == 0)
			break;
	if (inst[i].name == NULL)
		return 0;

	if (!slang_assembly_file_push_label2 (file, inst[i].code1, 4, 0))
		return 0;
	if (inst[i].code2 != slang_asm_none)
		if (!slang_assembly_file_push_label2 (file, inst[i].code2, 4, 0))
			return 0;

	/* clean-up the stack from the remaining dst address */
	if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))
		return 0;

	return 1;
}

/* XXX: general swizzle! */
static int equality_aggregate (slang_assembly_file *file, const slang_storage_aggregate *agg,
	unsigned int *index, unsigned int size, slang_assembly_local_info *info, unsigned int z_label)
{
	unsigned int i;

	for (i = 0; i < agg->count; i++)
	{
		const slang_storage_array *arr = agg->arrays + i;
		unsigned int j;

		for (j = 0; j < arr->length; j++)
		{
			if (arr->type == slang_stor_aggregate)
			{
				if (!equality_aggregate (file, arr->aggregate, index, size, info, z_label))
					return 0;
			}
			else
			{
				if (!slang_assembly_file_push_label2 (file, slang_asm_float_equal, size + *index,
					*index))
					return 0;
				*index += 4;
				if (!slang_assembly_file_push_label (file, slang_asm_jump_if_zero, z_label))
					return 0;
			}
		}
	}
	return 1;
}
/* XXX: general swizzle! */
static int equality (slang_assembly_file *file, slang_operation *op,
	slang_assembly_name_space *space, slang_assembly_local_info *info, int equal)
{
	slang_assembly_typeinfo ti;
	int result;
	slang_storage_aggregate agg;
	unsigned int index, size;
	unsigned int skip_jump, true_label, true_jump, false_label, false_jump;

	/* get type of operation */
	slang_assembly_typeinfo_construct (&ti);
	if (!_slang_typeof_operation (op, space, &ti))
	{
		slang_assembly_typeinfo_destruct (&ti);
		return 0;
	}

	/* convert it to an aggregate */
	slang_storage_aggregate_construct (&agg);
	if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs)))
		goto end;

	/* compute the size of the agregate - there are two such aggregates on the stack */
	size = _slang_sizeof_aggregate (&agg);

	/* jump to the actual data-comparison code */
	skip_jump = file->count;
	if (!(result = slang_assembly_file_push (file, slang_asm_jump)))
		goto end;

	/* pop off the stack the compared data and push 1 */
	true_label = file->count;
	if (!(result = slang_assembly_file_push_label (file, slang_asm_local_free, size * 2)))
		goto end;
	if (!(result = slang_assembly_file_push_literal (file, slang_asm_bool_push, 1.0f)))
		goto end;
	true_jump = file->count;
	if (!(result = slang_assembly_file_push (file, slang_asm_jump)))
		goto end;

	false_label = file->count;
	if (!(result = slang_assembly_file_push_label (file, slang_asm_local_free, size * 2)))
		goto end;
	if (!(result = slang_assembly_file_push_literal (file, slang_asm_bool_push, 0.0f)))
		goto end;
	false_jump = file->count;
	if (!(result = slang_assembly_file_push (file, slang_asm_jump)))
		goto end;

	file->code[skip_jump].param[0] = file->count;

	/* compare the data on stack, it will eventually jump either to true or false label */
	index = 0;
	if (!(result = equality_aggregate (file, &agg, &index, size, info,
		equal ? false_label : true_label)))
		goto end;
	if (!(result = slang_assembly_file_push_label (file, slang_asm_jump,
		equal ? true_label : false_label)))
		goto end;

	file->code[true_jump].param[0] = file->count;
	file->code[false_jump].param[0] = file->count;

	result = 1;
end:
	slang_storage_aggregate_destruct (&agg);
	slang_assembly_typeinfo_destruct (&ti);
	return result;
}

int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, int reference,
	slang_assembly_flow_control *flow, slang_assembly_name_space *space,
	slang_assembly_local_info *info, slang_assembly_stack_info *stk)
{
	unsigned int assem;

	stk->swizzle_mask = 0;

	assem = file->count;
	if (!slang_assembly_file_push_new (file))
		return 0;

	switch (op->type)
	{
	case slang_oper_block_no_new_scope:
	case slang_oper_block_new_scope:
		{
			unsigned int i;
			for (i = 0; i < op->num_children; i++)
			{
				slang_assembly_stack_info stk;
				if (!_slang_assemble_operation (file, op->children + i, 0, flow, space, info, &stk))
					return 0;
				/* TODO: pass-in stk to cleanup */
				if (!_slang_cleanup_stack (file, op->children + i, 0, space))
					return 0;
			}
		}
		break;
	case slang_oper_variable_decl:
		{
			unsigned int i;

			for (i = 0; i < op->num_children; i++)
			{
				/* TODO: perform initialization of op->children[i] */
				/* TODO: clean-up stack */
			}
		}
		break;
	case slang_oper_asm:
		{
			unsigned int i;
			for (i = 0; i < op->num_children; i++)
			{
				slang_assembly_stack_info stk;
				if (!_slang_assemble_operation (file, op->children + i, i == 0, flow, space, info,
					&stk))
					return 0;
				/* TODO: inspect stk */
			}
			if (!call_asm_instruction (file, op->identifier))
				return 0;
		}
		break;
	case slang_oper_break:
		file->code[assem].type = slang_asm_jump;
		file->code[assem].param[0] = flow->loop_end;
		break;
	case slang_oper_continue:
		file->code[assem].type = slang_asm_jump;
		file->code[assem].param[0] = flow->loop_start;
		break;
	case slang_oper_discard:
		file->code[assem].type = slang_asm_discard;
		if (!slang_assembly_file_push (file, slang_asm_exit))
			return 0;
		break;
	case slang_oper_return:
		if (info->ret_size != 0)
		{
			slang_assembly_stack_info stk;
			if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, 0, info->ret_size))
				return 0;
			if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))
				return 0;
			/* TODO: inspect stk */
			if (!_slang_assemble_assignment (file, op->children, space, info))
				return 0;
			if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))
				return 0;
		}
		if (!slang_assembly_file_push_label (file, slang_asm_jump, flow->function_end))
			return 0;
		break;
	case slang_oper_expression:
		{
			slang_assembly_stack_info stk;
			if (!_slang_assemble_operation (file, op->children, reference, flow, space, info, &stk))
				return 0;
			/* TODO: inspect stk */
		}
		break;
	case slang_oper_if:
		if (!_slang_assemble_if (file, op, flow, space, info))
			return 0;
		break;
	case slang_oper_while:
		if (!_slang_assemble_while (file, op, flow, space, info))
			return 0;
		break;
	case slang_oper_do:
		if (!_slang_assemble_do (file, op, flow, space, info))
			return 0;
		break;
	case slang_oper_for:
		if (!_slang_assemble_for (file, op, flow, space, info))
			return 0;
		break;
	case slang_oper_void:
		break;
	case slang_oper_literal_bool:
		file->code[assem].type = slang_asm_bool_push;
		file->code[assem].literal = op->literal;
		break;
	case slang_oper_literal_int:
		file->code[assem].type = slang_asm_int_push;
		file->code[assem].literal = op->literal;
		break;
	case slang_oper_literal_float:
		file->code[assem].type = slang_asm_float_push;
		file->code[assem].literal = op->literal;
		break;
	case slang_oper_identifier:
		{
			slang_variable *var;
			unsigned int size;
			var = _slang_locate_variable (op->locals, op->identifier, 1);
			if (var == NULL)
				return 0;
			size = 0;
			if (!sizeof_variable (&var->type.specifier, slang_qual_none, var->array_size, space,
				&size))
				return 0;
			if (var->initializer != NULL)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -