os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

cc1.om (26492B)


      1 struct compiler {
      2 	// Allocator
      3 	a: *alloc;
      4 
      5 	err: *file;
      6 
      7 	// Parser
      8 	p: *parser;
      9 
     10 	// Context
     11 	filename: *byte;
     12 	lineno: int;
     13 	colno: int;
     14 
     15 	// Assembler
     16 	s: *assembler;
     17 
     18 	// Namespace
     19 	decls: *decl;
     20 
     21 	// C Output
     22 	do_cout: int;
     23 	cout: *file;
     24 
     25 	// Call graph
     26 	call_out: *file;
     27 
     28 	// Entry points
     29 	start: *label;
     30 	kstart: *label;
     31 
     32 	// Usage stack
     33 	used_top: *decl;
     34 
     35 	lex_action: **byte;
     36 	lex_action_len: int;
     37 	lex_action_cap: int;
     38 	nfa_id: int;
     39 	dfa_id: int;
     40 	dfa_cache: *rbnode;
     41 
     42 	mach: *machine;
     43 }
     44 
     45 struct machine {
     46 	id: int;
     47 	emit_builtin: func(c: *compiler);
     48 	output_ir: func(c: *compiler, d: *decl);
     49 }
     50 
     51 struct parser {
     52 	a: *alloc;
     53 	c: *compiler;
     54 	err: *file;
     55 }
     56 
     57 func cshow_context(c: *compiler) {
     58 	fputs(c.err, "on ");
     59 	if (c.filename) {
     60 		fputs(c.err, c.filename);
     61 	}
     62 	fputs(c.err, ":");
     63 	fputd(c.err, c.lineno);
     64 	fputs(c.err, ":");
     65 	fputd(c.err, c.colno);
     66 	fputs(c.err, "\n");
     67 }
     68 
     69 func cdie(c: *compiler, msg: *byte) {
     70 	cshow_context(c);
     71 	fputs(c.err, "cdie: ");
     72 	fputs(c.err, msg);
     73 	fputs(c.err, "\n");
     74 	exit(1);
     75 }
     76 
     77 func setup_parser(c: *compiler, err: *file): *parser {
     78 	var p: *parser;
     79 	p = alloc(c.a, sizeof(*p)) as *parser;
     80 	p.a = c.a;
     81 	p.c = c;
     82 	p.err = err;
     83 	return p;
     84 }
     85 
     86 func comp_setup(a: *alloc, err: *file): *compiler {
     87 	var c: *compiler;
     88 
     89 	c = alloc(a, sizeof(*c)) as *compiler;
     90 
     91 	c.a = a;
     92 
     93 	c.err = err;
     94 
     95 	c.p = setup_parser(c, err);
     96 
     97 	c.filename = nil;
     98 	c.lineno = 0;
     99 	c.colno = 0;
    100 
    101 	c.s = setup_assembler(a);
    102 
    103 	c.decls = nil;
    104 
    105 	c.do_cout = 0;
    106 	c.cout = nil;
    107 
    108 	c.start = nil;
    109 	c.kstart = nil;
    110 
    111 	c.used_top = nil;
    112 
    113 	return c;
    114 }
    115 
    116 func open_coutput(c: *compiler, filename: *byte) {
    117 	var fd: int;
    118 
    119 	if (c.cout) {
    120 		die("multiple output files");
    121 	}
    122 
    123 	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) + (6 << 3) + 6);
    124 	if (fd < 0) {
    125 		die("open_coutput: failed to open output");
    126 	}
    127 
    128 	c.cout = fopen(fd, c.a);
    129 	c.cout.noflush = 1;
    130 }
    131 
    132 func compile(c: *compiler, p: *node) {
    133 	var n: *node;
    134 	var d: *decl;
    135 	var v: *decl;
    136 	var kind: int;
    137 
    138 	// Process enum and struct declarations
    139 	n = p;
    140 	loop {
    141 		if (!n) {
    142 			break;
    143 		}
    144 
    145 		kind = n.a.kind;
    146 		if (kind == N_STRUCT) {
    147 			defstruct(c, n.a);
    148 		} else if (kind == N_UNION) {
    149 			defunion(c, n.a);
    150 		} else if (kind == N_ENUM) {
    151 			defenum(c, n.a);
    152 		} else if (kind != N_FUNC && kind != N_FUNCDECL && kind != N_LEXER && kind != N_GRAMMAR) {
    153 			cdie(c, "invalid decl");
    154 		}
    155 
    156 		n = n.b;
    157 	}
    158 
    159 	// Process function declarations
    160 	n = p;
    161 	loop {
    162 		if (!n) {
    163 			break;
    164 		}
    165 
    166 		kind = n.a.kind;
    167 		if (kind == N_FUNCDECL) {
    168 			defextern(c, n.a);
    169 		} else if (kind == N_FUNC) {
    170 			defun(c, n.a);
    171 		} else if (kind == N_LEXER) {
    172 			lexer_compile(c, n.a, nil);
    173 		} else if (kind == N_GRAMMAR) {
    174 			lalr_compiler(c, n.a, nil);
    175 		}
    176 
    177 		n = n.b;
    178 	}
    179 
    180 	// Allocate structs
    181 	d = first_decl(c);
    182 	loop {
    183 		if (!d) {
    184 			break;
    185 		}
    186 
    187 		if (d.struct_defined) {
    188 			layout_struct(c, d);
    189 		}
    190 
    191 		d = next_decl(c, d);
    192 	}
    193 
    194 	// Typecheck functions and translate to ir
    195 	d = first_decl(c);
    196 	loop {
    197 		if (!d) {
    198 			break;
    199 		}
    200 
    201 		if d.func_defined && d.func_def {
    202 			typecheck_stmt(c, d, d.func_def.b);
    203 			d.func_ir = func_to_ir(c, d.func_def);
    204 		}
    205 
    206 		d = next_decl(c, d);
    207 	}
    208 
    209 	// Check usage
    210 	d = find(c, "_start", nil, 0);
    211 	if (d && d.func_defined) {
    212 		c.start = d.func_label;
    213 		mark_func_used(c, nil, d);
    214 	}
    215 
    216 	d = find(c, "_kstart", nil, 0);
    217 	if (d && d.func_defined) {
    218 		c.kstart = d.func_label;
    219 		mark_func_used(c, nil, d);
    220 	}
    221 
    222 	check_usage(c);
    223 
    224 	d = find(c, "_isr0", nil, 0);
    225 	if d && d.func_used {
    226 		v = find(c, "_isr", nil, 0);
    227 		if (v && v.func_defined) {
    228 			mark_func_used(c, d, v);
    229 		}
    230 	}
    231 
    232 	d = find(c, "_ssr0", nil, 0);
    233 	if d && d.func_used {
    234 		v = find(c, "_ssr", nil, 0);
    235 		if (v && v.func_defined) {
    236 			mark_func_used(c, d, v);
    237 		}
    238 	}
    239 
    240 	check_usage(c);
    241 
    242 	if c.call_out {
    243 		fflush(c.call_out);
    244 	}
    245 
    246 	// Do optimization passes
    247 	d = first_decl(c);
    248 	loop {
    249 		if (!d) {
    250 			break;
    251 		}
    252 
    253 		if d.func_used && d.func_defined && d.func_ir {
    254 			ir_optimize(d.func_ir);
    255 		}
    256 
    257 		d = next_decl(c, d);
    258 	}
    259 
    260 	// Compile the ir to output
    261 	d = first_decl(c);
    262 	loop {
    263 		if (!d) {
    264 			break;
    265 		}
    266 
    267 		if d.func_used && d.func_defined && d.func_ir {
    268 			c.mach.output_ir(c, d);
    269 		}
    270 
    271 		d = next_decl(c, d);
    272 	}
    273 }
    274 
    275 func mark_func_used(c: *compiler, d: *decl, v: *decl) {
    276 	var edge: *decl;
    277 
    278 	if d {
    279 		// name uses member
    280 		edge = find(c, d.name, v.name, 1);
    281 		if c.call_out && !edge.used_forward {
    282 			fputs(c.call_out, d.name);
    283 			fputs(c.call_out, " -> ");
    284 			fputs(c.call_out, v.name);
    285 			fputs(c.call_out, "\n");
    286 		}
    287 		edge.used_forward = 1;
    288 		// member uses name
    289 		edge = find(c, v.name, d.name, 1);
    290 		edge.used_backward = 1;
    291 	}
    292 
    293 	if v.func_used {
    294 		return;
    295 	}
    296 
    297 	v.func_used = 1;
    298 	v.used_next = c.used_top;
    299 	c.used_top = v;
    300 }
    301 
    302 func mark_ir_expr(c: *compiler, d: *decl, op: *irop) {
    303 	var v: *decl;
    304 	var kind: int;
    305 
    306 	if op.kind == IOP_FUNC {
    307 		v = find(c, op.s, nil, 0);
    308 		if !v || !v.func_defined {
    309 			return;
    310 		}
    311 
    312 		mark_func_used(c, d, v);
    313 	}
    314 
    315 	if op.a {
    316 		mark_ir_expr(c, d, op.a);
    317 	}
    318 
    319 	if op.b {
    320 		mark_ir_expr(c, d, op.b);
    321 	}
    322 }
    323 
    324 func mark_ir_used(c: *compiler, d: *decl) {
    325 	var ic: *irfunc;
    326 	var ib: *irblock;
    327 	var i: int;
    328 	var j: int;
    329 
    330 	ic = d.func_ir;
    331 
    332 	i = 0;
    333 	loop {
    334 		if i == ic.blocks_len {
    335 			break;
    336 		}
    337 
    338 		ib = ic.blocks[i];
    339 
    340 		j = 0;
    341 		loop {
    342 			if j == ib.ops_len {
    343 				break;
    344 			}
    345 
    346 			mark_ir_expr(c, d, ib.ops[j]);
    347 
    348 			j = j + 1;
    349 		}
    350 
    351 		i = i + 1;
    352 	}
    353 }
    354 
    355 func check_usage(c: *compiler) {
    356 	var d: *decl;
    357 
    358 	loop {
    359 		d = c.used_top;
    360 		if !d {
    361 			break;
    362 		}
    363 		c.used_top = d.used_next;
    364 
    365 		if d.func_ir {
    366 			mark_ir_used(c, d);
    367 		}
    368 	}
    369 }
    370 
    371 func defextern(c: *compiler, n: *node): *decl {
    372 	var d: *decl;
    373 	var name: *byte;
    374 	var t: *type;
    375 
    376 	c.filename = n.filename;
    377 	c.lineno = n.lineno;
    378 	c.colno = n.colno;
    379 
    380 	name = n.a.s;
    381 
    382 	t = prototype(c, n.b);
    383 
    384 	d = find(c, name, nil, 1);
    385 
    386 	// TODO This is a quick hack but it's short.
    387 	// Mark functions in syscall.om as coming from stdlib
    388 	// This changes the behavior of ircout to link to libc
    389 	// for these functions.
    390 	if strcmp(n.filename, "syscall.om") == 0 {
    391 		d.func_stdlib = 1;
    392 	}
    393 
    394 	if d.func_defined {
    395 		unify(c, d.func_type, t);
    396 		return d;
    397 	}
    398 
    399 	d.func_defined = 1;
    400 	d.func_type = t;
    401 
    402 	return d;
    403 }
    404 
    405 func defun(c: *compiler, funcdef: *node) {
    406 	var d: *decl;
    407 	var name: *byte;
    408 	var v: *decl;
    409 	var t: *type;
    410 	var n: *node;
    411 
    412 	d = defextern(c, funcdef.a);
    413 
    414 	if d.func_defined == 2 {
    415 		die("duplicate function");
    416 	}
    417 	d.func_defined = 2;
    418 
    419 	d.func_def = funcdef;
    420 
    421 	n = funcdef.a.b.a;
    422 	loop {
    423 		if (!n) {
    424 			break;
    425 		}
    426 
    427 		c.filename = n.filename;
    428 		c.lineno = n.lineno;
    429 		c.colno = n.colno;
    430 		c.s.filename = n.filename;
    431 		c.s.lineno = n.lineno;
    432 
    433 		name = n.a.a.s;
    434 		t = prototype(c, n.a.b);
    435 
    436 		v = find(c, d.name, name, 1);
    437 		if (v.var_defined) {
    438 			cdie(c, "duplicate argument");
    439 		}
    440 
    441 		v.var_defined = 1;
    442 		v.var_type = t;
    443 
    444 		n = n.b;
    445 	}
    446 
    447 	hoist_locals(c, d, funcdef.b);
    448 }
    449 
    450 func defstruct(c: *compiler, n: *node) {
    451 	var name: *byte;
    452 	var d: *decl;
    453 
    454 	name = n.a.s;
    455 
    456 	c.filename = n.filename;
    457 	c.lineno = n.lineno;
    458 	c.colno = n.colno;
    459 
    460 	if (!strcmp(name, "int") || !strcmp(name, "byte") || !strcmp(name, "func")) {
    461 		cdie(c, "reserved word");
    462 	}
    463 
    464 	d = find(c, name, nil, 1);
    465 
    466 	if (d.struct_defined) {
    467 		cdie(c, "duplicate struct");
    468 	}
    469 
    470 	d.struct_defined = 1;
    471 	d.struct_def = n;
    472 	d.struct_type = prototype(c, n.a);
    473 }
    474 
    475 func defunion(c: *compiler, n: *node) {
    476 	var name: *byte;
    477 	var d: *decl;
    478 
    479 	name = n.a.s;
    480 
    481 	c.filename = n.filename;
    482 	c.lineno = n.lineno;
    483 	c.colno = n.colno;
    484 
    485 	if (!strcmp(name, "int") || !strcmp(name, "byte") || !strcmp(name, "func")) {
    486 		cdie(c, "reserved word");
    487 	}
    488 
    489 	d = find(c, name, nil, 1);
    490 
    491 	if (d.struct_defined) {
    492 		cdie(c, "duplicate struct");
    493 	}
    494 
    495 	d.struct_defined = 1;
    496 	d.struct_def = n;
    497 	d.struct_type = prototype(c, n.a);
    498 }
    499 
    500 func define_enum_tag(c: *compiler, name: *byte, value: int) {
    501 	var d: *decl;
    502 
    503 	d = find(c, name, nil, 1);
    504 
    505 	if d.enum_defined {
    506 		cdie(c, "duplicate enum");
    507 	}
    508 
    509 	d.enum_defined = 1;
    510 	d.enum_value = value;
    511 }
    512 
    513 func define_ir_func(c: *compiler, ic: *irfunc, t: *type) {
    514 	var d: *decl;
    515 
    516 	d = find(c, ic.name, nil, 1);
    517 
    518 	if d.func_defined == 2 {
    519 		cdie(c, "duplicate func");
    520 	}
    521 
    522 	if d.func_defined {
    523 		unify(c, d.func_type, t);
    524 	}
    525 
    526 	d.func_defined = 2;
    527 	d.func_type = t;
    528 	d.func_ir = ic;
    529 }
    530 
    531 func defenum(c: *compiler, n: *node) {
    532 	var i: int;
    533 	var name: *byte;
    534 
    535 	n = n.a;
    536 	i = 0;
    537 	loop {
    538 		if (!n) {
    539 			break;
    540 		}
    541 
    542 		c.filename = n.a.filename;
    543 		c.lineno = n.a.lineno;
    544 		c.colno = n.a.colno;
    545 
    546 		name = n.a.a.s;
    547 
    548 		if (n.a.b) {
    549 			i = n.a.b.n;
    550 		}
    551 
    552 		define_enum_tag(c, name, i);
    553 
    554 		i = i + 1;
    555 		n = n.b;
    556 	}
    557 }
    558 
    559 func layout_struct(c: *compiler, d: *decl) {
    560 	var m: *node;
    561 	var offset: int;
    562 	var name: *byte;
    563 	var md: *decl;
    564 	var t: *type;
    565 
    566 	if (d.struct_layout_done) {
    567 		if (d.struct_layout_done == 2) {
    568 			cdie(c, "circular struct definition");
    569 		}
    570 
    571 		return;
    572 	}
    573 
    574 	d.struct_layout_done = 2;
    575 
    576 	m = d.struct_def.b;
    577 
    578 	offset = 0;
    579 	loop {
    580 		if (!m) {
    581 			break;
    582 		}
    583 
    584 		c.filename = m.a.filename;
    585 		c.lineno = m.a.lineno;
    586 		c.colno = m.a.colno;
    587 
    588 		name = m.a.a.s;
    589 		t = prototype(c, m.a.b);
    590 
    591 		md = find(c, d.name, name, 1);
    592 
    593 		if (d.member_defined) {
    594 			cdie(c, "duplicate member");
    595 		}
    596 
    597 		md.member_defined = 1;
    598 		md.member_type = t;
    599 		md.member_offset = offset;
    600 
    601 		offset = offset + type_sizeof(c, t);
    602 
    603 		m = m.b;
    604 	}
    605 
    606 	d.struct_size = offset;
    607 	d.struct_layout_done = 1;
    608 }
    609 
    610 func layout_union(c: *compiler, d: *decl) {
    611 	var m: *node;
    612 	var size: int;
    613 	var member_size: int;
    614 	var name: *byte;
    615 	var md: *decl;
    616 	var t: *type;
    617 
    618 	if (d.struct_layout_done) {
    619 		if (d.struct_layout_done == 2) {
    620 			cdie(c, "circular struct definition");
    621 		}
    622 
    623 		return;
    624 	}
    625 
    626 	d.struct_layout_done = 2;
    627 
    628 	m = d.struct_def.b;
    629 
    630 	size = 0;
    631 	loop {
    632 		if (!m) {
    633 			break;
    634 		}
    635 
    636 		c.filename = m.a.filename;
    637 		c.lineno = m.a.lineno;
    638 		c.colno = m.a.colno;
    639 
    640 		name = m.a.a.s;
    641 		t = prototype(c, m.a.b);
    642 
    643 		md = find(c, d.name, name, 1);
    644 
    645 		if (d.member_defined) {
    646 			cdie(c, "duplicate member");
    647 		}
    648 
    649 		md.member_defined = 1;
    650 		md.member_type = t;
    651 		md.member_offset = 0;
    652 
    653 		member_size = type_sizeof(c, t);
    654 		if member_size > size {
    655 			size = member_size;
    656 		}
    657 
    658 		m = m.b;
    659 	}
    660 
    661 	d.struct_size = size;
    662 	d.struct_layout_done = 1;
    663 }
    664 
    665 func typecheck_expr(c: *compiler, d: *decl, n: *node, rhs: int) {
    666 	var v: *decl;
    667 	var kind: int;
    668 
    669 	c.filename = n.filename;
    670 	c.lineno = n.lineno;
    671 	c.colno = n.colno;
    672 
    673 	kind = n.kind;
    674 	if (kind == N_STR) {
    675 		if (!rhs) {
    676 			cdie(c, "str is not an lexpr");
    677 		}
    678 
    679 		n.t = mktype1(c, TY_PTR, mktype0(c, TY_BYTE));
    680 	} else if (kind == N_NIL) {
    681 		if (!rhs) {
    682 			cdie(c, "nil is not an lexpr");
    683 		}
    684 
    685 		n.t = mktype0(c, TY_NIL);
    686 	} else if (kind == N_NUM) {
    687 		if (!rhs) {
    688 			cdie(c, "num is not an lexpr");
    689 		}
    690 
    691 		n.t = mktype0(c, TY_INT);
    692 	} else if (kind == N_CHAR) {
    693 		if (!rhs) {
    694 			cdie(c, "char is not an lexpr");
    695 		}
    696 
    697 		n.t = mktype0(c, TY_INT);
    698 	} else if (kind == N_EXPRLIST) {
    699 		if (!rhs) {
    700 			cdie(c, "call is not an lexpr");
    701 		}
    702 
    703 		if (n.b) {
    704 			typecheck_expr(c, d, n.b, 1);
    705 		}
    706 
    707 		typecheck_expr(c, d, n.a, 1);
    708 
    709 		if (n.b) {
    710 			n.t = mktype2(c, TY_ARG, n.a.t, n.b.t);
    711 		} else {
    712 			n.t = mktype1(c, TY_ARG, n.a.t);
    713 		}
    714 	} else if (kind == N_CALL) {
    715 		if (!rhs) {
    716 			cdie(c, "call is not an lexpr");
    717 		}
    718 
    719 		if (n.b) {
    720 			typecheck_expr(c, d, n.b, 1);
    721 		}
    722 
    723 		if (n.a.kind == N_IDENT) {
    724 			v = find(c, n.a.s, nil, 0);
    725 			if (v && v.enum_defined) {
    726 				cdie(c, "type error");
    727 			}
    728 
    729 			v = find(c, d.name, n.a.s, 0);
    730 			if (v && v.var_defined) {
    731 				n.a.t = v.var_type;
    732 			} else if !strcmp(n.a.s, "_include") {
    733 				v = find(c, n.a.s, nil, 0);
    734 				if (!v || !v.func_defined) {
    735 					cdie(c, "no such function");
    736 				}
    737 				n.a.t = v.func_type;
    738 			} else {
    739 				v = find(c, n.a.s, nil, 0);
    740 				if (!v || !v.func_defined) {
    741 					cdie(c, "no such function");
    742 				}
    743 				n.a.t = v.func_type;
    744 			}
    745 		} else {
    746 			typecheck_expr(c, d, n.a, 1);
    747 		}
    748 
    749 		if (n.a.t.kind != TY_FUNC) {
    750 			cdie(c, "calling not a function");
    751 		}
    752 
    753 		if (n.b) {
    754 			unify(c, n.a.t.arg, n.b.t);
    755 		} else {
    756 			unify(c, n.a.t.arg, nil);
    757 		}
    758 
    759 		n.t = n.a.t.val;
    760 	} else if (kind == N_DOT) {
    761 		typecheck_expr(c, d, n.a, 0);
    762 
    763 		if (n.a.t.kind == TY_PTR) {
    764 			if (n.a.t.val.kind != TY_STRUCT && n.a.t.val.kind != TY_UNION) {
    765 				cdie(c, "dot not a struct");
    766 			}
    767 
    768 			v = find(c, n.a.t.val.st.name, n.b.s, 0);
    769 		} else {
    770 			if (n.a.t.kind != TY_STRUCT && n.a.t.kind != TY_UNION) {
    771 				cdie(c, "dot not a struct");
    772 			}
    773 
    774 			v = find(c, n.a.t.st.name, n.b.s, 0);
    775 		}
    776 
    777 		if (!v || !v.member_defined) {
    778 			cdie(c, "no such member");
    779 		}
    780 
    781 		n.t = v.member_type;
    782 	} else if (kind == N_IDENT) {
    783 		v = find(c, n.s, nil, 0);
    784 		if (v && v.enum_defined) {
    785 			n.t = mktype0(c, TY_INT);
    786 			return;
    787 		}
    788 
    789 		v = find(c, d.name, n.s, 0);
    790 		if (v && v.var_defined) {
    791 			n.t = v.var_type;
    792 			return;
    793 		}
    794 
    795 		v = find(c, n.s, nil, 0);
    796 		if (v && v.func_defined) {
    797 			n.t = v.func_type;
    798 			return;
    799 		}
    800 
    801 		fputs(nil, n.s);
    802 		cdie(c, "no such variable");
    803 	} else if (kind == N_ASSIGN) {
    804 		if (!rhs) {
    805 			cdie(c, "assign is not an lexpr");
    806 		}
    807 
    808 		typecheck_expr(c, d, n.b, 1);
    809 		typecheck_expr(c, d, n.a, 0);
    810 
    811 		unify(c, n.a.t, n.b.t);
    812 
    813 		n.t = n.a.t;
    814 	} else if (kind == N_SIZEOF) {
    815 		if (!rhs) {
    816 			cdie(c, "sizeof is not an lexpr");
    817 		}
    818 
    819 		typecheck_expr(c, d, n.a, 0);
    820 
    821 		n.t = mktype0(c, TY_INT);
    822 	} else if (kind == N_REF) {
    823 		if (!rhs) {
    824 			cdie(c, "ref is not an lexpr");
    825 		}
    826 
    827 		typecheck_expr(c, d, n.a, 0);
    828 
    829 		n.t = mktype1(c, TY_PTR, n.a.t);
    830 	} else if (kind == N_DEREF) {
    831 		typecheck_expr(c, d, n.a, 1);
    832 
    833 		if (n.a.t.kind != TY_PTR) {
    834 			cdie(c, "deref not a pointer");
    835 		}
    836 
    837 		n.t = n.a.t.val;
    838 	} else if (kind == N_INDEX) {
    839 		typecheck_expr(c, d, n.a, 1);
    840 		typecheck_expr(c, d, n.b, 1);
    841 
    842 		if (n.a.t.kind != TY_PTR) {
    843 			cdie(c, "not a pointer");
    844 		}
    845 
    846 		if (!type_isint(n.b.t)) {
    847 			cdie(c, "index: not an int");
    848 		}
    849 
    850 		n.t = n.a.t.val;
    851 	} else if (kind == N_LT) {
    852 		if (!rhs) {
    853 			cdie(c, "not lexpr");
    854 		}
    855 
    856 		typecheck_expr(c, d, n.b, 1);
    857 		typecheck_expr(c, d, n.a, 1);
    858 
    859 		unify(c, n.a.t, n.b.t);
    860 
    861 		if (!type_isprim(n.a.t)) {
    862 			cdie(c, "lt: not an int");
    863 		}
    864 
    865 		n.t = n.a.t;
    866 	} else if (kind == N_GT) {
    867 		if (!rhs) {
    868 			cdie(c, "not lexpr");
    869 		}
    870 
    871 		typecheck_expr(c, d, n.b, 1);
    872 		typecheck_expr(c, d, n.a, 1);
    873 
    874 		unify(c, n.a.t, n.b.t);
    875 
    876 		if (!type_isprim(n.a.t)) {
    877 			cdie(c, "gt: not an int");
    878 		}
    879 
    880 		n.t = n.a.t;
    881 	} else if (kind == N_LE) {
    882 		if (!rhs) {
    883 			cdie(c, "not lexpr");
    884 		}
    885 
    886 		typecheck_expr(c, d, n.b, 1);
    887 		typecheck_expr(c, d, n.a, 1);
    888 
    889 		unify(c, n.a.t, n.b.t);
    890 
    891 		if (!type_isprim(n.a.t)) {
    892 			cdie(c, "le: not an int");
    893 		}
    894 
    895 		n.t = n.a.t;
    896 	} else if (kind == N_GE) {
    897 		if (!rhs) {
    898 			cdie(c, "not lexpr");
    899 		}
    900 
    901 		typecheck_expr(c, d, n.b, 1);
    902 		typecheck_expr(c, d, n.a, 1);
    903 
    904 		unify(c, n.a.t, n.b.t);
    905 
    906 		if (!type_isprim(n.a.t)) {
    907 			cdie(c, "ge: not an int");
    908 		}
    909 
    910 		n.t = n.a.t;
    911 	} else if (kind == N_EQ) {
    912 		if (!rhs) {
    913 			cdie(c, "not lexpr");
    914 		}
    915 
    916 		typecheck_expr(c, d, n.b, 1);
    917 		typecheck_expr(c, d, n.a, 1);
    918 
    919 		unify(c, n.a.t, n.b.t);
    920 
    921 		if (!type_isprim(n.a.t)) {
    922 			cdie(c, "eq: not an int");
    923 		}
    924 
    925 		n.t = n.a.t;
    926 	} else if (kind == N_NE) {
    927 		if (!rhs) {
    928 			cdie(c, "not lexpr");
    929 		}
    930 
    931 		typecheck_expr(c, d, n.b, 1);
    932 		typecheck_expr(c, d, n.a, 1);
    933 
    934 		unify(c, n.a.t, n.b.t);
    935 
    936 		if (!type_isprim(n.a.t)) {
    937 			cdie(c, "ne: not an int");
    938 		}
    939 
    940 		n.t = n.a.t;
    941 	} else if (kind == N_BNOT) {
    942 		if (!rhs) {
    943 			cdie(c, "not lexpr");
    944 		}
    945 
    946 		typecheck_expr(c, d, n.a, 1);
    947 
    948 		if (!type_isprim(n.a.t)) {
    949 			cdie(c, "not an prim");
    950 		}
    951 
    952 		n.t = mktype0(c, TY_INT);
    953 	} else if (kind == N_BOR) {
    954 		if (!rhs) {
    955 			cdie(c, "not lexpr");
    956 		}
    957 
    958 		typecheck_expr(c, d, n.a, 1);
    959 		typecheck_expr(c, d, n.b, 1);
    960 
    961 		if (!type_isprim(n.a.t)) {
    962 			cdie(c, "not an prim");
    963 		}
    964 
    965 		if (!type_isprim(n.b.t)) {
    966 			cdie(c, "not an prim");
    967 		}
    968 
    969 		n.t = mktype0(c, TY_INT);
    970 	} else if (kind == N_BAND) {
    971 		if (!rhs) {
    972 			cdie(c, "not lexpr");
    973 		}
    974 
    975 		typecheck_expr(c, d, n.a, 1);
    976 		typecheck_expr(c, d, n.b, 1);
    977 
    978 		if (!type_isprim(n.a.t)) {
    979 			cdie(c, "not an prim");
    980 		}
    981 
    982 		if (!type_isprim(n.b.t)) {
    983 			cdie(c, "not an prim");
    984 		}
    985 
    986 		n.t = mktype0(c, TY_INT);
    987 	} else if (kind == N_POS) {
    988 		if (!rhs) {
    989 			cdie(c, "not lexpr");
    990 		}
    991 
    992 		typecheck_expr(c, d, n.a, 1);
    993 
    994 		if (!type_isint(n.a.t)) {
    995 			cdie(c, "pos: not an int");
    996 		}
    997 
    998 		n.t = n.a.t;
    999 	} else if (kind == N_NEG) {
   1000 		if (!rhs) {
   1001 			cdie(c, "not lexpr");
   1002 		}
   1003 
   1004 		typecheck_expr(c, d, n.a, 1);
   1005 
   1006 		if (!type_isint(n.a.t)) {
   1007 			cdie(c, "neg: not an int");
   1008 		}
   1009 
   1010 		n.t = n.a.t;
   1011 	} else if (kind == N_NOT) {
   1012 		if (!rhs) {
   1013 			cdie(c, "not lexpr");
   1014 		}
   1015 
   1016 		typecheck_expr(c, d, n.a, 1);
   1017 
   1018 		if (!type_isint(n.a.t)) {
   1019 			cdie(c, "not: not an int");
   1020 		}
   1021 
   1022 		n.t = n.a.t;
   1023 	} else if (kind == N_ADD) {
   1024 		if (!rhs) {
   1025 			cdie(c, "not lexpr");
   1026 		}
   1027 
   1028 		typecheck_expr(c, d, n.b, 1);
   1029 		typecheck_expr(c, d, n.a, 1);
   1030 
   1031 		unify(c, n.a.t, n.b.t);
   1032 
   1033 		if (!type_isint(n.a.t)) {
   1034 			cdie(c, "add: not an int");
   1035 		}
   1036 
   1037 		n.t = n.a.t;
   1038 	} else if (kind == N_SUB) {
   1039 		if (!rhs) {
   1040 			cdie(c, "not lexpr");
   1041 		}
   1042 
   1043 		typecheck_expr(c, d, n.b, 1);
   1044 		typecheck_expr(c, d, n.a, 1);
   1045 
   1046 		unify(c, n.a.t, n.b.t);
   1047 
   1048 		if (!type_isint(n.a.t)) {
   1049 			cdie(c, "sub: not an int");
   1050 		}
   1051 
   1052 		n.t = n.a.t;
   1053 	} else if (kind == N_MUL) {
   1054 		if (!rhs) {
   1055 			cdie(c, "not lexpr");
   1056 		}
   1057 
   1058 		typecheck_expr(c, d, n.b, 1);
   1059 		typecheck_expr(c, d, n.a, 1);
   1060 
   1061 		unify(c, n.a.t, n.b.t);
   1062 
   1063 		if (!type_isint(n.a.t)) {
   1064 			cdie(c, "mul: not an int");
   1065 		}
   1066 
   1067 		n.t = n.a.t;
   1068 	} else if (kind == N_DIV) {
   1069 		if (!rhs) {
   1070 			cdie(c, "not lexpr");
   1071 		}
   1072 
   1073 		typecheck_expr(c, d, n.b, 1);
   1074 		typecheck_expr(c, d, n.a, 1);
   1075 
   1076 		unify(c, n.a.t, n.b.t);
   1077 
   1078 		if (!type_isint(n.a.t)) {
   1079 			cdie(c, "div: not an int");
   1080 		}
   1081 
   1082 		n.t = n.a.t;
   1083 	} else if (kind == N_MOD) {
   1084 		if (!rhs) {
   1085 			cdie(c, "not lexpr");
   1086 		}
   1087 
   1088 		typecheck_expr(c, d, n.b, 1);
   1089 		typecheck_expr(c, d, n.a, 1);
   1090 
   1091 		unify(c, n.a.t, n.b.t);
   1092 
   1093 		if (!type_isint(n.a.t)) {
   1094 			cdie(c, "mod: not an int");
   1095 		}
   1096 
   1097 		n.t = n.a.t;
   1098 	} else if (kind == N_LSH) {
   1099 		if (!rhs) {
   1100 			cdie(c, "not lexpr");
   1101 		}
   1102 
   1103 		typecheck_expr(c, d, n.b, 1);
   1104 		typecheck_expr(c, d, n.a, 1);
   1105 
   1106 		unify(c, n.a.t, n.b.t);
   1107 
   1108 		if (!type_isint(n.a.t)) {
   1109 			cdie(c, "lsh: not an int");
   1110 		}
   1111 
   1112 		n.t = n.a.t;
   1113 	} else if (kind == N_RSH) {
   1114 		if (!rhs) {
   1115 			cdie(c, "not lexpr");
   1116 		}
   1117 
   1118 		typecheck_expr(c, d, n.b, 1);
   1119 		typecheck_expr(c, d, n.a, 1);
   1120 
   1121 		unify(c, n.a.t, n.b.t);
   1122 
   1123 		if (!type_isint(n.a.t)) {
   1124 			cdie(c, "rsh: not an int");
   1125 		}
   1126 
   1127 		n.t = n.a.t;
   1128 	} else if (kind == N_AND) {
   1129 		if (!rhs) {
   1130 			cdie(c, "not lexpr");
   1131 		}
   1132 
   1133 		typecheck_expr(c, d, n.b, 1);
   1134 		typecheck_expr(c, d, n.a, 1);
   1135 
   1136 		unify(c, n.a.t, n.b.t);
   1137 
   1138 		if (!type_isint(n.a.t)) {
   1139 			cdie(c, "and: not an int");
   1140 		}
   1141 
   1142 		n.t = n.a.t;
   1143 	} else if (kind == N_OR) {
   1144 		if (!rhs) {
   1145 			cdie(c, "not lexpr");
   1146 		}
   1147 
   1148 		typecheck_expr(c, d, n.b, 1);
   1149 		typecheck_expr(c, d, n.a, 1);
   1150 
   1151 		unify(c, n.a.t, n.b.t);
   1152 
   1153 		if (!type_isint(n.a.t)) {
   1154 			cdie(c, "or: not an int");
   1155 		}
   1156 
   1157 		n.t = n.a.t;
   1158 	} else if (kind == N_XOR) {
   1159 		if (!rhs) {
   1160 			cdie(c, "not lexpr");
   1161 		}
   1162 
   1163 		typecheck_expr(c, d, n.b, 1);
   1164 		typecheck_expr(c, d, n.a, 1);
   1165 
   1166 		unify(c, n.a.t, n.b.t);
   1167 
   1168 		if (!type_isint(n.a.t)) {
   1169 			cdie(c, "xor: not an int");
   1170 		}
   1171 
   1172 		n.t = n.a.t;
   1173 	} else if (kind == N_CAST) {
   1174 		if (!rhs) {
   1175 			cdie(c, "not lexpr");
   1176 		}
   1177 
   1178 		typecheck_expr(c, d, n.a, 1);
   1179 		if (!type_isprim(n.a.t)) {
   1180 			cdie(c, "not a primitive");
   1181 		}
   1182 
   1183 		n.t = prototype(c, n.b);
   1184 	} else {
   1185 		cdie(c, "not an expression");
   1186 	}
   1187 }
   1188 
   1189 func typecheck_stmt(c: *compiler, d: *decl, n: *node) {
   1190 	var v: *decl;
   1191 	var kind: int;
   1192 
   1193 	if (!n) {
   1194 		return;
   1195 	}
   1196 
   1197 	c.filename = n.filename;
   1198 	c.lineno = n.lineno;
   1199 	c.colno = n.colno;
   1200 
   1201 	kind = n.kind;
   1202 	if (kind == N_CONDLIST) {
   1203 		loop {
   1204 			if (!n) {
   1205 				break;
   1206 			}
   1207 
   1208 			if (n.a.a) {
   1209 				typecheck_expr(c, d, n.a.a, 1);
   1210 			}
   1211 
   1212 			typecheck_stmt(c, d, n.a.b);
   1213 
   1214 			n = n.b;
   1215 		}
   1216 	} else if (kind == N_STMTLIST) {
   1217 		loop {
   1218 			if (!n) {
   1219 				break;
   1220 			}
   1221 			typecheck_stmt(c, d, n.a);
   1222 			n = n.b;
   1223 		}
   1224 	} else if (kind == N_LOOP) {
   1225 		typecheck_stmt(c, d, n.a);
   1226 	} else if (kind == N_BREAK) {
   1227 	} else if (kind == N_CONTINUE) {
   1228 	} else if (kind == N_RETURN) {
   1229 		if (n.a) {
   1230 			if (d.func_type.val.kind == TY_VOID) {
   1231 				cdie(c, "returning a value in a void function");
   1232 			}
   1233 			call_check(c, n.a);
   1234 			typecheck_expr(c, d, n.a, 1);
   1235 			unify(c, n.a.t, d.func_type.val);
   1236 		} else {
   1237 			if (d.func_type.val.kind != TY_VOID) {
   1238 				cdie(c, "returning void in a non void function");
   1239 			}
   1240 		}
   1241 	} else if (kind == N_LABEL) {
   1242 		v = find(c, d.name, n.a.s, 0);
   1243 	} else if (kind == N_GOTO) {
   1244 		v = find(c, d.name, n.a.s, 0);
   1245 		if (!v || !v.goto_defined) {
   1246 			cdie(c, "label not defined");
   1247 		}
   1248 	} else if (kind != N_VARDECL) {
   1249 		call_check(c, n);
   1250 		typecheck_expr(c, d, n, 1);
   1251 	}
   1252 }
   1253 
   1254 func hoist_locals(c: *compiler, d: *decl, n: *node) {
   1255 	var kind: int;
   1256 	var name: *byte;
   1257 	var t: *type;
   1258 	var v: *decl;
   1259 
   1260 	if (!n) {
   1261 		return;
   1262 	}
   1263 
   1264 	kind = n.kind;
   1265 	if (kind == N_CONDLIST) {
   1266 		loop {
   1267 			if (!n) {
   1268 				return;
   1269 			}
   1270 
   1271 			hoist_locals(c, d, n.a.b);
   1272 
   1273 			n = n.b;
   1274 		}
   1275 	} else if (kind == N_STMTLIST) {
   1276 		loop {
   1277 			if (!n) {
   1278 				return;
   1279 			}
   1280 
   1281 			hoist_locals(c, d, n.a);
   1282 
   1283 			n = n.b;
   1284 		}
   1285 	} else if (kind == N_LOOP) {
   1286 		hoist_locals(c, d, n.a);
   1287 		return;
   1288 	} else if (kind == N_LABEL) {
   1289 		name = n.a.s;
   1290 		v = find(c, d.name, name, 1);
   1291 
   1292 		if (v.goto_defined) {
   1293 			cdie(c, "duplicate goto");
   1294 		}
   1295 		v.goto_defined = 1;
   1296 
   1297 		return;
   1298 	} else if (kind != N_VARDECL) {
   1299 		return;
   1300 	}
   1301 
   1302 	name = n.a.s;
   1303 	t = prototype(c, n.b);
   1304 
   1305 	n.t = t;
   1306 
   1307 	v = find(c, d.name, name, 1);
   1308 
   1309 	if (v.var_defined) {
   1310 		cdie(c, "duplicate variable");
   1311 	}
   1312 
   1313 	v.var_type = t;
   1314 	v.var_defined = 1;
   1315 }
   1316 
   1317 func gather_include(c: *compiler, filename: *byte, slen: *int): *byte {
   1318 	var fd: int;
   1319 	var blob: *byte;
   1320 
   1321 	fd = open(filename, O_RDONLY, 0);
   1322 	if fd < 0 {
   1323 		cdie(c, "gather_include: failed to open include");
   1324 	}
   1325 
   1326 	blob = readall(fd, slen, c.a);
   1327 
   1328 	close(fd);
   1329 
   1330 	return blob;
   1331 }
   1332 
   1333 func call_check(c: *compiler, n: *node): int {
   1334 	var result: int;
   1335 	var ret: int;
   1336 
   1337 	result = 0;
   1338 
   1339 	if !n {
   1340 		return result;
   1341 	}
   1342 
   1343 	if n.kind == N_CALL {
   1344 		result = call_check(c, n.a);
   1345 		n = n.b;
   1346 		loop {
   1347 			if !n {
   1348 				break;
   1349 			}
   1350 			ret = call_check(c, n.a);
   1351 			if result && ret {
   1352 				cdie(c, "multiple calls in call");
   1353 			}
   1354 			result = result | ret;
   1355 			n = n.b;
   1356 		}
   1357 		result = 1;
   1358 	} else if n.kind == N_BOR || n.kind == N_BAND {
   1359 		// Side effects okay in both positions
   1360 		result = call_check(c, n.a);
   1361 		result = result | call_check(c, n.b);
   1362 	} else if n.kind == N_ASSIGN || n.kind == N_INDEX || n.kind == N_LT
   1363 		|| n.kind == N_LE || n.kind == N_GT || n.kind == N_GE
   1364 		|| n.kind == N_EQ || n.kind == N_NE || n.kind == N_BNOT
   1365 		|| n.kind == N_ADD || n.kind == N_SUB || n.kind == N_MUL
   1366 		|| n.kind == N_DIV || n.kind == N_MOD || n.kind == N_LSH
   1367 		|| n.kind == N_RSH || n.kind == N_AND || n.kind == N_OR
   1368 		|| n.kind == N_XOR {
   1369 		// Possible side effects in both positions
   1370 		result = call_check(c, n.a);
   1371 		ret = call_check(c, n.b);
   1372 		if result && ret {
   1373 			cdie(c, "multiple calls in expression");
   1374 		}
   1375 		result = result | ret;
   1376 	} else if n.kind == N_REF || n.kind == N_DEREF || n.kind == N_POS
   1377 		|| n.kind == N_NEG || n.kind == N_NOT || n.kind == N_CAST
   1378 		|| n.kind == N_DOT {
   1379 		// Possible side effect in the first position
   1380 		result = call_check(c, n.a);
   1381 	} else if n.kind == N_STR || n.kind == N_NUM || n.kind == N_CHAR
   1382 		|| n.kind == N_IDENT || n.kind == N_SIZEOF || n.kind == N_NIL {
   1383 		// No side effects
   1384 	} else {
   1385 		show_node(nil, n);
   1386 		fputd(nil, n.kind);
   1387 		die("invalid expr");
   1388 	}
   1389 
   1390 	return result;
   1391 }
   1392 
   1393 func open_call_out(c: *compiler, filename: *byte) {
   1394 	var fd: int;
   1395 
   1396 	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) + (6 << 3) + 6);
   1397 	if (fd < 0) {
   1398 		die("open_call_out: failed to open output");
   1399 	}
   1400 
   1401 	c.call_out = fopen(fd, c.a);
   1402 	c.call_out.noflush = 1;
   1403 }
   1404 
   1405 func open_lines_out(c: *compiler, filename: *byte) {
   1406 	var fd: int;
   1407 
   1408 	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) + (6 << 3) + 6);
   1409 	if (fd < 0) {
   1410 		die("open_lines_out: failed to open output");
   1411 	}
   1412 
   1413 	c.s.lines_out = fopen(fd, c.a);
   1414 	c.s.lines_out.noflush = 1;
   1415 }
   1416 
   1417 struct name_node {
   1418 	next: *name_node;
   1419 	name: *byte;
   1420 }
   1421 
   1422 func main(argc: int, argv: **byte, envp: **byte) {
   1423 	var a: alloc;
   1424 	var c: *compiler;
   1425 	var p: *node;
   1426 	var i: int;
   1427 	var show: int;
   1428 	var out_filename: *byte;
   1429 	var cout_filename: *byte;
   1430 	var err: *file;
   1431 	var input: *name_node;
   1432 	var tmp: *name_node;
   1433 	var link: **name_node;
   1434 	var sem: *lex_sem;
   1435 	var _aarch64: machine;
   1436 	var _x86_64: machine;
   1437 	var _riscv64: machine;
   1438 
   1439 	link = &input;
   1440 
   1441 	setup_alloc(&a);
   1442 
   1443 	err = fopen(2, &a);
   1444 
   1445 	c = comp_setup(&a, err);
   1446 
   1447 	_aarch64.id = 0xb7;
   1448 	_aarch64.emit_builtin = aarch64_builtin;
   1449 	_aarch64.output_ir = aarch64_output_ir;
   1450 
   1451 	_x86_64.id = 0x3e;
   1452 	_x86_64.emit_builtin = x86_64_builtin;
   1453 	_x86_64.output_ir = x86_64_output_ir;
   1454 
   1455 	_riscv64.id = 0xf3;
   1456 	_riscv64.emit_builtin = riscv64_builtin;
   1457 	_riscv64.output_ir = riscv64_output_ir;
   1458 
   1459 	if get_machine() == 0xb7 {
   1460 		c.mach = &_aarch64;
   1461 	} else if get_machine() == 0x3e {
   1462 		c.mach = &_x86_64;
   1463 	} else if get_machine() == 0xf3 {
   1464 		c.mach = &_riscv64;
   1465 	}
   1466 
   1467 	i = 1;
   1468 	loop {
   1469 		if (i >= argc) {
   1470 			break;
   1471 		}
   1472 
   1473 		if (!strcmp(argv[i], "-o")) {
   1474 			i = i + 1;
   1475 			if (i >= argc) {
   1476 				die("invalid -o at end of argument list");
   1477 			}
   1478 			out_filename = argv[i];
   1479 			i = i + 1;
   1480 			continue;
   1481 		}
   1482 
   1483 		if (!strcmp(argv[i], "-fdump")) {
   1484 			i = i + 1;
   1485 			show = 1;
   1486 			continue;
   1487 		}
   1488 
   1489 		if (!strcmp(argv[i], "-m")) {
   1490 			i = i + 1;
   1491 			if (i >= argc) {
   1492 				die("invalid -m at end of argument list");
   1493 			}
   1494 			if (!strcmp(argv[i], "aarch64")) {
   1495 				c.mach = &_aarch64;
   1496 				i = i + 1;
   1497 			} else if (!strcmp(argv[i], "x86_64")) {
   1498 				c.mach = &_x86_64;
   1499 				i = i + 1;
   1500 			} else if (!strcmp(argv[i], "riscv64")) {
   1501 				c.mach = &_riscv64;
   1502 				i = i + 1;
   1503 			} else {
   1504 				die("unknown machine");
   1505 			}
   1506 			continue;
   1507 		}
   1508 
   1509 		if (!strcmp(argv[i], "-C")) {
   1510 			i = i + 1;
   1511 			if (i >= argc) {
   1512 				die("invalid -o at end of argument list");
   1513 			}
   1514 			cout_filename = argv[i];
   1515 			i = i + 1;
   1516 			continue;
   1517 		}
   1518 
   1519 		if (!strcmp(argv[i], "-G")) {
   1520 			i = i + 1;
   1521 			if (i >= argc) {
   1522 				die("invalid -G at end of argument list");
   1523 			}
   1524 			open_call_out(c, argv[i]);
   1525 			i = i + 1;
   1526 			continue;
   1527 		}
   1528 
   1529 		if (!strcmp(argv[i], "-n")) {
   1530 			i = i + 1;
   1531 			if (i >= argc) {
   1532 				die("invalid -n at end of argument list");
   1533 			}
   1534 			open_lines_out(c, argv[i]);
   1535 			i = i + 1;
   1536 			continue;
   1537 		}
   1538 
   1539 		if (argv[i][0] == '-' as byte) {
   1540 			die("invalid argument");
   1541 		}
   1542 
   1543 		tmp = alloc(&a, sizeof(*tmp)) as *name_node;
   1544 		tmp.next = nil;
   1545 		tmp.name = argv[i];
   1546 		*link = tmp;
   1547 		link = &tmp.next;
   1548 
   1549 		i = i + 1;
   1550 	}
   1551 
   1552 	tmp = input;
   1553 	loop {
   1554 		if !tmp {
   1555 			break;
   1556 		}
   1557 		sem = dolalr(c, tmp.name, err);
   1558 		p = concat_program(p, sem.n);
   1559 		tmp = tmp.next;
   1560 	}
   1561 
   1562 	if show {
   1563 		show_node(err, p);
   1564 		fflush(err);
   1565 		return;
   1566 	}
   1567 
   1568 	if !c.mach {
   1569 		die("machine not set");
   1570 	}
   1571 
   1572 	compile(c, p);
   1573 
   1574 	if cout_filename {
   1575 		open_coutput(c, cout_filename);
   1576 		ircout(c);
   1577 	}
   1578 
   1579 	if out_filename {
   1580 		c.mach.emit_builtin(c);
   1581 
   1582 		open_output(c.s, out_filename);
   1583 		writeout(c.s, c.mach.id, c.start, c.kstart);
   1584 	}
   1585 }