os

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

ircout.om (15183B)


      1 func ircout(c: *compiler) {
      2 	var d: *decl;
      3 
      4 	fputs(c.cout, "typedef unsigned char b;\n");
      5 	fputs(c.cout, "typedef unsigned long u;\n");
      6 	fputs(c.cout, "typedef long s;\n");
      7 
      8 	// Forward declare used functions
      9 	d = first_decl(c);
     10 	loop {
     11 		if !d {
     12 			break;
     13 		}
     14 
     15 		if d.func_used && d.func_defined {
     16 			ircforward(c, d);
     17 		}
     18 
     19 		d = next_decl(c, d);
     20 	}
     21 
     22 	// Emit stdlib declarations
     23 	ircdeclstdlib(c);
     24 
     25 	// Define used functions
     26 	d = first_decl(c);
     27 	loop {
     28 		if !d {
     29 			break;
     30 		}
     31 
     32 		if d.func_used && d.func_defined {
     33 			ircdefine(c, d);
     34 		}
     35 
     36 		d = next_decl(c, d);
     37 	}
     38 
     39 	fflush(c.cout);
     40 }
     41 
     42 func ircdeclstdlib(c: *compiler) {
     43 	fputs(c.cout, "extern u syscall();\n");
     44 	fputs(c.cout, "extern void exit();\n");
     45 	fputs(c.cout, "extern s read();\n");
     46 	fputs(c.cout, "extern s write();\n");
     47 	fputs(c.cout, "extern u mmap();\n");
     48 	fputs(c.cout, "extern int close();\n");
     49 	fputs(c.cout, "extern int unlink();\n");
     50 	fputs(c.cout, "extern int open();\n");
     51 	fputs(c.cout, "extern char **environ;\n");
     52 	fputs(c.cout, "int main(int argc, char**argv) {\n");
     53 	fputs(c.cout, "\treturn zmain((u)argc, (u)argv, (u)environ);\n");
     54 	fputs(c.cout, "}\n");
     55 }
     56 
     57 func ircstdlib(c: *compiler, d: *decl) {
     58 	if strcmp(d.name, "syscall") == 0 {
     59 		fputs(c.cout, "/* no glue for syscall using stdlib */\n");
     60 	} else if strcmp(d.name, "_start") == 0 {
     61 		fputs(c.cout, "/* no glue for _start using stdlib */\n");
     62 	} else if strcmp(d.name, "exit") == 0 {
     63 		fputs(c.cout, "u zexit(u vn) {\n");
     64 		fputs(c.cout, "\texit((int)vn);\n");
     65 		fputs(c.cout, "}\n");
     66 	} else if strcmp(d.name, "read") == 0 {
     67 		fputs(c.cout, "u zread(u vfd, u vbuf, u vn) {\n");
     68 		fputs(c.cout, "\treturn (u)read((int)vfd, (void*)vbuf, (unsigned long)vn);\n");
     69 		fputs(c.cout, "}\n");
     70 	} else if strcmp(d.name, "write") == 0 {
     71 		fputs(c.cout, "u zwrite(u vfd, u vbuf, u vn) {\n");
     72 		fputs(c.cout, "\treturn (u)write((int)vfd, (void*)vbuf, (unsigned long)vn);\n");
     73 		fputs(c.cout, "}\n");
     74 	} else if strcmp(d.name, "mmap") == 0 {
     75 		fputs(c.cout, "u zmmap(u vaddr, u vlen, u vprot, u vflags, u vfd, u voff) {\n");
     76 		fputs(c.cout, "\treturn (u)mmap((void*)vaddr, (unsigned long)vlen, (int)vprot, (int)vflags, (int)vfd, (long)voff);\n");
     77 		fputs(c.cout, "}\n");
     78 	} else if strcmp(d.name, "close") == 0 {
     79 		fputs(c.cout, "u zclose(u vfd) {\n");
     80 		fputs(c.cout, "\treturn (u)close((int)vfd);\n");
     81 		fputs(c.cout, "}\n");
     82 	} else if strcmp(d.name, "unlink") == 0 {
     83 		fputs(c.cout, "u zunlink(u vname) {\n");
     84 		fputs(c.cout, "\treturn (u)unlink((char *)vname);\n");
     85 		fputs(c.cout, "}\n");
     86 	} else if strcmp(d.name, "open") == 0 {
     87 		fputs(c.cout, "u zopen(u vname, u vflags, u vmode) {\n");
     88 		fputs(c.cout, "\treturn (u)open((char *)vname, (int)vflags, (int)vmode);\n");
     89 		fputs(c.cout, "}\n");
     90 	} else if strcmp(d.name, "get_machine") == 0 {
     91 		fputs(c.cout, "u zget_machine() {\n");
     92 		fputs(c.cout, "\treturn 0;\n");
     93 		fputs(c.cout, "}\n");
     94 	} else {
     95 		die("unimplemented stdlib glue");
     96 	}
     97 }
     98 
     99 func ircdecl(c: *compiler, ic: *irfunc) {
    100 	var i: int;
    101 	var iv: *irvar;
    102 
    103 	fputs(c.cout, "u z");
    104 	fputs(c.cout, ic.name);
    105 	fputs(c.cout, "(");
    106 
    107 	i = 0;
    108 	loop {
    109 		if i == ic.arg_count {
    110 			break;
    111 		}
    112 
    113 		iv = ic.vars[i];
    114 
    115 		fputs(c.cout, "u v");
    116 		fputs(c.cout, iv.name);
    117 
    118 		i = i + 1;
    119 
    120 		if i != ic.arg_count {
    121 			fputs(c.cout, ", ");
    122 		}
    123 	}
    124 
    125 	fputs(c.cout, ")");
    126 }
    127 
    128 func ircforward(c: *compiler, d: *decl) {
    129 	var ic: *irfunc;
    130 
    131 	ic = d.func_ir;
    132 	if !ic {
    133 		return;
    134 	}
    135 
    136 	fputs(c.cout, "u z");
    137 	fputs(c.cout, ic.name);
    138 	fputs(c.cout, "();\n");
    139 }
    140 
    141 func ircdefine(c: *compiler, d: *decl) {
    142 	var i: int;
    143 	var ic: *irfunc;
    144 	var iv: *irvar;
    145 	var top: *irblock;
    146 	var size: int;
    147 	var id: int;
    148 
    149 	if d.func_stdlib {
    150 		ircstdlib(c, d);
    151 		return;
    152 	}
    153 
    154 	ic = d.func_ir;
    155 	if !ic {
    156 		return;
    157 	}
    158 
    159 	i = 0;
    160 	loop {
    161 		if i == ic.vars_len {
    162 			break;
    163 		}
    164 
    165 		iv = ic.vars[i];
    166 
    167 		i = i + 1;
    168 	}
    169 
    170 	top = ic.blocks[0];
    171 	ircuse(c, ic, top);
    172 
    173 	ircdecl(c, ic);
    174 	fputs(c.cout, " {\n");
    175 
    176 	i = ic.arg_count;
    177 	loop {
    178 		if i == ic.vars_len {
    179 			break;
    180 		}
    181 
    182 		iv = ic.vars[i];
    183 
    184 		if iv.dead {
    185 			i = i + 1;
    186 			continue;
    187 		}
    188 
    189 		fputs(c.cout, "\t");
    190 		fputs(c.cout, "u ");
    191 
    192 		if iv.name {
    193 			fputs(c.cout, "v");
    194 			fputs(c.cout, iv.name);
    195 		} else {
    196 			fputs(c.cout, "v");
    197 			fputd(c.cout, i);
    198 		}
    199 
    200 		if iv.t && iv.t.kind != TY_VOID {
    201 			size = type_sizeof(c, iv.t);
    202 		} else {
    203 			size = sizeof(i);
    204 		}
    205 
    206 		if size == sizeof(i) {
    207 			fputs(c.cout, " = 0");
    208 		} else {
    209 			fputs(c.cout, "[");
    210 			fputd(c.cout, (size + sizeof(i) + 1) / sizeof(i));
    211 			fputs(c.cout, "] = {0}");
    212 		}
    213 
    214 		fputs(c.cout, ";\n");
    215 
    216 		i = i + 1;
    217 	}
    218 
    219 	ircbody(c, ic, top);
    220 	irreset(top);
    221 
    222 	fputs(c.cout, "}\n");
    223 }
    224 
    225 func ircuse(c: *compiler, ic: *irfunc, ib: *irblock) {
    226 	var i: int;
    227 
    228 	if !ib {
    229 		return;
    230 	}
    231 
    232 	if ib.mark {
    233 		ib.mark = 6;
    234 		return;
    235 	}
    236 
    237 	ib.mark = 2;
    238 
    239 	if ib.out {
    240 		ircuse(c, ic, ib.out);
    241 	}
    242 
    243 	if ib.alt && ib.ops[ib.ops_len - 1].kind == IOP_BRANCH {
    244 		ircuse(c, ic, ib.alt);
    245 		ib.alt.mark = 6;
    246 	}
    247 }
    248 
    249 func ircbody(c: *compiler, ic: *irfunc, ib: *irblock) {
    250 	if !ib || ib.mark & 1 {
    251 		return;
    252 	}
    253 
    254 	ib.mark = ib.mark | 1;
    255 
    256 	ircblock(c, ic, ib);
    257 
    258 	if ib.out {
    259 		ircbody(c, ic, ib.out);
    260 	}
    261 
    262 	if ib.alt && ib.ops[ib.ops_len - 1].kind == IOP_BRANCH {
    263 		ircbody(c, ic, ib.alt);
    264 	}
    265 }
    266 
    267 func ircblock(c: *compiler, ic: *irfunc, ib: *irblock) {
    268 	var i: int;
    269 	var op: *irop;
    270 	var kind: int;
    271 	var didlabel: int;
    272 
    273 	didlabel = (ib.mark & 4) == 0;
    274 
    275 	loop {
    276 		if i + 1 == ib.ops_len {
    277 			break;
    278 		}
    279 
    280 		op = ib.ops[i];
    281 
    282 		kind = op.kind;
    283 		if kind == IOP_ARG || kind == IOP_RETVAL {
    284 			i = i + 1;
    285 			continue;
    286 		}
    287 
    288 		ircline(c, op);
    289 
    290 		if !didlabel {
    291 			fputs(c.cout, "b");
    292 			fputd(c.cout, ib.n);
    293 			fputs(c.cout, ":");
    294 			didlabel = 1;
    295 		}
    296 
    297 		fputs(c.cout, "\t");
    298 		ircop(c, ic, ib, op, 20);
    299 		fputs(c.cout, ";\n");
    300 
    301 		i = i + 1;
    302 	}
    303 
    304 	op = ib.ops[i];
    305 
    306 	kind = op.kind;
    307 	if kind == IOP_CALL {
    308 		ircline(c, op);
    309 
    310 		if !didlabel {
    311 			fputs(c.cout, "b");
    312 			fputd(c.cout, ib.n);
    313 			fputs(c.cout, ":");
    314 			didlabel = 1;
    315 		}
    316 
    317 		irccall(c, ic, ib, op);
    318 	} else if kind == IOP_JUMP {
    319 		ircline(c, op);
    320 
    321 		if !didlabel {
    322 			fputs(c.cout, "b");
    323 			fputd(c.cout, ib.n);
    324 			fputs(c.cout, ":");
    325 			didlabel = 1;
    326 		}
    327 
    328 		if ib.out.mark & 1 {
    329 			fputs(c.cout, "\t");
    330 			fputs(c.cout, "goto b");
    331 			fputd(c.cout, ib.out.n);
    332 			fputs(c.cout, ";\n");
    333 		}
    334 	} else if kind == IOP_BRANCH {
    335 		ircline(c, op);
    336 
    337 		if !didlabel {
    338 			fputs(c.cout, "b");
    339 			fputd(c.cout, ib.n);
    340 			fputs(c.cout, ":");
    341 			didlabel = 1;
    342 		}
    343 
    344 		fputs(c.cout, "\t");
    345 		fputs(c.cout, "if (");
    346 		ircop_neg(c, ic, ib, op.a, 20);
    347 		fputs(c.cout, ") goto b");
    348 		fputd(c.cout, ib.alt.n);
    349 		fputs(c.cout, ";\n");
    350 
    351 		if ib.out.mark & 1 {
    352 			ircline(c, op);
    353 			fputs(c.cout, "\t");
    354 			fputs(c.cout, "goto b");
    355 			fputd(c.cout, ib.out.n);
    356 			fputs(c.cout, ";\n");
    357 		}
    358 	} else if kind == IOP_RETURN {
    359 		ircline(c, op);
    360 
    361 		if !didlabel {
    362 			fputs(c.cout, "b");
    363 			fputd(c.cout, ib.n);
    364 			fputs(c.cout, ":");
    365 			didlabel = 1;
    366 		}
    367 
    368 		fputs(c.cout, "\t");
    369 		fputs(c.cout, "return ");
    370 		ircop(c, ic, ib, op.a, 20);
    371 		fputs(c.cout, ";\n");
    372 	} else {
    373 		die("invalid op");
    374 	}
    375 }
    376 
    377 func ircline(c: *compiler, op: *irop) {
    378 	return; // Try to minimize the output, don't output lines.
    379 
    380 	if !op.filename {
    381 		return;
    382 	}
    383 
    384 	fputs(c.cout, "#line ");
    385 	fputd(c.cout, op.lineno);
    386 	fputs(c.cout, " ");
    387 	ircstr(c, op.filename, strlen(op.filename));
    388 	fputs(c.cout, "\n");
    389 }
    390 
    391 func ircstr(c: *compiler, s: *byte, n: int) {
    392 	var i: int;
    393 	var ch: int;
    394 
    395 	i = 0;
    396 	fputs(c.cout, "\"");
    397 	loop {
    398 		if i == n {
    399 			break;
    400 		}
    401 
    402 		if i % 100 == 99 {
    403 			fputs(c.cout, "\"\n\t\t\"");
    404 		}
    405 
    406 		ch = s[i] as int;
    407 
    408 		if ch < 32 || ch > 127 || ch == '\\' || ch == '"' {
    409 			fputc(c.cout, '\\');
    410 			fputc(c.cout, '0' + (ch >> 6) & 7);
    411 			fputc(c.cout, '0' + (ch >> 3) & 7);
    412 			fputc(c.cout, '0' + ch & 7);
    413 		} else {
    414 			fputc(c.cout, ch);
    415 		}
    416 
    417 		i = i + 1;
    418 	}
    419 	fputs(c.cout, "\"");
    420 }
    421 
    422 func ircop_neg(c: *compiler, ic: *irfunc, ib: *irblock, op: *irop, pri: int) {
    423 	var kind: int;
    424 
    425 	kind = op.kind;
    426 	if kind == IOP_EQ {
    427 		ircop(c, ic, ib, op.a, 7);
    428 		fputs(c.cout, " != ");
    429 		ircop(c, ic, ib, op.b, 7);
    430 	} else if kind == IOP_NE {
    431 		ircop(c, ic, ib, op.a, 7);
    432 		fputs(c.cout, " == ");
    433 		ircop(c, ic, ib, op.b, 7);
    434 	} else if kind == IOP_GT {
    435 		fputs(c.cout, "(s)");
    436 		ircop(c, ic, ib, op.a, 2);
    437 		fputs(c.cout, " <= (s)");
    438 		ircop(c, ic, ib, op.b, 2);
    439 	} else if kind == IOP_GE {
    440 		fputs(c.cout, "(s)");
    441 		ircop(c, ic, ib, op.a, 2);
    442 		fputs(c.cout, " < (s)");
    443 		ircop(c, ic, ib, op.b, 2);
    444 	} else if kind == IOP_LT {
    445 		fputs(c.cout, "(s)");
    446 		ircop(c, ic, ib, op.a, 2);
    447 		fputs(c.cout, " >= (s)");
    448 		ircop(c, ic, ib, op.b, 2);
    449 	} else if kind == IOP_LE {
    450 		fputs(c.cout, "(s)");
    451 		ircop(c, ic, ib, op.a, 2);
    452 		fputs(c.cout, " > (s)");
    453 		ircop(c, ic, ib, op.b, 2);
    454 	} else {
    455 		fputs(c.cout, "!");
    456 		ircop(c, ic, ib, op, 2);
    457 	}
    458 }
    459 
    460 func ircop(c: *compiler, ic: *irfunc, ib: *irblock, op: *irop, pri: int) {
    461 	var kind: int;
    462 	var iv: *irvar;
    463 	var size: int;
    464 	var mypri: int;
    465 
    466 	// C Operator Precedence
    467 	// 1 call()
    468 	// 2 ! ~ * - & (cast)
    469 	// 3 * / %
    470 	// 4 + -
    471 	// 5 << >>
    472 	// 6 < <= > >=
    473 	// 7 == !=
    474 	// 8 &
    475 	// 9 |
    476 	kind = op.kind;
    477 	if kind == IOP_VAR || kind == IOP_VARREF {
    478 		mypri = 2;
    479 	} else if kind == IOP_FUNC {
    480 		mypri = 2;
    481 	} else if kind == IOP_CONST {
    482 		mypri = 1;
    483 	} else if kind == IOP_STR {
    484 		mypri = 2;
    485 	} else if kind == IOP_LOAD {
    486 		mypri = 2;
    487 	} else if kind == IOP_STORE {
    488 		mypri = 2;
    489 	} else if kind == IOP_NEG {
    490 		mypri = 2;
    491 	} else if kind == IOP_NOT {
    492 		mypri = 2;
    493 	} else if kind == IOP_ADD {
    494 		mypri = 4;
    495 	} else if kind == IOP_AND {
    496 		mypri = 8;
    497 	} else if kind == IOP_OR {
    498 		mypri = 10;
    499 	} else if kind == IOP_XOR {
    500 		mypri = 9;
    501 	} else if kind == IOP_DIV {
    502 		mypri = 2;
    503 	} else if kind == IOP_MOD {
    504 		mypri = 2;
    505 	} else if kind == IOP_LSH {
    506 		mypri = 6;
    507 	} else if kind == IOP_RSH {
    508 		mypri = 6;
    509 	} else if kind == IOP_MUL {
    510 		mypri = 3;
    511 	} else if kind == IOP_SUB {
    512 		mypri = 4;
    513 	} else if kind == IOP_EQ {
    514 		mypri = 7;
    515 	} else if kind == IOP_NE {
    516 		mypri = 7;
    517 	} else if kind == IOP_GT {
    518 		mypri = 2;
    519 	} else if kind == IOP_GE {
    520 		mypri = 2;
    521 	} else if kind == IOP_LT {
    522 		mypri = 2;
    523 	} else if kind == IOP_LE {
    524 		mypri = 2;
    525 	} else {
    526 		die("invalid op");
    527 	}
    528 
    529 	if mypri >= pri {
    530 		fputs(c.cout, "(");
    531 	}
    532 
    533 	if kind == IOP_VAR || kind == IOP_VARREF {
    534 		iv = ic.vars[op.n];
    535 
    536 		if iv.t && iv.t.kind != TY_VOID {
    537 			size = type_sizeof(c, iv.t);
    538 		} else {
    539 			size = sizeof(size);
    540 		}
    541 
    542 		if size == sizeof(size) {
    543 			if kind == IOP_VARREF {
    544 				fputs(c.cout, "(u)&");
    545 			}
    546 		} else {
    547 			if kind == IOP_VARREF {
    548 				fputs(c.cout, "(u)");
    549 			} else {
    550 				fputs(c.cout, "*");
    551 			}
    552 		}
    553 
    554 		if iv.name {
    555 			fputs(c.cout, "v");
    556 			fputs(c.cout, iv.name);
    557 		} else {
    558 			fputs(c.cout, "v");
    559 			fputd(c.cout, op.n);
    560 		}
    561 	} else if kind == IOP_FUNC {
    562 		fputs(c.cout, "(u)z");
    563 		fputs(c.cout, op.s);
    564 	} else if kind == IOP_CONST {
    565 		fputd(c.cout, op.n);
    566 		fputs(c.cout, "UL");
    567 	} else if kind == IOP_STR {
    568 		fputs(c.cout, "(u)");
    569 		ircstr(c, op.s, op.slen);
    570 	} else if kind == IOP_LOAD {
    571 		if op.t.kind == TY_BYTE {
    572 			fputs(c.cout, "(u)*(b*)");
    573 			ircop(c, ic, ib, op.a, 2);
    574 		} else {
    575 			fputs(c.cout, "*(u*)");
    576 			ircop(c, ic, ib, op.a, 2);
    577 		}
    578 	} else if kind == IOP_STORE {
    579 		if op.a.kind == IOP_VAR {
    580 			ircop(c, ic, ib, op.a, 14);
    581 			fputs(c.cout, " = ");
    582 			ircop(c, ic, ib, op.b, 14);
    583 		} else if op.a.kind == IOP_LOAD {
    584 			if op.t.kind == TY_BYTE {
    585 				fputs(c.cout, "*(b*)");
    586 			} else {
    587 				fputs(c.cout, "*(u*)");
    588 			}
    589 			ircop(c, ic, ib, op.a.a, 2);
    590 			fputs(c.cout, " = ");
    591 			ircop(c, ic, ib, op.b, 14);
    592 		} else {
    593 			die("invalid store");
    594 		}
    595 	} else if kind == IOP_NEG {
    596 		fputs(c.cout, "-");
    597 		ircop(c, ic, ib, op.a, 2);
    598 	} else if kind == IOP_NOT {
    599 		fputs(c.cout, "~");
    600 		ircop(c, ic, ib, op.a, 2);
    601 	} else if kind == IOP_ADD {
    602 		ircop(c, ic, ib, op.a, 4);
    603 		fputs(c.cout, " + ");
    604 		ircop(c, ic, ib, op.b, 4);
    605 	} else if kind == IOP_AND {
    606 		ircop(c, ic, ib, op.a, 8);
    607 		fputs(c.cout, " & ");
    608 		ircop(c, ic, ib, op.b, 8);
    609 	} else if kind == IOP_OR {
    610 		ircop(c, ic, ib, op.a, 10);
    611 		fputs(c.cout, " | ");
    612 		ircop(c, ic, ib, op.b, 10);
    613 	} else if kind == IOP_XOR {
    614 		ircop(c, ic, ib, op.a, 9);
    615 		fputs(c.cout, " ^ ");
    616 		ircop(c, ic, ib, op.b, 9);
    617 	} else if kind == IOP_DIV {
    618 		fputs(c.cout, "(u)((s)");
    619 		ircop(c, ic, ib, op.a, 2);
    620 		fputs(c.cout, " / (s)");
    621 		ircop(c, ic, ib, op.b, 2);
    622 		fputs(c.cout, ")");
    623 	} else if kind == IOP_MOD {
    624 		fputs(c.cout, "(u)((s)");
    625 		ircop(c, ic, ib, op.a, 2);
    626 		fputs(c.cout, " % (s)");
    627 		ircop(c, ic, ib, op.b, 2);
    628 		fputs(c.cout, ")");
    629 	} else if kind == IOP_LSH {
    630 		ircop(c, ic, ib, op.a, 6);
    631 		fputs(c.cout, " << ");
    632 		ircop(c, ic, ib, op.b, 6);
    633 	} else if kind == IOP_RSH {
    634 		ircop(c, ic, ib, op.a, 6);
    635 		fputs(c.cout, " >> ");
    636 		ircop(c, ic, ib, op.b, 6);
    637 	} else if kind == IOP_MUL {
    638 		ircop(c, ic, ib, op.a, 3);
    639 		fputs(c.cout, " * ");
    640 		ircop(c, ic, ib, op.b, 3);
    641 	} else if kind == IOP_SUB {
    642 		ircop(c, ic, ib, op.a, 4);
    643 		fputs(c.cout, " - ");
    644 		ircop(c, ic, ib, op.b, 4);
    645 	} else if kind == IOP_EQ {
    646 		fputs(c.cout, "(u)(");
    647 		ircop(c, ic, ib, op.a, 7);
    648 		fputs(c.cout, " == ");
    649 		ircop(c, ic, ib, op.b, 7);
    650 		fputs(c.cout, ")");
    651 	} else if kind == IOP_NE {
    652 		fputs(c.cout, "(u)(");
    653 		ircop(c, ic, ib, op.a, 7);
    654 		fputs(c.cout, " != ");
    655 		ircop(c, ic, ib, op.b, 7);
    656 		fputs(c.cout, ")");
    657 	} else if kind == IOP_GT {
    658 		fputs(c.cout, "(u)((s)");
    659 		ircop(c, ic, ib, op.a, 6);
    660 		fputs(c.cout, " > (s)");
    661 		ircop(c, ic, ib, op.b, 6);
    662 		fputs(c.cout, ")");
    663 	} else if kind == IOP_GE {
    664 		fputs(c.cout, "(u)((s)");
    665 		ircop(c, ic, ib, op.a, 6);
    666 		fputs(c.cout, " >= (s)");
    667 		ircop(c, ic, ib, op.b, 6);
    668 		fputs(c.cout, ")");
    669 	} else if kind == IOP_LT {
    670 		fputs(c.cout, "(u)((s)");
    671 		ircop(c, ic, ib, op.a, 6);
    672 		fputs(c.cout, " < (s)");
    673 		ircop(c, ic, ib, op.b, 6);
    674 		fputs(c.cout, ")");
    675 	} else if kind == IOP_LE {
    676 		fputs(c.cout, "(u)((s)");
    677 		ircop(c, ic, ib, op.a, 6);
    678 		fputs(c.cout, " <= (s)");
    679 		ircop(c, ic, ib, op.b, 6);
    680 		fputs(c.cout, ")");
    681 	} else {
    682 		die("invalid op");
    683 	}
    684 
    685 	if mypri >= pri {
    686 		fputs(c.cout, ")");
    687 	}
    688 }
    689 
    690 func irccall(c: *compiler, ic: *irfunc, ib: *irblock, op: *irop) {
    691 	fputs(c.cout, "\t");
    692 	ircretval(c, ic, ib);
    693 
    694 	if op.a.kind != IOP_FUNC {
    695 		fputs(c.cout, "((u(*)())");
    696 		ircop(c, ic, ib, op.a, 2);
    697 		fputs(c.cout, ")(");
    698 	} else {
    699 		fputs(c.cout, "z");
    700 		fputs(c.cout, op.a.s);
    701 		fputs(c.cout, "(");
    702 	}
    703 
    704 	ircargs(c, ic, ib, op.n);
    705 	fputs(c.cout, ");\n");
    706 
    707 	if ib.out.mark & 1 {
    708 		ircline(c, op);
    709 		fputs(c.cout, "\t");
    710 		fputs(c.cout, "goto b");
    711 		fputd(c.cout, ib.out.n);
    712 		fputs(c.cout, ";\n");
    713 	}
    714 }
    715 
    716 func ircretval(c: *compiler, ic: *irfunc, ib: *irblock) {
    717 	var i: int;
    718 	var op: *irop;
    719 	var kind: int;
    720 
    721 	i = 0;
    722 	loop {
    723 		if i == ib.ops_len {
    724 			break;
    725 		}
    726 
    727 		op = ib.ops[i];
    728 		if op.kind == IOP_RETVAL {
    729 			ircop(c, ic, ib, op.a, 14);
    730 			fputs(c.cout, " = ");
    731 			break;
    732 		}
    733 
    734 		i = i + 1;
    735 	}
    736 }
    737 
    738 func ircargs(c: *compiler, ic: *irfunc, ib: *irblock, n: int) {
    739 	var i: int;
    740 	var op: *irop;
    741 	var kind: int;
    742 	var args: **irop;
    743 
    744 	args = alloc(c.a, n * sizeof(*args)) as **irop;
    745 
    746 	i = 0;
    747 	loop {
    748 		if i == ib.ops_len {
    749 			break;
    750 		}
    751 
    752 		op = ib.ops[i];
    753 		if op.kind == IOP_ARG {
    754 			args[op.n] = op.a;
    755 		}
    756 
    757 		i = i + 1;
    758 	}
    759 
    760 	i = 0;
    761 	loop {
    762 		if i == n {
    763 			break;
    764 		}
    765 
    766 		if args[i] {
    767 			ircop(c, ic, ib, args[i], 15);
    768 		} else {
    769 			fputs(c.cout, "0UL");
    770 		}
    771 
    772 		i = i + 1;
    773 
    774 		if i != n {
    775 			fputs(c.cout, ", ");
    776 		}
    777 	}
    778 
    779 	free(c.a, args as *byte);
    780 }