Skip to content
Snippets Groups Projects
Commit 55709080 authored by Clemens Paumgarten's avatar Clemens Paumgarten
Browse files

tac start

parent 578bacc3
No related branches found
No related tags found
No related merge requests found
......@@ -37,8 +37,10 @@ add_executable(mcc
src/symbol_table_semantic_error.c
include/mcc/symbol_table_semantic_error.h
src/symbol_table_parse.c
include/mcc/tac_build.h
include/mcc/symbol_table_parse.h
include/mcc/symbol_table_validate.h
src/tac_build.c
src/symbol_table_validate.c
include/mcc/symbol_table_print.h
src/symbol_table_print.c
......@@ -49,4 +51,8 @@ add_executable(mcc
src/utils/mcc_scope.c
include/mcc/mcc_scope.h
src/utils/dynamic_array.c
include/mcc/dynamic_array.h include/mcc/mcc.h)
include/mcc/dynamic_array.h
include/mcc/mcc.h
app/mc_ir.c
src/tac.c
include/mcc/tac.h src/tac_string_builder.c include/mcc/tac_string_builder.h src/utils/utils.c include/mcc/utils.h)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <ctype.h>
#include "mcc/ast.h"
#include "mcc/parser.h"
#include "mcc/symbol_table.h"
#include "mcc/symbol_table_parse.h"
#include "mcc/symbol_table_print.h"
#include "mcc/printer.h"
#include "mcc/mcc_scope.h"
int main(int argc, char *argv[]) {
char* symbol_scope = "program";
FILE* out = stdout;
if (argc < 2) {
mcc_symbol_table_print_usage(argv[0]);
return EXIT_FAILURE;
}
int c;
static struct option options[] = {
{ "help", no_argument, 0, 'h' },
{ "output", required_argument, 0, 'o' },
{ "function", required_argument, 0, 'f' },
{ 0, 0, 0, 0 }
};
while ((c = getopt_long(argc, argv, "hf:o:", options, NULL)) != -1) {
switch(c) {
case 'h':
mcc_symbol_table_print_usage(argv[0]);
return EXIT_SUCCESS;
case 'o':
out = fopen(optarg, "rw");
break;
case 'f':
symbol_scope = optarg;
break;
case '?':
if(isprint(optopt))
fprintf(stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf(stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
abort();
}
}
// get input src
char *input = NULL;
if (optind < argc) {
input = argv[optind];
} else {
fprintf(stderr, "%s: Missing input!\n", argv[0]);
mcc_symbol_table_print_usage(argv[0]);
return EXIT_FAILURE;
}
FILE *in;
if (strcmp("-", input) == 0) {
in = stdin;
} else {
in = fopen(input, "r");
if (!in) {
perror("fopen");
return EXIT_FAILURE;
}
}
struct mcc_ast_program *prog = NULL;
// parsing phase
{
struct mcc_parser_result result = mcc_parse_file(in);
if (result.status != MCC_PARSER_STATUS_OK) {
// print error message
printf("%s", result.parser_error -> error_msg);
return EXIT_FAILURE;
}
prog = result.program;
}
// create symbol table
struct mcc_symbol_table_error_collector *ec = mcc_symbol_table_new_error_collector();
struct mcc_symbol_table *symbol_table;
// check if scope should be limited
if (strcmp("program", symbol_scope) == 0) {
symbol_table = mcc_symbol_table_build(prog, ec);
} else {
struct mcc_ast_function *func = mcc_limit_scope_to_function(symbol_scope, prog);
symbol_table = mcc_symbol_table_build(func, ec);
}
if (symbol_table == NULL) {
mcc_symbol_table_print_error(ec, out);
return EXIT_FAILURE;
}
mcc_symbol_table_print(symbol_table,out);
mcc_symbol_table_delete_table(symbol_table);
mcc_symbol_table_delete_error_collector(ec);
mcc_ast_delete(prog);
return EXIT_SUCCESS;
}
......@@ -350,6 +350,8 @@ void mcc_ast_empty_node();
struct mcc_ast_parameter {
struct mcc_ast_node node;
// declarations
Dynamic_Array *parameters;
};
......
......@@ -57,7 +57,6 @@ struct mcc_symbol_table_error_collector {
};
struct mcc_symbol_table_error_collector *mcc_symbol_table_new_error_collector();
struct mcc_semantic_error *mcc_symbol_table_new_error(struct mcc_ast_source_location *loc, enum mcc_semantic_error_type type);
......
#ifndef MCC_TAC_H
#define MCC_TAC_H
#include "ast.h"
#include "dynamic_array.h"
#define MCC_TAC_ENTRY_SIZE 10
#define MCC_TAC_ERROR_SIZE 10
enum mcc_tac_operation{
MCC_TAC_BOOL_LITERAL,
MCC_TAC_INT_LITERAL,
MCC_TAC_STRING_LITERAL,
MCC_TAC_FLOAT_LITERAL,
// IDENTIFIER
MCC_TAC_IDENTIFIER_STRING,
MCC_TAC_IDENTIFIER_BOOL,
MCC_TAC_IDENTIFIER_INT,
MCC_TAC_IDENTIFIER_FLOAT,
MCC_TAC_UNARY_EXPRESSION,
MCC_TAC_BINARY_EXPRESSION,
MCC_TAC_NEGATE_INT,
MCC_TAC_NEGATE_FLOAT,
// Binary ops
MCC_TAC_NOT_BOOL,
MCC_TAC_PLUS_INT,
MCC_TAC_PLUS_FLOAT,
MCC_TAC_MINUS_INT,
MCC_TAC_MINUS_FLOAT,
MCC_TAC_MUL_INT,
MCC_TAC_MUL_FLOAT,
MCC_TAC_DIV_INT,
MCC_TAC_DIV_FLOAT,
MCC_TAC_EQ,
MCC_TAC_NEQ,
MCC_TAC_GT,
MCC_TAC_LT,
MCC_TAC_LTEQ,
MCC_TAC_GTEQ,
MCC_TAC_LT_FLOAT,
MCC_TAC_LTEQ_FLOAT,
MCC_TAC_GT_FLOAT,
MCC_TAC_GTEQ_FLOAT,
MCC_TAC_EQ_FLOAT,
MCC_TAC_NEQ_FLOAT,
MCC_TAC_AND,
MCC_TAC_OR,
// variable
MCC_TAC_VARIABLE_DECLARATION,
MCC_TAC_VARIABLE_ASSIGNMENT,
// IR operations
MCC_TAC_JMP,
MCC_TAC_JMP_FALSE,
};
enum mcc_tac_error_type {};
struct mcc_tac_entry {
enum mcc_tac_operation tac_op;
char *arg1;
char *arg2;
char *result;
};
struct mcc_tac {
// list of tac entries
Dynamic_Array *tac_entries;
int label_count;
int temporary_count;
// these are used to easily access the last temporary and label string of a tac object
char *last_label;
char *last_temporary;
struct mcc_tac *next;
struct mcc_tac *prev;
};
struct mcc_tac_error {
struct mcc_ast_source_location *sloc;
enum mcc_tac_error_type error_type;
};
struct mcc_tac_error_collector {
// array of mcc_tac_error
Dynamic_Array *errors;
};
struct mcc_tac *mcc_tac_new(struct mcc_tac *prev_tac);
struct mcc_tac_entry *mcc_tac_new_entry(
enum mcc_tac_operation tac_op,
char *arg1,
char *arg2,
char *result
);
int mcc_tac_add_entry(struct mcc_tac *tac, struct mcc_tac_entry *te);
struct mcc_tac_error_collector *mcc_tac_new_error_collector();
void mcc_tac_delete(struct mcc_tac *tac);
//
#endif //MCC_TAC_H
......@@ -2,70 +2,15 @@
#define MCC_TAC_BUILD_H
#include "ast.h"
#include <stdio.h>
#include "symbol_table.h"
#include "tac.h"
// builds tac by parsing program
struct mcc_tac *mcc_build_tac(struct mcc_ast_program *program, struct mcc_symbol_table *st);
enum mcc_tac_operation{
struct mcc_tac *mcc_tac_parse_statement(struct mcc_ast_statement *statement, struct mcc_tac *tac);
MCC_TAC_BOOL_LITERAL,
MCC_TAC_INT_LITERAL,
MCC_TAC_STRING_LITERAL,
MCC_TAC_FLOAT_LITERAL,
MCC_TAC_IDENTIFIER,
MCC_TAC_UNARY_EXPRESSION,
MCC_TAC_BINARY_EXPRESSION,
MCC_TAC_NEGATE_INT,
MCC_TAC_NEGATE_FLOAT,
MCC_TAC_NOT_BOOL,
MCC_TAC_PLUS_INT,
MCC_TAC_PLUS_FLOAT,
MCC_TAC_MINUS_INT,
MCC_TAC_MINUS_FLOAT,
MCC_TAC_MUL_INT,
MCC_TAC_MUL_FLOAT,
MCC_TAC_DIV_INT,
MCC_TAC_DIV_FLOAT,
MCC_TAC_EQ,
MCC_TAC_NEQ,
MCC_TAC_GT,
MCC_TAC_LT,
MCC_TAC_LTEQ,
MCC_TAC_GTEQ,
MCC_TAC_LT_FLOAT,
MCC_TAC_LTEQ_FLOAT,
MCC_TAC_GT_FLOAT,
MCC_TAC_GTEQ_FLOAT,
MCC_TAC_EQ_FLOAT,
MCC_TAC_NEQ_FLOAT,
MCC_TAC_AND,
MCC_TAC_OR,
MCC_TAC_VARIABLE_DECLARATION,
MCC_TAC_VARIABLE_ASSIGNMENT,
MCC_TAC_JMP
void mcc_tac_parse_statement_list(struct mcc_ast_statement_list *stl, struct mcc_tac *tac);
};
// use quadruples like this : https://github.com/fauzanzaid/Quadruple-Three-Address-Code-in-C ??
struct mcc_tac{
enum mcc_tac_operation tac_op;
char *arg1;
char *arg2;
char *result;
struct mcc_tac *next;
struct mcc_tac *prev;
};
struct mcc_tac *mcc_create_tac(struct mcc_ast_expression *expr, struct mcc_tac *tac);
struct mcc_tac *mcc_new_tac();
int mcc_tac_add(struct mcc_tac *tac_prev, struct mcc_tac *tac_add);
void mcc_tac_delete(struct mcc_tac *tac);
#endif
\ No newline at end of file
//
// Created by Clemens Paumgarten on 13.06.19.
//
#ifndef MCC_TAC_STRING_BUILDER_H
#define MCC_TAC_STRING_BUILDER_H
#include "tac.h"
char *mcc_tac_new_temporary_string(struct mcc_tac *tac);
char *mcc_tac_new_label_string(struct mcc_tac *tac);
#endif //MCC_TAC_STRING_BUILDER_H
//
// Created by Clemens Paumgarten on 13.06.19.
//
#ifndef MCC_UTILS_H
#define MCC_UTILS_H
int mcc_get_number_of_digits(int input);
#endif //MCC_UTILS_H
#include <stdlib.h>
#include <assert.h>
#include <tac.h>
// --------------------------------------------- Error Collector
struct mcc_tac_error_collector *mcc_tac_new_error_collector() {
struct mcc_tac_error_collector *ec = malloc(sizeof(*ec));
if (ec == NULL) return NULL;
ec -> errors = mcc_create_dynamic_array(MCC_TAC_ERROR_SIZE);
return ec;
}
int mcc_tac_add_error(struct mcc_tac_error_collector *ec, struct mcc_tac_error *e) {
assert(ec);
assert(e);
return mcc_add_to_array(ec -> errors, e);
}
struct mcc_tac_error *mcc_tac_new_error(struct mcc_ast_source_location *sloc, enum mcc_tac_error_type error_type) {
struct mcc_tac_error *e = malloc(sizeof(*e));
e -> sloc = sloc;
e -> error_type = error_type;
return e;
}
// --------------------------------------------- TAC Object
struct mcc_tac *mcc_tac_new(struct mcc_tac *prev_tac) {
struct mcc_tac *tac = malloc(sizeof(tac));
if(!tac) {
return NULL;
}
tac->prev = prev_tac;
tac->next = NULL;
if(prev_tac != NULL) {
prev_tac->next = tac;
}
tac->tac_entries = mcc_create_dynamic_array(MCC_TAC_ENTRY_SIZE);
tac -> temporary_count = 0;
tac -> label_count = 0;
return tac;
}
struct mcc_tac_entry *mcc_tac_new_entry(
enum mcc_tac_operation tac_op,
char *arg1,
char *arg2,
char *result
) {
struct mcc_tac_entry *te = malloc(sizeof(*te));
te -> tac_op = tac_op;
te -> arg1 = arg1;
te -> arg2 = arg2;
te -> result = result;
return te;
}
int mcc_tac_add_entry(struct mcc_tac *tac, struct mcc_tac_entry *te) {
return mcc_add_to_array(tac -> tac_entries, te);
}
void mcc_tac_delete_entry(void *te) {
struct mcc_tac_entry *tac_entry = (struct mcc_tac_entry *) te;
free(tac_entry);
}
void mcc_tac_delete(struct mcc_tac *tac) {
if(tac->!= NULL) {
mcc_tac_delete(tac->next);
}
mcc_delete_array(tac->tac_entries, mcc_tac_delete_entry);
free(tac);
}
#include "mcc/tac_build.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "tac_build.h"
struct mcc_tac *mcc_new_tac()
{
struct mcc_tac *tac = malloc(sizeof(tac));
// -------------------------------- parse expression
if (!tac) {
return NULL;
static void parse_expression_identifier(struct mcc_ast_identifier *identifier, struct mcc_tac *tac) {
// Get expression type from symbol table
enum mCc_ast_type expression_type =
mCc_symbol_table_check_get_expression_type(
builder->root_st, builder->current_st, expression);
// Get tac copy operation type
enum mCc_tac_operation_type type = get_copy_type(expression_type);
// Create arg1 from identifier
char *arg1 = id->name;
create_and_add_line_new_temp(builder, type, arg1, NULL);
}
void mcc_tac_parse_expression(struct mcc_ast_expression *expression, struct mcc_tac *tac) {
assert(expression);
assert(tac);
switch (expression -> type) {
case MCC_AST_EXPRESSION_TYPE_IDENTIFIER:
char *temp =
break;
default:
return;
}
}
tac -> tac_op = NULL;
tac -> arg1 = NULL;
tac -> arg2 = NULL;
tac -> result = NULL;
// -------------------------------- parse statement
tac -> prev = NULL;
tac -> next = NULL;
struct mcc_tac *mcc_tac_parse_statement_if(struct mcc_ast_statement *if_st, struct mcc_tac *tac) {
// create new tac
return tac;
// evaluate condition expression
// jumpfalse
// true condition
// false condition
}
struct mcc_tac *mcc_create_tac(struct mcc_ast_expression *expr, struct mcc_tac *tac)
{
switch (expr->type)
{
case MCC_AST_EXPRESSION_TYPE_PARENTH:
mcc_create_tac(expr->expression,tac);
break;
case MCC_AST_EXPRESSION_TYPE_BINARY_OP:
struct mcc_tac *tac_bin = mcc_new_tac();
if(expr->lhs->type == MCC_AST_EXPRESSION_TYPE_LITERAL ){
tac_bin->arg1 = ast_literal_to_char(expr->lhs,tac);
}
if(expr->rhs->type == MCC_AST_EXPRESSION_TYPE_LITERAL){
// TODO literal to char
tac_bin->arg2 = ast_literal_to_char(expr->rhs,tac);
void mcc_tac_parse_statement_list(struct mcc_ast_statement_list *stl, struct mcc_tac *tac) {
assert(stl);
assert(tac);
while (stl != NULL) {
mcc_tac_parse_statement(stl -> statement, tac);
stl = stl -> next;
}
}
struct mcc_tac *mcc_tac_parse_statement(struct mcc_ast_statement *statement, struct mcc_tac *tac) {
switch (statement -> type) {
case MCC_AST_STATEMENT_TYPE_COMPOUND:
mcc_tac_parse_statement_list(statement -> statement_list, tac);
case MCC_AST_STATEMENT_TYPE_IF:
return NULL;
}
case MCC_AST_EXPRESSION_TYPE_CALL_EXPRESSION:
case MCC_AST_EXPRESSION_TYPE_UNARY_OP:
case MCC_AST_EXPRESSION_TYPE_LITERAL:
//TODO parse MCC_AST types to MCC_TAC_OP types
break;
default:
break;
}
// -------------------------------- parse function
int mcc_tac_parse_function(struct mcc_ast_function *f, struct mcc_tac *tac) {
assert(f);
assert(tac);
// TODO: do something with params
if (f->statement != NULL) {
mcc_tac_parse_statement(f -> statement, tac);
}
}
char *ast_literal_to_char(struct mcc_ast_expression *expr, struct mcc_tac *tac){
char *string;
switch (expr->literal->type) {
case MCC_AST_DATA_TYPE_INT:
string = malloc(sizeof(char) * (myLog10(expr->literal->i_value, 0) + 2));
sprintf(string, "%ld", expr->literal->i_value);
break;
case MCC_AST_DATA_TYPE_FLOAT:
string = malloc(sizeof(char) * 64);
sprintf(string, "%lf", expr->literal->f_value);
break;
case MCC_AST_DATA_TYPE_STRING:
string = expr->literal->s_value;
break;
case MCC_AST_DATA_TYPE_BOOL:
string = expr->literal->b_value;
break;
case MCC_AST_DATA_TYPE_VOID:
string = "void";
break;
default:
string = "Error ast_literal_to_char";
// start parsing program
struct mcc_tac *mcc_tac_build(struct mcc_ast_program *program, struct mcc_symbol_table *st) {
struct mcc_tac *tac = mcc_tac_new(NULL);
struct mcc_ast_function *f = NULL;
// look for main an start parsing program
for (int i = 0; i < program -> function_def -> size; i++) {
f = program -> function_def -> arr[i];
if (strcmp(f -> identifier -> i_value, "main") == 0) {
mcc_tac_parse_function(f, tac);
}
return string;
}
\ No newline at end of file
}
// for (int i = 0; i < program -> function_def -> size; i++) {
// struct mcc_ast_function *f = program -> function_def -> arr[i];
//
// mcc_tac_parse_function(f, tac);
// }
return tac;
}
//char *ast_literal_to_char(struct mcc_ast_expression *expr, struct mcc_tac *tac){
// char *string;
// switch (expr->literal->type) {
// case MCC_AST_DATA_TYPE_INT:
// string = malloc(sizeof(char) * (myLog10(expr->literal->i_value, 0) + 2)); // why log10?
// sprintf(string, "%ld", expr->literal->i_value);
// break;
//
// case MCC_AST_DATA_TYPE_FLOAT:
// string = malloc(sizeof(char) * 64);
// sprintf(string, "%lf", expr->literal->f_value);
// break;
//
// case MCC_AST_DATA_TYPE_STRING:
// string = expr->literal->s_value;
// break;
//
// case MCC_AST_DATA_TYPE_BOOL:
// string = expr->literal->b_value ? "1" : "0";
// break;
// case MCC_AST_DATA_TYPE_VOID:
// string = "void";
// break;
//
// default:
// string = "Error ast_literal_to_char";
// }
//
// return string;
//}
//
//static struct mcc_tac *new_tac_binary(struct mcc_ast_expression *expr) {
// struct mcc_tac *tac_bin = mcc_new_tac();
//
// if(expr->lhs->type == MCC_AST_EXPRESSION_TYPE_LITERAL ){
// tac_bin->arg1 = ast_literal_to_char(expr->lhs,tac);
// }
// if(expr->rhs->type == MCC_AST_EXPRESSION_TYPE_LITERAL){
// // TODO literal to char
// tac_bin->arg2 = ast_literal_to_char(expr->rhs,tac);
// }
//
//}
//
//struct mcc_tac *mcc_create_tac(struct mcc_ast_expression *expr, struct mcc_tac *tac) {
// struct mcc_tac *next_tac = malloc(sizeof(*next_tac));
//
// // add new tac object to linked list
// next_tac -> prev = tac;
// next_tac -> next = NULL;
// tac -> next = next_tac;
//
//
//
//
//// struct mcc_tac *tac_bin;
//// switch (expr->type) {
////
//// case MCC_AST_EXPRESSION_TYPE_PARENTH:
//// mcc_create_tac(expr->expression,tac);
//// break;
//// case MCC_AST_EXPRESSION_TYPE_BINARY_OP:
//// if(expr->lhs->type == MCC_AST_EXPRESSION_TYPE_LITERAL ){
//// tac_bin->arg1 = ast_literal_to_char(expr->lhs,tac);
//// }
//// if(expr->rhs->type == MCC_AST_EXPRESSION_TYPE_LITERAL){
//// // TODO literal to char
//// tac_bin->arg2 = ast_literal_to_char(expr->rhs,tac);
//// }
//// case MCC_AST_EXPRESSION_TYPE_CALL_EXPRESSION:
//// case MCC_AST_EXPRESSION_TYPE_UNARY_OP:
//// case MCC_AST_EXPRESSION_TYPE_LITERAL:
//// //TODO parse MCC_AST types to MCC_TAC_OP types
////
//// break;
////
//// default:
//// break;
//// }
//}
#include <stdlib.h>
#include <stdio.h>
#include "utils.h"
#include "tac_string_builder.h"
char *mcc_tac_new_temporary_string(struct mcc_tac *tac) {
size_t num_digits = (size_t) mcc_get_number_of_digits(tac -> temporary_count);
// +2 for character t and for \0
char *t = malloc(num_digits + 2);
if (t == NULL) {
return NULL;
}
sprintf(t, "t%d", tac -> temporary_count);
tac -> temporary_count++;
tac -> last_temporary = t;
return t;
}
char *mcc_tac_new_label_string(struct mcc_tac *tac) {
size_t num_digits = (size_t) mcc_get_number_of_digits(tac -> label_count);
// +2 for character t and for \0
char *t = malloc(num_digits + 2);
if (t == NULL) {
return NULL;
}
sprintf(t, "L%d", tac -> label_count);
tac -> label_count++;
tac -> last_label = t;
return t;
}
int mcc_get_number_of_digits(int input) {
int digits = 0;
while (input != 0) {
input /= 10;
digits++;
}
return digits;
}
\ No newline at end of file
......@@ -2,9 +2,10 @@ int main() {
int a;
if (1 < 2) {
a = 1;
int b;
b = 2;
int a;
{
int a;
}
}
return 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment