diff --git a/src/Makefile b/src/Makefile index f2d17681..0c559e18 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,6 +10,10 @@ AST_DIR := ast AST_SRCS := $(wildcard $(AST_DIR)/*.c) AST_OBJS := $(AST_SRCS:.c=.o) +CODEGEN_DIR := code_generator +CODEGEN_SRCS := $(wildcard $(CODEGEN_DIR)/*.c) +CODEGEN_OBJS := $(CODEGEN_SRCS:.c=.o) + LEX_SRC := lexer.l LEX_INTERMEDIATE := lex.yy.c LEX_TARGET := lex.yy.o @@ -23,6 +27,7 @@ YACC := bison YACC_OPTION := -d TARGET := kmc89 OBJS += $(AST_OBJS) +OBJS += $(CODEGEN_OBJS) OBJS += $(LEX_TARGET) $(YACC_TARGET) CLEAN_OBJS += $(LEX_INTERMEDIATE) $(YACC_INTERMEDIATE) diff --git a/src/code_generator/code_generator.h b/src/code_generator/code_generator.h new file mode 100644 index 00000000..ec162939 --- /dev/null +++ b/src/code_generator/code_generator.h @@ -0,0 +1,24 @@ +#ifndef KMC_C89_COMPILER_CODE_GENERATOR_H +#define KMC_C89_COMPILER_CODE_GENERATOR_H + +#include +#include "ast.h" +#include "ast/external_definitions.h" +#include "utility.h" +#include "vector.h" +#include "stdstring.h" +#include "variable_set.h" +#include "pool.h" + +void translation_unit(LLVMModuleRef module, AstTranslationUnitRef translation_unit); +LLVMTypeRef get_type(AstRef ast); +LLVMTypeRef get_type_with_type(LLVMTypeRef base_type, AstRef ast); +TypeVectorRef get_parameter_types(AstRef ast); +LLVMTypeRef get_function_type(AstFunctionDefinitionRef function_definition); +AstTokenRef get_name(AstRef ast); +ValueVectorRef get_arguments(ValueVectorRef variable_set, AstArgumentExpressionListRef ast); +void build_block(LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, AstRef ast); +LLVMValueRef build_expression(LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, AstRef ast); +LLVMValueRef make_value(LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, LLVMTypeRef type, AstRef ast); + +#endif /* KMC_C89_COMPILER_CODE_GENERATOR_H */ diff --git a/src/code_generator/expression.c b/src/code_generator/expression.c new file mode 100644 index 00000000..f1a1854c --- /dev/null +++ b/src/code_generator/expression.c @@ -0,0 +1,213 @@ +#include "code_generator.h" +#include "variable_set.h" +#include "ast/lexical_elements_impl.h" +#include "ast/expressions_impl.h" +#include "ast/is_method.h" +#include "ast/get_method.h" +#include "ast/ast_impl.h" + +LLVMValueRef build_expression_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_comma_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstCommaExpressionRef comma_expression) { + build_expression(module, builder, variable_set, comma_expression->expression); + return build_expression(module, builder, variable_set, comma_expression->expression); +} + +LLVMValueRef build_expression_assignment_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstAssignmentExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_basic_assignment_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstBasicAssignmentExpressionRef expression) { + LLVMValueRef rhs = build_expression(module, builder, variable_set, expression->assignment); + return LLVMBuildStore(builder, rhs, get_variable(variable_set, expression->unary)); +} + +LLVMValueRef build_expression_conditional_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstConditionalExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_logical_or_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstLogicalOrExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_logical_and_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstLogicalAndExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_bitwise_or_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstBitwiseOrExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_bitwise_xor_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstBitwiseXorExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_bitwise_and_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstBitwiseAndExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_equality_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstEqualityExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_relarional_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstRelationalExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_shift_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstShiftExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_additive_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstAdditiveExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_multiplicative_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstMultiplicativeExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef build_expression_cast_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstCastExpressionRef cast) { + return build_expression(module, builder, variable_set, cast->cast); +} + +LLVMValueRef build_expression_unary_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstUnaryExpressionRef unary) { + return build_expression(module, builder, variable_set, unary->unary); +} + +LLVMValueRef build_expression_function_call_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstFunctionCallExpressionRef function_call) { + AstTokenRef function_name = get_name(function_call->function); + LLVMValueRef function = LLVMGetNamedFunction(module, string_data(function_name)); + LLVMTypeRef function_type = LLVMGetElementType(LLVMTypeOf(function)); + int parameter_count = LLVMCountParamTypes(function_type); + ValueVectorRef argument_vec = + get_arguments( + variable_set, + ast_get_argument_expression_list(function_call->argument_list)); + int argument_count = ValueVectorFunc(size)(argument_vec); + if (parameter_count != argument_count) return NULL; + return LLVMBuildCall(builder, function, ValueVectorFunc(data)(argument_vec), + ValueVectorFunc(size)(argument_vec), string_data(function_name)); +} + +LLVMValueRef build_expression_postfix_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstPostfixExpressionRef postfix) { + return build_expression(module, builder, variable_set, postfix->postfix); +} + +LLVMValueRef build_expression_primary_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstPrimaryExpressionRef primary) { + return build_expression(module, builder, variable_set, primary->primary_expression); +} + +LLVMValueRef build_expression_constant( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstConstantRef constant) { + return build_expression(module, builder, variable_set, constant->constant); +} + +LLVMValueRef build_expression_integer_constant( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstIntegerConstantRef constant) { + return LLVMConstIntOfString( + LLVMInt32Type(), string_data(ast_get_token(constant->token)), 10); +} + +LLVMValueRef build_expression_identifier( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstIdentifierRef identifier) { + return get_variable_identifier(variable_set, identifier); +} + +LLVMValueRef build_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, AstRef ast) { + switch (ast->tag) { + case AST_EXPRESSION: + return build_expression_expression(module, builder, variable_set, ast_get_expression(ast)); + case AST_COMMA_EXPRESSION: + return build_expression_comma_expression(module, builder, variable_set, ast_get_comma_expression(ast)); + case AST_ASSIGNMENT_EXPRESSION: + return build_expression_assignment_expression(module, builder, variable_set, ast_get_assignment_expression(ast)); + case AST_BASIC_ASSIGNMENT_EXPRESSION: + return build_expression_basic_assignment_expression(module, builder, variable_set, ast_get_basic_assignment_expression(ast)); + case AST_CONDITIONAL_EXPRESSION: + return build_expression_conditional_expression(module, builder, variable_set, ast_get_conditional_expression(ast)); + case AST_LOGICAL_OR_EXPRESSION: + return build_expression_logical_or_expression(module, builder, variable_set, ast_get_logical_or_expression(ast)); + case AST_LOGICAL_AND_EXPRESSION: + return build_expression_logical_and_expression(module, builder, variable_set, ast_get_logical_and_expression(ast)); + case AST_BITWISE_OR_EXPRESSION: + return build_expression_bitwise_or_expression(module, builder, variable_set, ast_get_bitwise_or_expression(ast)); + case AST_BITWISE_XOR_EXPRESSION: + return build_expression_bitwise_xor_expression(module, builder, variable_set, ast_get_bitwise_xor_expression(ast)); + case AST_BITWISE_AND_EXPRESSION: + return build_expression_bitwise_and_expression(module, builder, variable_set, ast_get_bitwise_and_expression(ast)); + case AST_EQUALITY_EXPRESSION: + return build_expression_equality_expression(module, builder, variable_set, ast_get_equality_expression(ast)); + case AST_RELATIONAL_EXPRESSION: + return build_expression_relarional_expression(module, builder, variable_set, ast_get_relational_expression(ast)); + case AST_SHIFT_EXPRESSION: + return build_expression_shift_expression(module, builder, variable_set, ast_get_shift_expression(ast)); + case AST_ADDITIVE_EXPRESSION: + return build_expression_additive_expression(module, builder, variable_set, ast_get_additive_expression(ast)); + case AST_MULTIPLICATIVE_EXPRESSION: + return build_expression_multiplicative_expression(module, builder, variable_set, ast_get_multiplicative_expression(ast)); + case AST_CAST_EXPRESSION: + return build_expression_cast_expression(module, builder, variable_set, ast_get_cast_expression(ast)); + case AST_UNARY_EXPRESSION: + return build_expression_unary_expression(module, builder, variable_set, ast_get_unary_expression(ast)); + case AST_POSTFIX_EXPRESSION: + return build_expression_postfix_expression(module, builder, variable_set, ast_get_postfix_expression(ast)); + case AST_FUNCTION_CALL_EXPRESSION: + return build_expression_function_call_expression(module, builder, variable_set, ast_get_function_call_expression(ast)); + case AST_PRIMARY_EXPRESSION: + return build_expression_primary_expression(module, builder, variable_set, ast_get_primary_expression(ast)); + case AST_CONSTANT: + return build_expression_constant(module, builder, variable_set, ast_get_constant(ast)); + case AST_INTEGER_CONSTANT: + return build_expression_integer_constant(module, builder, variable_set, ast_get_integer_constant(ast)); + case AST_IDENTIFIER: + return build_expression_identifier(module, builder, variable_set, ast_get_identifier(ast)); + default:; + } + return NULL; +} diff --git a/src/code_generator/name.c b/src/code_generator/name.c new file mode 100644 index 00000000..669d8c5c --- /dev/null +++ b/src/code_generator/name.c @@ -0,0 +1,38 @@ +#include "code_generator.h" +#include "stdstring.h" +#include "ast/lexical_elements_impl.h" +#include "ast/expressions_impl.h" +#include "ast/is_method.h" +#include "ast/get_method.h" +#include "ast/ast_impl.h" + +AstTokenRef get_name_identifier(AstIdentifierRef identifier) { + return ast_get_token(identifier->token); +} + +AstTokenRef get_name_primary_expression(AstPrimaryExpressionRef primary) { + return get_name(primary->primary_expression); +} + +AstTokenRef get_name_postfix_expression(AstPostfixExpressionRef postfix) { + return get_name(postfix->postfix); +} + +AstTokenRef get_name_unary_expression(AstUnaryExpressionRef unary) { + return get_name(unary->unary); +} + +AstTokenRef get_name(AstRef ast) { + switch (ast->tag) { + case AST_IDENTIFIER: + return get_name_identifier(ast_get_identifier(ast)); + case AST_PRIMARY_EXPRESSION: + return get_name_primary_expression(ast_get_primary_expression(ast)); + case AST_POSTFIX_EXPRESSION: + return get_name_postfix_expression(ast_get_postfix_expression(ast)); + case AST_UNARY_EXPRESSION: + return get_name_unary_expression(ast_get_unary_expression(ast)); + default: + return NULL; + } +} diff --git a/src/code_generator/parameter_type.c b/src/code_generator/parameter_type.c new file mode 100644 index 00000000..e998190d --- /dev/null +++ b/src/code_generator/parameter_type.c @@ -0,0 +1,58 @@ +#include "code_generator.h" +#include "ast/declarations_impl.h" +#include "ast/is_method.h" +#include "ast/get_method.h" +#include "ast/ast_impl.h" + +TypeVectorRef get_parameter_types_declarator(AstDeclaratorRef declarator) { + return get_parameter_types(declarator->direct_declarator); +} + +TypeVectorRef get_parameter_types_direct_declarator(AstDirectDeclaratorRef direct_declarator) { + return get_parameter_types(direct_declarator->direct_declarator); +} + +TypeVectorRef get_parameter_types_function_declarator(AstFunctionDeclaratorRef function_declarator) { + return get_parameter_types(function_declarator->parameter_type_list); +} + +TypeVectorRef get_parameter_types_parameter_type_list(AstParameterTypeListRef parameter_type_list) { + return get_parameter_types(parameter_type_list->parameter_type_list); +} + +TypeVectorRef get_parameter_types_parameter_list(AstParameterListRef parameter_list) { + AstVectorRef parameter_vector = parameter_list->parameter_declaration_vector; + TypeVectorRef parameter_types = TypeVectorFunc(ctor)(NULL); + int i; + for (i = 0; i < (int)AST_VECTOR_FUNC(size)(parameter_vector); i++) { + AstParameterDeclarationRef parameter_declaration = + ast_get_parameter_declaration(AST_VECTOR_FUNC(at)(parameter_vector, i)); + if (ast_is_parameter_concrete_declaration( + parameter_declaration->parameter_declaration)) { + AstParameterConcreteDeclarationRef parameter_concrete_declaration = + ast_get_parameter_concrete_declaration(parameter_declaration->parameter_declaration); + TypeVectorFunc(push_back)(parameter_types, + get_type(parameter_concrete_declaration->declaration_specifier_list)); + } else { + return NULL; + } + } + return parameter_types; +} + +TypeVectorRef get_parameter_types(AstRef ast) { + switch (ast->tag) { + case AST_DECLARATOR: + return get_parameter_types_declarator(ast_get_declarator(ast)); + case AST_DIRECT_DECLARATOR: + return get_parameter_types_direct_declarator(ast_get_direct_declarator(ast)); + case AST_FUNCTION_DECLARATOR: + return get_parameter_types_function_declarator(ast_get_function_declarator(ast)); + case AST_PARAMETER_TYPE_LIST: + return get_parameter_types_parameter_type_list(ast_get_parameter_type_list(ast)); + case AST_PARAMETER_LIST: + return get_parameter_types_parameter_list(ast_get_parameter_list(ast)); + default: + return NULL; + } +} diff --git a/src/code_generator/pool.c b/src/code_generator/pool.c new file mode 100644 index 00000000..6fb5e928 --- /dev/null +++ b/src/code_generator/pool.c @@ -0,0 +1,21 @@ +#include "pool.h" +#include "vector_impl.h" +#include + +static MemoryPoolRef g_codegen_pool = NULL; + +void codegen_pool_ctor(void) { + assert(!g_codegen_pool); + g_codegen_pool = memory_pool_ctor(CODEGEN_POOL_CHUNK_SIZE); +} + +void codegen_pool_dtor(void) { + memory_pool_dtor(&g_codegen_pool); +} + +MemoryPoolRef codegen_pool(void) { + return g_codegen_pool; +} + +DEFINE_VECTOR(LLVMTypeRef) +DEFINE_VECTOR(LLVMValueRef) diff --git a/src/code_generator/pool.h b/src/code_generator/pool.h new file mode 100644 index 00000000..6bc4e864 --- /dev/null +++ b/src/code_generator/pool.h @@ -0,0 +1,25 @@ +#ifndef KMC_C89_COMPILER_CODE_GENERATOR_POOL_H +#define KMC_C89_COMPILER_CODE_GENERATOR_POOL_H + +#include +#include "memory_pool.h" +#include "vector.h" + +#define codegen_palloc(type) \ + palloc(type, codegen_pool(), 1) + +static const size_t CODEGEN_POOL_CHUNK_SIZE = 1024; + +void codegen_pool_ctor(void); +void codegen_pool_dtor(void); +MemoryPoolRef codegen_pool(void); + +#define TypeVectorFunc(func) VECTORFUNC(LLVMTypeRef, func) +DECLARE_VECTOR(LLVMTypeRef) +typedef struct VECTOR(LLVMTypeRef) *TypeVectorRef; + +#define ValueVectorFunc(func) VECTORFUNC(LLVMValueRef, func) +DECLARE_VECTOR(LLVMValueRef) +typedef struct VECTOR(LLVMValueRef) *ValueVectorRef; + +#endif /* KMC_C89_COMPILER_CODE_GENERATOR_POOL_H */ diff --git a/src/code_generator/statements.c b/src/code_generator/statements.c new file mode 100644 index 00000000..c90ba50e --- /dev/null +++ b/src/code_generator/statements.c @@ -0,0 +1,148 @@ +#include "code_generator.h" +#include "variable_set.h" +#include "ast/statements_impl.h" +#include "ast/declarations_impl.h" +#include "ast/is_method.h" +#include "ast/get_method.h" +#include "ast/ast_impl.h" + +void build_block_with_type( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef base_type, AstRef ast); + +void build_block_with_type_init_declarator_list( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef base_type, AstInitDeclaratorListRef init_declarator_list) { + AstVectorRef vector = init_declarator_list->init_declarator_vector; + AstRef *itr; + AstRef *begin = AST_VECTOR_FUNC(begin)(vector); + AstRef *end = AST_VECTOR_FUNC(end)(vector); + for (itr = begin; itr != end; itr++) { + build_block_with_type(module, builder, variable_set, base_type, *itr); + } +} + +void build_block_with_type_init_declarator( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef base_type, AstInitDeclaratorRef init_declarator) { + build_block_with_type( + module, builder, variable_set, base_type, + init_declarator->init_declarator); +} + +void build_block_with_type_declarator( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef base_type, AstDeclaratorRef declarator) { + AstTokenRef name = get_name(declarator->direct_declarator); + LLVMTypeRef type = base_type; /* get_type_with_type(declarator->direct_declarator); */ + LLVMValueRef variable = LLVMGetUndef(type); + LLVMSetValueName(variable, string_data(name)); + ValueVectorFunc(push_back)(variable_set, variable); +} + +void build_block_with_type_declarator_with_initializer( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef base_type, AstDeclaratorWithInitializerRef declarator) { + AstTokenRef name = get_name(declarator->declarator); + LLVMTypeRef type = base_type; /* get_type_with_type(declarator->declarator); */ + LLVMValueRef variable = make_value(module, builder, variable_set, type, declarator->initializer); + LLVMSetValueName(variable, string_data(name)); + ValueVectorFunc(push_back)(variable_set, variable); +} + +void build_block_with_type( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef base_type, AstRef ast) { + switch (ast->tag) { + case AST_INIT_DECLARATOR_LIST: + build_block_with_type_init_declarator_list( + module, builder, variable_set, base_type, + ast_get_init_declarator_list(ast)); + break; + case AST_INIT_DECLARATOR: + build_block_with_type_init_declarator( + module, builder, variable_set, base_type, + ast_get_init_declarator(ast)); + break; + case AST_DECLARATOR: + build_block_with_type_declarator( + module, builder, variable_set, base_type, + ast_get_declarator(ast)); + break; + case AST_DECLARATOR_WITH_INITIALIZER: + build_block_with_type_declarator_with_initializer( + module, builder, variable_set, base_type, + ast_get_declarator_with_initializer(ast)); + break; + default:; + } +} + +void build_block_compound_statement( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstCompoundStatementRef compound_statement) { + build_block(module, builder, variable_set, compound_statement->declaration_list); + build_block(module, builder, variable_set, compound_statement->statement_list); +} + +void build_block_declaration_list( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstDeclarationListRef declaration_list) { + AstVectorRef declaration_vector = declaration_list->declaration_vector; + AstRef *itr; + AstRef *begin = AST_VECTOR_FUNC(begin)(declaration_vector); + AstRef *end = AST_VECTOR_FUNC(end)(declaration_vector); + for (itr = begin; itr != end; itr++) { + build_block(module, builder, variable_set, *itr); + } +} + +void build_block_declaration( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstDeclarationRef declaration) { + LLVMTypeRef type = get_type(declaration->declaration_specifier_list); + build_block_with_type(module, builder, variable_set, type, declaration->init_declarator_list); +} + +void build_block_statement_list( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstStatementListRef statement_list) { + AstVectorRef statement_vector = statement_list->statement_vector; + AstRef *itr; + AstRef *begin = AST_VECTOR_FUNC(begin)(statement_vector); + AstRef *end = AST_VECTOR_FUNC(end)(statement_vector); + for (itr = begin; itr != end; itr++) { + build_block(module, builder, variable_set, *itr); + } +} + +void build_block_statement( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstStatementRef statement) { + build_block(module, builder, variable_set, statement->statement); +} + +void build_block_expression_statement( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + AstExpressionStatementRef expression_statement) { + if (expression_statement->expression != NULL) + build_expression(module, builder, variable_set, expression_statement->expression); +} + +void build_block(LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, AstRef ast) { + switch (ast->tag) { + case AST_COMPOUND_STATEMENT: + build_block_compound_statement(module, builder, variable_set, ast_get_compound_statement(ast)); break; + case AST_DECLARATION_LIST: + build_block_declaration_list(module, builder, variable_set, ast_get_declaration_list(ast)); break; + case AST_DECLARATION: + build_block_declaration(module, builder, variable_set, ast_get_declaration(ast)); break; + case AST_STATEMENT_LIST: + build_block_statement_list(module, builder, variable_set, ast_get_statement_list(ast)); break; + case AST_STATEMENT: + build_block_statement(module, builder, variable_set, ast_get_statement(ast)); break; + case AST_EXPRESSION_STATEMENT: + build_block_expression_statement(module, builder, variable_set, ast_get_expression_statement(ast)); break; + default:; + } +} diff --git a/src/code_generator/translation_unit.c b/src/code_generator/translation_unit.c new file mode 100644 index 00000000..52878fc8 --- /dev/null +++ b/src/code_generator/translation_unit.c @@ -0,0 +1,43 @@ +#include "code_generator.h" +#include "pool.h" +#include "ast/external_definitions_impl.h" +#include "stdstring.h" +#include "ast/is_method.h" +#include "ast/get_method.h" +#include "ast/ast_impl.h" + +LLVMTypeRef get_function_type(AstFunctionDefinitionRef function_definition) { + LLVMTypeRef return_type = get_type(function_definition->declaration_specifier_list); + TypeVectorRef parameter_types = get_parameter_types(function_definition->declarator); + return LLVMFunctionType( + return_type, + TypeVectorFunc(data)(parameter_types), + TypeVectorFunc(size)(parameter_types), + false); +} + +void define_function(LLVMModuleRef module, LLVMBuilderRef builder, + AstFunctionDefinitionRef function_definition) { + StringRef name = get_name(function_definition->declarator); + LLVMTypeRef type = get_function_type(function_definition); + LLVMValueRef func = LLVMAddFunction(module, string_data(name), type); + LLVMBasicBlockRef entry = LLVMAppendBasicBlock(func, "entry"); + ValueVectorRef variable_set = ValueVectorFunc(ctor)(NULL); + LLVMPositionBuilderAtEnd(builder, entry); + build_block(module, builder, variable_set, function_definition->compound_statement); +} + +void translation_unit(LLVMModuleRef module, AstTranslationUnitRef translation_unit) { + AstVectorRef vector = translation_unit->external_declaration_vector; + LLVMBuilderRef builder = LLVMCreateBuilder(); + AstRef *itr; + AstRef *begin = AST_VECTOR_FUNC(begin)(vector); + AstRef *end = AST_VECTOR_FUNC(end)(vector); + for (itr = begin; itr != end; itr++) { + if (ast_is_function_definition(*itr)) { + define_function(module, builder, ast_get_function_definition(*itr)); + } else { + /* declaration(ast_get_declaration(external_declaration)); */ + } + } +} diff --git a/src/code_generator/type.c b/src/code_generator/type.c new file mode 100644 index 00000000..9e352a0a --- /dev/null +++ b/src/code_generator/type.c @@ -0,0 +1,60 @@ +#include "code_generator.h" +#include "stdstring.h" +#include "ast/declarations_impl.h" +#include "ast/is_method.h" +#include "ast/get_method.h" +#include "ast/ast_impl.h" + +LLVMTypeRef get_type_declaration_specifier_list( + AstDeclarationSpecifierListRef declaration_specifier_list) { + return LLVMInt32Type(); +} + +LLVMTypeRef get_type(AstRef ast) { + switch (ast->tag) { + case AST_DECLARATION_SPECIFIER_LIST: + return get_type_declaration_specifier_list(ast_get_declaration_specifier_list(ast)); + default: + return NULL; + } +} + +LLVMTypeRef get_type_with_type_declarator( + LLVMTypeRef base_type, AstDeclaratorRef declarator) { + LLVMTypeRef direct_type = get_type_with_type(base_type, declarator->direct_declarator); + return get_type_with_type(direct_type, declarator->pointer); +} + +LLVMTypeRef get_type_with_type_direct_declarator( + LLVMTypeRef base_type, AstDirectDeclaratorRef direct_declarator) { + return get_type_with_type(base_type, direct_declarator->direct_declarator); +} + +LLVMTypeRef get_type_with_type_pointer( + LLVMTypeRef base_type, AstPointerRef pointer) { + if (pointer->pointer == NULL) return base_type; + else + return get_type_with_type(LLVMPointerType(base_type, 0), pointer->pointer); +} + +LLVMTypeRef get_type_with_type_identifier( + LLVMTypeRef base_type, AstIdentifierRef identifier) { + UNUSED(identifier); + return base_type; +} + +LLVMTypeRef get_type_with_type(LLVMTypeRef base_type, AstRef ast) { + switch (ast->tag) { + case AST_DECLARATOR: + return get_type_with_type_declarator(base_type, ast_get_declarator(ast)); + case AST_DIRECT_DECLARATOR: + return get_type_with_type_direct_declarator( + base_type, ast_get_direct_declarator(ast)); + case AST_POINTER: + return get_type_with_type_pointer( base_type, ast_get_pointer(ast)); + case AST_IDENTIFIER: + return get_type_with_type_identifier(base_type, ast_get_identifier(ast)); + default: + return NULL; + } +} diff --git a/src/code_generator/value.c b/src/code_generator/value.c new file mode 100644 index 00000000..d670058e --- /dev/null +++ b/src/code_generator/value.c @@ -0,0 +1,77 @@ +#include "code_generator.h" +#include "variable_set.h" +#include "pool.h" +#include "stdstring.h" +#include "ast/expressions_impl.h" +#include "ast/declarations_impl.h" +#include "ast/is_method.h" +#include "ast/get_method.h" +#include "ast/ast_impl.h" + +ValueVectorRef get_arguments( + ValueVectorRef variable_set, + AstArgumentExpressionListRef argument_expression_list) { + AstVectorRef argument_list = argument_expression_list->argument_list; + ValueVectorRef value_vec = ValueVectorFunc(ctor)(NULL); + AstRef *itr; + AstRef *begin = AST_VECTOR_FUNC(begin)(argument_list); + AstRef *end = AST_VECTOR_FUNC(end)(argument_list); + for (itr = begin; itr != end; itr++) { + ValueVectorFunc(push_back)(value_vec, + get_variable(variable_set, *itr)); + } + return value_vec; +} + +LLVMValueRef make_value_initializer( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef type, AstInitializerRef initializer) { + return make_value(module, builder, variable_set, type, initializer->initializer); +} + +LLVMValueRef make_value_assignment_expression( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef type, AstAssignmentExpressionRef expression) { + return build_expression(module, builder, variable_set, expression->expression); +} + +LLVMValueRef make_value_initializer_list( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef type, AstInitializerListRef initializer_list) { + ValueVectorRef value_vec = ValueVectorFunc(ctor)(NULL); + AstRef *itr; + AstRef *begin = AST_VECTOR_FUNC(begin)(initializer_list->initializer_vector); + AstRef *end = AST_VECTOR_FUNC(end)(initializer_list->initializer_vector); + for (itr = begin; itr != end; itr++) { + ValueVectorFunc(push_back)( + value_vec, make_value(module, builder, variable_set, type, *itr)); + } + switch (LLVMGetTypeKind(type)) { + case LLVMStructTypeKind: + return LLVMConstStruct( + ValueVectorFunc(data)(value_vec), ValueVectorFunc(size)(value_vec), false); + case LLVMArrayTypeKind: + return LLVMConstArray( + LLVMGetElementType(type), ValueVectorFunc(data)(value_vec), + ValueVectorFunc(size)(value_vec)); + default: + return NULL; + } +} + +LLVMValueRef make_value( + LLVMModuleRef module, LLVMBuilderRef builder, ValueVectorRef variable_set, + LLVMTypeRef type, AstRef ast) { + switch (ast->tag) { + case AST_INITIALIZER: + return make_value_initializer(module, builder, variable_set, type, + ast_get_initializer(ast)); + case AST_ASSIGNMENT_EXPRESSION: + return make_value_assignment_expression(module, builder, variable_set, type, + ast_get_assignment_expression(ast)); + case AST_INITIALIZER_LIST: + return make_value_initializer_list(module, builder, variable_set, type, + ast_get_initializer_list(ast)); + default:; + } +} diff --git a/src/code_generator/variable_set.c b/src/code_generator/variable_set.c new file mode 100644 index 00000000..57bbec37 --- /dev/null +++ b/src/code_generator/variable_set.c @@ -0,0 +1,44 @@ +#include "variable_set.h" +#include +#include "vector_impl.h" +#include "ast/get_method.h" +#include "ast/lexical_elements_impl.h" +#include "ast/expressions_impl.h" +#include "ast/ast_impl.h" +#include "stdstring.h" + +LLVMValueRef get_variable_identifier( + ValueVectorRef variable_set, AstIdentifierRef name) { + AstTokenRef name_str = ast_get_token(name->token); + LLVMValueRef *itr; + LLVMValueRef *begin = ValueVectorFunc(begin)(variable_set); + LLVMValueRef *end = ValueVectorFunc(end)(variable_set); + for (itr = begin; itr != end; itr++) { + if (strcmp(LLVMGetValueName(*itr), string_data(name_str)) == 0) + return *itr; + } + return NULL; +} + +LLVMValueRef get_variable_unary_expression( + ValueVectorRef variable_set, AstUnaryExpressionRef unary) { + return get_variable(variable_set, unary->unary); +} + +LLVMValueRef get_variable_postfix_expression( + ValueVectorRef variable_set, AstPostfixExpressionRef postfix) { + return get_variable(variable_set, postfix->postfix); +} + +LLVMValueRef get_variable(ValueVectorRef variable_set, AstRef ast) { + switch (ast->tag) { + case AST_UNARY_EXPRESSION: + return get_variable_unary_expression(variable_set, ast_get_unary_expression(ast)); + case AST_POSTFIX_EXPRESSION: + return get_variable_postfix_expression(variable_set, ast_get_postfix_expression(ast)); + case AST_IDENTIFIER: + return get_variable_identifier(variable_set, ast_get_identifier(ast)); + default:; + } + return NULL; +} diff --git a/src/code_generator/variable_set.h b/src/code_generator/variable_set.h new file mode 100644 index 00000000..506a604c --- /dev/null +++ b/src/code_generator/variable_set.h @@ -0,0 +1,11 @@ +#ifndef KMC_C89_COMPILER_VARIABLE_SET_H +#define KMC_C89_COMPILER_VARIABLE_SET_H + +#include +#include "ast.h" +#include "pool.h" + +LLVMValueRef get_variable(ValueVectorRef variable_set, AstRef ast); +LLVMValueRef get_variable_identifier(ValueVectorRef variable_set, AstIdentifierRef ast); + +#endif /* KMC_C89_COMPILER_VARIABLE_SET_H */