.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;
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)
}
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)
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;