From: Michael D. Lowis Date: Thu, 10 Feb 2022 21:50:07 +0000 (-0500) Subject: added some type generation code for llvm ir X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=3759374c29fa7c71dbd33a0ea9a38aef4aa0904e;p=proto%2Fobnc.git added some type generation code for llvm ir --- diff --git a/cerise/backend/ssa/codegen.c b/cerise/backend/ssa/codegen.c index fc09ae9..571eaf6 100644 --- a/cerise/backend/ssa/codegen.c +++ b/cerise/backend/ssa/codegen.c @@ -26,14 +26,77 @@ Type StringType = { .size = -1 }; +static char* strmcat(char* first, ...) { + va_list args; + /* calculate the length of the final string */ + size_t len = strlen(first); + va_start(args, first); + for (char* s = NULL; (s = va_arg(args, char*));) + len += strlen(s); + va_end(args); + /* allocate the final string and copy the args into it */ + char *str = malloc(len+1), *curr = str; + while (first && *first) *(curr++) = *(first++); + va_start(args, first); + for (char* s = NULL; (s = va_arg(args, char*));) + while (s && *s) *(curr++) = *(s++); + va_end(args); + /* null terminate and return */ + *curr = '\0'; + return str; +} + +void declare_record_type(Type* type) +{ + if (!type->name) + { + /* print the field typedefs if needed */ + for (Field* f = type->fields; f; f = f->next) + { + if (f->type->form == FORM_RECORD) + { + declare_record_type(f->type); + } + } + + /* ok print the top level typedef */ + int len = snprintf(NULL, 0, "%%struct.%p", (void*)type); + type->name = calloc(1, len+1); + (void)snprintf(type->name, len+1, "%%struct.%p", (void*)type); + + printf("%s = type { ", type->name); + for (Field* f = type->fields; f; f = f->next) + { + emit_type(f->type); + if (f->next) + { + printf(", "); + } + } + printf(" }\n"); + } +} + + void emit_type(Type* type) { switch (type->form) { - case FORM_BOOL: printf("@Bool"); break; - case FORM_INT: printf("@Int"); break; - case FORM_REAL: printf("@Real"); break; - case FORM_VOID: printf("@Void"); break; + case FORM_BOOL: printf("%%Bool"); break; + case FORM_INT: printf("%%Int"); break; + case FORM_REAL: printf("%%Real"); break; + case FORM_VOID: printf("%%Void"); break; + case FORM_STRING: printf("%%String"); break; + + case FORM_ARRAY: + printf("[]"); + break; + + case FORM_RECORD: + printf("%%%s", type->name); + break; + + case FORM_PROC: default: printf("????"); break; @@ -42,10 +105,12 @@ void emit_type(Type* type) void codegen_init(Parser* p) { - printf("@Bool = type i1\n"); - printf("@Int = type i64\n"); - printf("@Real = type double\n"); - printf("@Void = type void\n"); + (void)p; + printf("%%Bool = type i1\n"); + printf("%%Int = type i64\n"); + printf("%%Real = type double\n"); + printf("%%Void = type void\n"); + printf("%%String = type { i64, i8* }\n"); } void codegen_symbol(Parser* p, Symbol* sym) @@ -61,6 +126,10 @@ void codegen_symbol(Parser* p, Symbol* sym) } else if (sym->class == SYM_TYPE) { + if (sym->type->form == FORM_RECORD) + { + declare_record_type(sym->type); + } printf("%c%s = type \n", (sym->global ? '@' : '%'), sym->name); } else if (sym->class == SYM_PROC) diff --git a/cerise/inc/cerise.h b/cerise/inc/cerise.h index 0e9d625..4d664bc 100644 --- a/cerise/inc/cerise.h +++ b/cerise/inc/cerise.h @@ -90,10 +90,15 @@ typedef struct Field { typedef struct Type { enum { - FORM_BOOL, FORM_INT, FORM_REAL, FORM_ARRAY, FORM_STRING, - FORM_RECORD, FORM_PROC, FORM_VOID, + /* base types */ + FORM_BOOL, FORM_INT, FORM_REAL, FORM_VOID, + + /* aggregate types */ + FORM_ARRAY, FORM_RECORD, FORM_STRING, FORM_PROC, + FORM_COUNT } form; + char* name; struct Field* fields; struct Type* base; int size; diff --git a/cerise/tests/Module.m b/cerise/tests/Module.m index 53c6946..61aa3c6 100644 --- a/cerise/tests/Module.m +++ b/cerise/tests/Module.m @@ -40,6 +40,7 @@ var f : TypeD g : array 5 of Int h : TypeF + i : TypeA #procedure Foo*(e : Int, z : Int, q1 : TypeD, q2 : array 5 of Int) : Int # const FOO = 2 @@ -70,6 +71,8 @@ begin end begin + i = 42; + b = i; b = 1; if c == b then b = b - 1;