main.c (4595B)
1 #include <assert.h> 2 #include <fcntl.h> 3 #include <stdbool.h> 4 #include <string.h> 5 #include <stdint.h> 6 #include <stdio.h> 7 #include <sys/stat.h> 8 #include <sys/mman.h> 9 #include <unistd.h> 10 11 #include "array.h" 12 #include "nooc.h" 13 #include "stack.h" 14 #include "ir.h" 15 #include "util.h" 16 #include "elf.h" 17 #include "type.h" 18 #include "map.h" 19 #include "target.h" 20 21 static struct stack blocks; 22 struct assgns assgns; 23 struct exprs exprs; 24 struct target targ; 25 struct toplevel toplevel; 26 struct map *typesmap; 27 char *infile; 28 29 struct block parse(const struct token *const start); 30 struct token *lex(struct slice start); 31 32 uint64_t 33 data_push(const char *const ptr, const size_t len) 34 { 35 array_push((&toplevel.data), ptr, len); 36 return DATA_OFFSET + toplevel.data.len - len; 37 } 38 39 uint64_t 40 data_pushzero(const size_t len) 41 { 42 array_zero((&toplevel.data), len); 43 return DATA_OFFSET + toplevel.data.len - len; 44 } 45 46 void 47 data_set(const uint64_t addr, const void *const ptr, const size_t len) 48 { 49 memcpy(&toplevel.data.data[addr - DATA_OFFSET], ptr, len); 50 } 51 52 void 53 evalexpr(struct decl *const decl) 54 { 55 struct expr *expr = &exprs.data[decl->val]; 56 if (expr->kind == EXPR_LIT) { 57 switch (expr->class) { 58 case C_INT: { 59 const struct type *const type = &types.data[decl->type]; 60 data_set(decl->w.addr, &expr->d.v.v, type->size); 61 break; 62 } 63 case C_STR: { 64 const uint64_t addr = data_push(expr->d.v.v.s.data, expr->d.v.v.s.len); 65 decl->w.addr = addr; 66 break; 67 } 68 default: 69 error(expr->start->line, expr->start->col, "genexpr: unknown value type!"); 70 } 71 } else { 72 error(expr->start->line, expr->start->col, "cannot evaluate expression at compile time"); 73 } 74 } 75 76 void 77 gentoplevel(struct toplevel *toplevel, const struct block *const block) 78 { 79 char syscallname[] = "syscall0"; 80 stackpush(&blocks, block); 81 typecheck(&blocks, block); 82 struct iproc iproc = { 0 }; 83 uint64_t curaddr = TEXT_OFFSET; 84 85 iproc.s = (struct slice){8, 8, syscallname}; 86 for (int i = 1; i < 8; i++) { 87 syscallname[7]++; 88 iproc.s.data = strdup(syscallname); 89 iproc.addr = curaddr; 90 array_add((&toplevel->code), iproc); 91 curaddr += targ.emitsyscall(&toplevel->text, i); 92 } 93 for (int i = 0; i < block->len; i++) { 94 const struct statement *const statement = &block->data[i]; 95 96 switch (statement->kind) { 97 case STMT_EXPR: 98 die("toplevel expressions are unimplemented"); 99 case STMT_ASSGN: 100 die("toplevel assignments are unimplemented"); 101 case STMT_DECL: { 102 struct decl *const decl = &block->decls.data[statement->idx]; 103 const struct expr *const expr = &exprs.data[decl->val]; 104 const struct type *const type = &types.data[decl->type]; 105 106 if (type->class == TYPE_PROC) { 107 assert(expr->class == C_PROC); 108 assert(expr->kind == EXPR_PROC); 109 iproc = (struct iproc){ 110 .s = decl->s, 111 .addr = curaddr 112 }; 113 114 if (slice_cmplit(&decl->s, "main") == 0) 115 toplevel->entry = curaddr; 116 117 stackpush(&blocks, &expr->d.proc.block); 118 typecheck(&blocks, &expr->d.proc.block); 119 genproc(&blocks, &iproc, &expr->d.proc); 120 array_add((&toplevel->code), iproc); 121 curaddr += targ.emitproc(&toplevel->text, &iproc); 122 stackpop(&blocks); 123 } else { 124 if (slice_cmplit(&decl->s, "main") == 0) 125 die("global main must be procedure"); 126 127 if (type->class == TYPE_ARRAY) { 128 const struct type *const subtype = &types.data[type->d.arr.subtype]; 129 decl->w.addr = data_pushzero(subtype->size * type->d.arr.len); 130 } else { 131 decl->w.addr = data_pushzero(type->size); 132 } 133 134 evalexpr(decl); 135 } 136 break; 137 } 138 default: 139 die("unreachable"); 140 } 141 142 } 143 stackpop(&blocks); 144 } 145 146 int 147 main(int argc, char *argv[]) 148 { 149 targ = x64_target; 150 if (argc < 3) { 151 fprintf(stderr, "not enough args\n"); 152 return 1; 153 } 154 155 infile = argv[1]; 156 const int in = open(infile, 0, O_RDONLY); 157 if (in < 0) { 158 fprintf(stderr, "couldn't open input\n"); 159 return 1; 160 } 161 162 struct stat statbuf; 163 if (fstat(in, &statbuf) < 0) { 164 close(in); 165 fprintf(stderr, "failed to stat in file\n"); 166 return 1; 167 } 168 169 char *const addr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, in, 0); 170 close(in); 171 if (addr == NULL) { 172 fprintf(stderr, "failed to map input file into memory\n"); 173 return 1; 174 } 175 176 const struct token *const head = lex((struct slice){statbuf.st_size, statbuf.st_size, addr}); 177 178 typesmap = mkmap(16); 179 inittypes(); 180 const struct block statements = parse(head); 181 182 gentoplevel(&toplevel, &statements); 183 184 FILE *const out = fopen(argv[2], "w"); 185 if (!out) { 186 close(in); 187 fprintf(stderr, "couldn't open output\n"); 188 return 1; 189 } 190 191 munmap(addr, statbuf.st_size); 192 193 elf(toplevel.entry, &toplevel.text, &toplevel.data, out); 194 195 fclose(out); 196 }