WONKY



LOG | FILES | OVERVIEW


#ifndef WONKY_INTEL_ASM_C
#define WONKY_INTEL_ASM_C WONKY_INTEL_ASM_C
#include <intel_asm.h>

struct Compiled_Object_Intel_Asm* compile_program_to_intel_asm(struct Program *program)
{
	struct Compile_Data_Intel_Asm *data;
	struct Compiled_Object_Intel_Asm *ret;
	struct Queue_Node *it;

	data=get_compile_data_for_intel_asm();

	for(it=program->functions_without_a_definition->first;it!=NULL;it=it->prev)
		import_function_definition(data,it->data);

	for(it=program->external_objects_without_an_initialiser->first;it!=NULL;it=it->prev)
		import_object_definition(data,it->data);

	for(it=program->translation_units->first;it!=NULL;it=it->prev)
		compile_translation_unit_to_intel_asm(data,it->data);

	ret=wonky_malloc(sizeof(struct Compiled_Object_Intel_Asm));
	ret->type=COMPILE_TO_INTEL_ASM;
	ret->errors=data->errors;
	ret->instructions=data->instructions;
	ret->data_block=data->data_block;
	ret->imports=data->imports;
	ret->exports=data->exports;

	return ret;
}
void save_compiled_intel_asm(struct Compiled_Object_Intel_Asm *object,struct wonky_stream *out)
{
	struct Queue_Node *it;
	for(it=object->exports->first;it!=NULL;it=it->prev)
		save_intel_asm_instruction(it->data,out);
	for(it=object->imports->first;it!=NULL;it=it->prev)
		save_intel_asm_instruction(it->data,out);
	for(it=object->data_block->first;it!=NULL;it=it->prev)
		save_intel_asm_instruction(it->data,out);
	for(it=object->instructions->first;it!=NULL;it=it->prev)
		save_intel_asm_instruction(it->data,out);
}
void save_compiled_intel_asm_as_nasm(struct Compiled_Object_Intel_Asm *object,struct wonky_stream *out)
{
	struct Queue_Node *it;
	wonky_fprintf(out,"[BITS 64]\n\n");
	for(it=object->exports->first;it!=NULL;it=it->prev)
		save_intel_asm_instruction(it->data,out);
	for(it=object->imports->first;it!=NULL;it=it->prev)
		save_intel_asm_instruction(it->data,out);
	wonky_fprintf(out,"\nsection .data\n");
	for(it=object->data_block->first;it!=NULL;it=it->prev)
		save_intel_asm_instruction(it->data,out);
	wonky_fprintf(out,"\nsection .text\n");
	for(it=object->instructions->first;it!=NULL;it=it->prev)
		save_intel_asm_instruction(it->data,out);
}
struct Compile_Data_Intel_Asm* get_compile_data_for_intel_asm()
{
	struct Compile_Data_Intel_Asm *ret;

	ret=wonky_malloc(sizeof(struct Compile_Data_Intel_Asm));
	ret->type=COMPILE_TO_INTEL_ASM;

	ret->errors=wonky_malloc(sizeof(struct Queue));
	Queue_Init(ret->errors);

	ret->data_block=wonky_malloc(sizeof(struct Queue));
	Queue_Init(ret->data_block);

	ret->exports=wonky_malloc(sizeof(struct Queue));
	Queue_Init(ret->exports);

	ret->imports=wonky_malloc(sizeof(struct Queue));
	Queue_Init(ret->imports);

	ret->instructions=wonky_malloc(sizeof(struct Queue));
	Queue_Init(ret->instructions);

	ret->number_of_anon_labels=0;
	ret->offset_from_stack_frame=0;
	return ret;

}




struct Intel_Asm_Instruction* intel_asm_get_push_rax()
{
	return get_intel_asm_unary_instruction(intel_asm_get_ax_register(),INTEL_ASM_OP_PUSH);
}
struct Intel_Asm_Instruction* intel_asm_get_pop_rax()
{
	return get_intel_asm_unary_instruction(intel_asm_get_ax_register(),INTEL_ASM_OP_POP);
}
struct Intel_Asm_Instruction* intel_asm_get_pop_rdx()
{
	return get_intel_asm_unary_instruction(intel_asm_get_dx_register(),INTEL_ASM_OP_POP);
}
void push_intel_asm_instruction(struct Compile_Data_Intel_Asm *compile_data,struct Intel_Asm_Instruction *instruction)
{
	Queue_Push(compile_data->instructions,instruction);
}
void reserve_stack_space(struct Compile_Data_Intel_Asm *compile_data,int size)
{
	compile_data->offset_from_stack_frame+=size;
	push_intel_asm_instruction(compile_data,
		get_intel_asm_binary_instruction(
						get_intel_asm_register(INTEL_ASM_REGISTER_RSP),
						get_intel_asm_in_instruction_number(size),
						INTEL_ASM_OP_SUB
						)
				);
}
void release_stack_space(struct Compile_Data_Intel_Asm *compile_data,int size)
{
	compile_data->offset_from_stack_frame-=size;
	push_intel_asm_instruction(compile_data,
		get_intel_asm_binary_instruction(
						get_intel_asm_register(INTEL_ASM_REGISTER_RSP),
						get_intel_asm_in_instruction_number(size),
						INTEL_ASM_OP_ADD
						)
				);
}
struct Intel_Asm_Memory_Location* reserve_static_space_for_object(struct Compile_Data_Intel_Asm *compile_data,struct Intel_Asm_Label *label,int size)
{
	
}
struct Intel_Asm_Memory_Location* reserve_static_space_for_string(struct Compile_Data_Intel_Asm *compile_data,struct Constant *string)
{
	struct Intel_Asm_Instruction *label;
	struct Intel_Asm_Instruction *db,*db2;
	struct Type_Array *string_type;

	wonky_assert(string->type->specifier==TS_ARRAY && string->value!=NULL);

	string_type=(struct Type_Array*)string->type;
	db=get_intel_asm_define_bytes(string->value,string_type->size);
	db2=get_intel_asm_define_bytes("\0",1);
	label=get_intel_asm_new_unique_label(compile_data);

	Queue_Push(compile_data->data_block,label);
	Queue_Push(compile_data->data_block,db);
	Queue_Push(compile_data->data_block,db2);

	return get_intel_asm_label_location((struct Intel_Asm_Label*)label);
}
void release_stack_space_for_whole_block_intel_asm(struct Compile_Data_Intel_Asm *compile_data,struct Normal_Scope *scope)
{
	int whole_size=0;
	struct Queue_Node *it;
	for(it=scope->object_order->first;it!=NULL;it=it->prev)
		whole_size+=get_type_size(((struct Denoted_Object*)it->data)->object->type);
	release_stack_space(compile_data,whole_size);
}
void release_stack_frame_for_function(struct Compile_Data_Intel_Asm *compile_data)
{

}

void intel_asm_memory_location_to_rax(struct Compile_Data_Intel_Asm *compile_data,struct Intel_Asm_Memory_Location *location)
{
	switch(location->type)
	{
		case INTEL_ASM_MEMORY_LOCATION_REGISTER:
		case INTEL_ASM_MEMORY_LOCATION_BY_LABEL:
		case INTEL_ASM_MEMORY_LOCATION_BY_REGISTER:
		case INTEL_ASM_MEMORY_LOCATION_IN_INSTRUCTION_NUMBER:
		case INTEL_ASM_MEMORY_LOCATION_BY_STACK_OFFSET:
			push_intel_asm_instruction(
						compile_data,
						get_intel_asm_binary_instruction(get_intel_asm_register(INTEL_ASM_REGISTER_RAX),location,INTEL_ASM_OP_MOV)
					);	
			break;
			break;
		case INTEL_ASM_MEMORY_LOCATION_STACK_OFFSET:
			push_intel_asm_instruction(
						compile_data,
						get_intel_asm_binary_instruction(get_intel_asm_register(INTEL_ASM_REGISTER_RAX),get_intel_asm_register(INTEL_ASM_REGISTER_RBP),INTEL_ASM_OP_MOV)
					);	
			push_intel_asm_instruction(
						compile_data,
							get_intel_asm_binary_instruction(
								get_intel_asm_register(INTEL_ASM_REGISTER_RAX),
								get_intel_asm_in_instruction_number(
										((struct Intel_Asm_Memory_Location_Stack_Offset*)location)->offset
												   ),
								INTEL_ASM_OP_SUB
									 		)
						 );
			break;
		default:
			wonky_assert(SHOULD_NOT_REACH_HERE);
	}
}
struct Intel_Asm_Memory_Location* reserve_space_for_value_intel_asm(struct Compile_Data_Intel_Asm *compile_data,struct Expression_Value *value)
{
	int size;
	size=get_expression_value_size(value);
	reserve_stack_space(compile_data,size);
	return get_intel_asm_stack_offset(compile_data->offset_from_stack_frame);
}
enum Intel_Asm_Registers rvalue_to_ax(struct Compile_Data_Intel_Asm *compile_data,struct Expression_Value *value)
{
	size_t value_size;
	enum Intel_Asm_Registers reg;

	value_size=get_expression_value_size(value);
	reg=get_ax_with_size(value_size);

	if(value->type==VALUE_LVALUE)
	{
		push_intel_asm_instruction(compile_data,intel_asm_get_pop(INTEL_ASM_REGISTER_RAX));
		push_intel_asm_instruction(
					compile_data,
					get_intel_asm_binary_instruction(
						get_intel_asm_register(reg),
						get_intel_asm_by_register(INTEL_ASM_REGISTER_RAX,value_size),
						INTEL_ASM_OP_MOV
						)
				);	
	}else
	{
		push_intel_asm_instruction(compile_data,intel_asm_get_pop(INTEL_ASM_REGISTER_RAX));
	}
	return reg;	
}
void lvalue_to_rax(struct Compile_Data_Intel_Asm *compile_data,struct Expression_Value *value)
{
	size_t value_size;

	value_size=get_expression_value_size(value);
	wonky_assert(value->type==VALUE_LVALUE);

	push_intel_asm_instruction(compile_data,intel_asm_get_pop(INTEL_ASM_REGISTER_RAX));
}
enum Intel_Asm_Registers rvalue_to_dx(struct Compile_Data_Intel_Asm *compile_data,struct Expression_Value *value)
{
	size_t value_size;
	enum Intel_Asm_Registers reg;

	value_size=get_expression_value_size(value);

	reg=get_dx_with_size(value_size);

	if(value->type==VALUE_LVALUE)
	{
		push_intel_asm_instruction(compile_data,intel_asm_get_pop(INTEL_ASM_REGISTER_RDX));
		push_intel_asm_instruction(
					compile_data,
					get_intel_asm_binary_instruction(
						get_intel_asm_register(reg),
						get_intel_asm_by_register(INTEL_ASM_REGISTER_RDX,value_size),
						INTEL_ASM_OP_MOV
						)
				);	
	}else
	{
		push_intel_asm_instruction(compile_data,intel_asm_get_pop(INTEL_ASM_REGISTER_RDX));
	}
	
	return reg;	
}
enum Intel_Asm_Registers get_ax_with_size(size_t size)
{
	switch(size)
	{
		case 1:
			return INTEL_ASM_REGISTER_AL;
		case 2:
			return INTEL_ASM_REGISTER_AX;
		case 4:
			return INTEL_ASM_REGISTER_EAX;
		case 8:
			return INTEL_ASM_REGISTER_RAX;
		default:
			wonky_assert(SHOULD_NOT_REACH_HERE);
	}

}
enum Intel_Asm_Registers get_dx_with_size(size_t size)
{
	switch(size)
	{
		case 1:
			return INTEL_ASM_REGISTER_DL;
		case 2:
			return INTEL_ASM_REGISTER_DX;
		case 4:
			return INTEL_ASM_REGISTER_EDX;
		case 8:
			return INTEL_ASM_REGISTER_RDX;
		default:
			wonky_assert(SHOULD_NOT_REACH_HERE);
	}
}
void release_value_from_stack(struct Compile_Data_Intel_Asm *compile_data,struct Expression_Value *value)
{
	release_stack_space(compile_data,get_expression_value_size(value));
}
struct Intel_Asm_Memory_Location* reserve_stack_space_for_object(struct Compile_Data_Intel_Asm *compile_data,struct Object *object)
{
	int size;
	struct Intel_Asm_Memory_Location *ret;
	size=(int)get_type_size(object->type);
	reserve_stack_space(compile_data,size);

	//compile_data->offset_from_stack_frame+=size;
	ret=get_intel_asm_stack_offset(compile_data->offset_from_stack_frame);

	object->location=(struct Memory_Location*)ret;
	return ret;
}
struct Intel_Asm_Memory_Location* reserve_stack_space_for_function_argument(struct Compile_Data_Intel_Asm *compile_data,struct Object *object)
{
	int size;
	struct Intel_Asm_Memory_Location *ret;
	size=(int)get_type_size(object->type);

	ret=get_intel_asm_stack_offset(-size);

	object->location=(struct Memory_Location*)ret;
	return ret;
}
void release_object_from_stack(struct Compile_Data_Intel_Asm *compile_data,struct Object *object)
{
	release_stack_space(compile_data,get_type_size(object->type));
}
struct Intel_Asm_Memory_Location* get_location_of_value(struct Compile_Data_Intel_Asm *compile_data,struct Expression_Value *value)
{
	switch(value->type)
	{
		case VALUE_LVALUE:
			return (struct Intel_Asm_Memory_Location*)((struct Expression_Value_LValue*)value)->object->location;	
		case VALUE_TEMP:
			return (struct Intel_Asm_Memory_Location*)((struct Expression_Value_RValue*)value)->temp_object->location;
		case VALUE_FUNCTION_DESIGNATOR:
			return (struct Intel_Asm_Memory_Location*)((struct Expression_Value_Function_Designator*)value)->function->location;
		case VALUE_CONSTANT:
			return get_location_of_constant(compile_data,((struct Expression_Value_Constant*)value)->constant);
		case VALUE_VOID:
		default:
			wonky_assert(SHOULD_NOT_REACH_HERE);
	}
}
struct Intel_Asm_Memory_Location* get_location_of_constant(struct Compile_Data_Intel_Asm *compile_data,struct Constant *constant)
{
	wonky_assert(constant->type->specifier==TS_INT);
	return get_intel_asm_in_instruction_number(*(int*)constant->value);
}
void intel_asm_anotate_denoted(struct Denoted *denoted,struct Compile_Data_Intel_Asm *compile_data)
{
	if(denoted->denotation==DT_Function)
	{
		intel_asm_anotate_function(compile_data,(struct Denoted_Function*)denoted);
	}
	//wonky_assert(SHOULD_NOT_REACH_HERE);
}
void intel_asm_anotate_function(struct Compile_Data_Intel_Asm *compile_data,struct Denoted_Function *function)
{
	struct identifier *id;
	struct Intel_Asm_Memory_Location_By_Label *location;
	id=function->id;
	location=(struct Intel_Asm_Memory_Location_By_Label*)
		get_intel_asm_label_location(
				(struct Intel_Asm_Label*)get_intel_asm_label(gstr_dup(id->data,id->data+id->size,1024))
				);

	function->location=(struct Memory_Location*)location;
}
void intel_asm_finish_comparison(struct Compile_Data_Intel_Asm *compile_data,enum Intel_Asm_Instruction_Type op)
{
	push_intel_asm_instruction(compile_data,get_intel_asm_unary_instruction(get_intel_asm_register(INTEL_ASM_REGISTER_AL),op));
	//push_intel_asm_instruction(compile_data,get_intel_asm_binary_instruction(get_intel_asm_register(INTEL_ASM_REGISTER_RAX),get_intel_asm_register(INTEL_ASM_REGISTER_AL),INTEL_ASM_OP_MOV));
}
void export_function_definition(struct Compile_Data_Intel_Asm *compile_data,struct AST_Function_Definition *function)
{
	wonky_assert(function!=NULL && function->type==ST_FUNCTION_DEFINITION);
	Queue_Push(compile_data->exports,get_intel_asm_export(gstr_dup(function->function->id->data,function->function->id->data+function->function->id->size,1024)));
	
}
void export_object_definition(struct Compile_Data_Intel_Asm *compile_data,struct AST_Object_Declaration *object)
{
	wonky_assert(object!=NULL && object->type==ST_OBJECT_DECLARATION);
	Queue_Push(compile_data->exports,get_intel_asm_export(gstr_dup(object->object->id->data,object->object->id->data+object->object->id->size,1024)));
}
void import_function_definition(struct Compile_Data_Intel_Asm *compile_data,struct AST_Function_Declaration *function)
{
	wonky_assert(function!=NULL && function->type==ST_FUNCTION_DECLARATION);
	Queue_Push(compile_data->imports,get_intel_asm_import(gstr_dup(function->function->id->data,function->function->id->data+function->function->id->size,1024)));
}
void import_object_definition(struct Compile_Data_Intel_Asm *compile_data,struct AST_Object_Declaration *object)
{
	wonky_assert(object!=NULL && object->type==ST_OBJECT_DECLARATION);
	wonky_assert(object->initializer==NULL);/*we only ask for objects without initialisers*/
	Queue_Push(compile_data->imports,get_intel_asm_import(gstr_dup(object->object->id->data,object->object->id->data+object->object->id->size,1024)));
}
#endif