#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