diff --git a/.gitignore b/.gitignore index 78922fbedf..569dfad1ce 100644 --- a/.gitignore +++ b/.gitignore @@ -395,6 +395,7 @@ winxed-c.html /t/compilers/data_json/*.pir /t/compilers/data_json/*_pbcexe /t/compilers/imcc/*.pbc +/t/compilers/imcc/imcpasm/*.pir /t/compilers/imcc/reg/*.pasm /t/compilers/imcc/reg/*.pbc /t/compilers/imcc/reg/*.pir diff --git a/compilers/imcc/debug.c b/compilers/imcc/debug.c index 27db8828ae..8ba7a6418d 100644 --- a/compilers/imcc/debug.c +++ b/compilers/imcc/debug.c @@ -244,13 +244,24 @@ IMCC_debug(ARGMOD(imc_info_t * imcc), int level, ARGIN(const char *fmt), ...) } void IMCC_debug_ins(imc_info_t *imcc, int level, const Instruction *ins) { - PIOHANDLE pstderr; - if (!(level & imcc->debug)) + if (!((level & imcc->debug) || imcc->write_pasm)) return; - pstderr = Parrot_io_internal_std_os_handle(imcc->interp, PIO_STDERR_FILENO); - Parrot_io_pprintf(imcc->interp, pstderr, "0x%x %s ", ins, ins->opname); - ins_print(imcc, pstderr, ins); - Parrot_io_pprintf(imcc->interp, pstderr, "\n"); + if (level & imcc->debug) { + PIOHANDLE pstderr; + pstderr = Parrot_io_internal_std_os_handle(imcc->interp, PIO_STDERR_FILENO); + if (imcc->verbose) + Parrot_io_eprintf(imcc->interp, "0x%x ", ins); + Parrot_io_eprintf(imcc->interp, "%s ", ins->opname); + ins_print(imcc, pstderr, ins); + Parrot_io_eprintf(imcc->interp, "\n"); + } +#if 0 + if (imcc->write_pasm) { + Parrot_io_pprintf(imcc->interp, imcc->write_pasm, "%s ", ins->opname); + ins_print(imcc, imcc->write_pasm, ins); + Parrot_io_pprintf(imcc->interp, imcc->write_pasm, "\n"); + } +#endif } /* @@ -269,31 +280,31 @@ dump_instructions(ARGMOD(imc_info_t * imcc), ARGIN(const IMC_Unit *unit)) ASSERT_ARGS(dump_instructions) const Instruction *ins; int pc; - const PIOHANDLE pstderr = + const PIOHANDLE pstderr = Parrot_io_internal_std_os_handle(imcc->interp, PIO_STDERR_FILENO); Parrot_io_eprintf(imcc->interp, "\nDumping the instructions status:" "\n-------------------------------\n"); Parrot_io_eprintf(imcc->interp, - "nins line blck deep flags\t type opnr size pc X ins\n"); + "nins line blck deep flags\t type opnr size pc X ins\n"); for (pc = 0, ins = unit->instructions; ins; ins = ins->next) { const Basic_block * const bb = unit->bb_list[ins->bbindex]; if (bb) { Parrot_io_eprintf(imcc->interp, - "%4i %4d %4d %4d\t%x\t%8x %4d %4d %4d ", - ins->index, ins->line, bb->index, bb->loop_depth, - ins->flags, ins->type, OP_INFO_OPNUM(ins->op), - ins->opsize, pc); + "%4i %4d %4d %4d\t%6x\t%8x %4d %4d %4d ", + ins->index, ins->line, bb->index, bb->loop_depth, + ins->flags, ins->type, ins->op ? OP_INFO_OPNUM(ins->op) : 0, + ins->opsize, pc); } else { - Parrot_io_eprintf(imcc->interp, "\t"); + Parrot_io_eprintf(imcc->interp, " \t \t "); } - - Parrot_io_eprintf(imcc->interp, "%s\n", ins->opname); - ins_print(imcc, pstderr, ins); + IMCC_debug_ins(imcc, 0xffff, ins); + //Parrot_io_eprintf(imcc->interp, "%s\n", ins->opname); + //ins_print(imcc, pstderr, ins); pc += ins->opsize; } diff --git a/compilers/imcc/debug.h b/compilers/imcc/debug.h index 8d1d7f8fe3..8c2bc58e5b 100644 --- a/compilers/imcc/debug.h +++ b/compilers/imcc/debug.h @@ -64,14 +64,6 @@ void IMCC_debug( __attribute__nonnull__(3) FUNC_MODIFIES(* imcc); -void IMCC_debug_ins( - ARGMOD(imc_info_t * imcc), - int level, - ARGIN(const Instruction *ins)) - __attribute__nonnull__(1) - __attribute__nonnull__(3) - FUNC_MODIFIES(* imcc); - PARROT_DOES_NOT_RETURN void IMCC_fatal( ARGMOD(imc_info_t * imcc), @@ -152,6 +144,7 @@ void IMCC_warning(ARGMOD(imc_info_t * imcc), ARGIN(const char *fmt), ...) /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ /* HEADERIZER END: compilers/imcc/debug.c */ +void IMCC_debug_ins(imc_info_t *imcc, int level, const Instruction *ins); #endif /* PARROT_IMCC_DEBUG_H_GUARD */ diff --git a/compilers/imcc/imc.c b/compilers/imcc/imc.c index 185b2ce088..009ca6ea2a 100644 --- a/compilers/imcc/imc.c +++ b/compilers/imcc/imc.c @@ -79,7 +79,7 @@ imc_compile_all_units(ARGMOD(imc_info_t * imcc)) } #endif - emit_close(imcc, NULL); + emit_close(imcc); /* All done with compilation, now free all memory allocated * for instructions and other structures. */ diff --git a/compilers/imcc/imc.h b/compilers/imcc/imc.h index b48b2db9b9..f6787757da 100644 --- a/compilers/imcc/imc.h +++ b/compilers/imcc/imc.h @@ -227,6 +227,7 @@ int imcc_string_ends_with( FUNC_MODIFIES(* imcc); PARROT_IGNORABLE_RESULT +PARROT_INLINE int /*@alt void@*/ imcc_vfprintf( ARGMOD(imc_info_t * imcc), @@ -483,12 +484,12 @@ struct _imc_info_t { AsmState asm_state; SymHash ghash; jmp_buf jump_buf; /* The jump for error handling */ + PIOHANDLE write_pasm; int cnr; int debug; int dont_optimize; int emitter; int error_code; /* The Error code. */ - int expect_pasm; int imcc_warn; int in_pod; int ins_line; diff --git a/compilers/imcc/imcc.l b/compilers/imcc/imcc.l index 75f4a8cf4d..852d12af3d 100644 --- a/compilers/imcc/imcc.l +++ b/compilers/imcc/imcc.l @@ -64,6 +64,8 @@ static void include_file(ARGMOD(imc_info_t *imcc), ARGIN(STRING *file_name), ARG static int handle_identifier(ARGMOD(imc_info_t *imcc), YYSTYPE *valp, ARGIN(const char *id)); +PIOHANDLE determine_input_file_type(ARGMOD(imc_info_t * imcc), ARGIN(STRING *sourcefile)); + #define YY_DECL int yylex(YYSTYPE *valp, yyscan_t yyscanner, ARGMOD(imc_info_t *imcc)) #define YYCHOP() (yytext[--yyleng] = '\0') @@ -132,8 +134,8 @@ SP [ ] %% /* for emacs "*/ - if (imcc->expect_pasm == 1 && !imcc->in_pod) { - imcc->expect_pasm = 2; + if (imcc->write_pasm == 1 && !imcc->in_pod) { + imcc->write_pasm = 2; BEGIN(emit); } @@ -235,10 +237,10 @@ SP [ ] } {EOL} { - if (imcc->expect_pasm == 2) + if (imcc->write_pasm == 2) BEGIN(INITIAL); - imcc->expect_pasm = 0; + imcc->write_pasm = 0; return '\n'; } @@ -248,12 +250,12 @@ SP [ ] } .*{EOL} { - if (imcc->expect_pasm == 2) + if (imcc->write_pasm == 2) BEGIN(INITIAL); else yy_pop_state(yyscanner); - imcc->expect_pasm = 0; + imcc->write_pasm = 0; return '\n'; } @@ -1365,7 +1367,7 @@ imcc_compile_buffer_safe(ARGMOD(imc_info_t *imcc), yyscan_t yyscanner, buffer = YY_CURRENT_BUFFER; file = imcc_setup_input(imcc, yyscanner, source, source_c, is_file); - emit_open(imcc); + emit_open(imcc, source); success = imcc_run_compilation(imcc, yyscanner); imcc_cleanup_input(imcc, file, source_c, is_file); diff --git a/compilers/imcc/imclexer.c b/compilers/imcc/imclexer.c index 73ed3c1c60..2bbfdd3a16 100644 --- a/compilers/imcc/imclexer.c +++ b/compilers/imcc/imclexer.c @@ -1761,6 +1761,8 @@ static void include_file(ARGMOD(imc_info_t *imcc), ARGIN(STRING *file_name), ARG static int handle_identifier(ARGMOD(imc_info_t *imcc), YYSTYPE *valp, ARGIN(const char *id)); +PIOHANDLE determine_input_file_type(ARGMOD(imc_info_t * imcc), ARGIN(STRING *sourcefile)); + #define YY_DECL int yylex(YYSTYPE *valp,yyscan_t yyscanner,ARGMOD(imc_info_t *imcc)) #define YYCHOP() (yytext[--yyleng] = '\0') @@ -1795,7 +1797,7 @@ static int handle_identifier(ARGMOD(imc_info_t *imcc), YYSTYPE *valp, ARGIN(cons -#line 1799 "compilers/imcc/imclexer.c" +#line 1801 "compilers/imcc/imclexer.c" #define INITIAL 0 #define emit 1 @@ -2044,11 +2046,11 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 133 "compilers/imcc/imcc.l" +#line 135 "compilers/imcc/imcc.l" /* for emacs "*/ - if (imcc->expect_pasm == 1 && !imcc->in_pod) { - imcc->expect_pasm = 2; + if (imcc->write_pasm == 1 && !imcc->in_pod) { + imcc->write_pasm = 2; BEGIN(emit); } @@ -2063,7 +2065,7 @@ YY_DECL return 0; } -#line 2067 "compilers/imcc/imclexer.c" +#line 2069 "compilers/imcc/imclexer.c" if ( !yyg->yy_init ) { @@ -2157,13 +2159,13 @@ YY_DECL case 1: YY_RULE_SETUP -#line 151 "compilers/imcc/imcc.l" +#line 153 "compilers/imcc/imcc.l" { SET_LINE_NUMBER; } YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP -#line 153 "compilers/imcc/imcc.l" +#line 155 "compilers/imcc/imcc.l" { SET_LINE_NUMBER; imcc->frames->heredoc_rest = mem_sys_strndup(yytext, yyleng); @@ -2173,7 +2175,7 @@ YY_RULE_SETUP case 3: /* rule 3 can match eol */ YY_RULE_SETUP -#line 159 "compilers/imcc/imcc.l" +#line 161 "compilers/imcc/imcc.l" { /* heredocs have highest priority * arrange them before all wildcard state matches */ @@ -2188,7 +2190,7 @@ YY_RULE_SETUP YY_BREAK case 4: YY_RULE_SETUP -#line 171 "compilers/imcc/imcc.l" +#line 173 "compilers/imcc/imcc.l" { SET_LINE_NUMBER; /* Are we at the end of the heredoc? */ @@ -2229,7 +2231,7 @@ YY_RULE_SETUP case 5: /* rule 5 can match eol */ YY_RULE_SETUP -#line 208 "compilers/imcc/imcc.l" +#line 210 "compilers/imcc/imcc.l" { STRING *str; @@ -2245,7 +2247,7 @@ YY_RULE_SETUP YY_BREAK case 6: YY_RULE_SETUP -#line 221 "compilers/imcc/imcc.l" +#line 223 "compilers/imcc/imcc.l" { yy_pop_state(yyscanner); yy_push_state(cmt4, yyscanner); @@ -2253,7 +2255,7 @@ YY_RULE_SETUP YY_BREAK case 7: YY_RULE_SETUP -#line 226 "compilers/imcc/imcc.l" +#line 228 "compilers/imcc/imcc.l" { yylineno = imcc->line = atoi(yytext); yy_pop_state(yyscanner); @@ -2264,7 +2266,7 @@ YY_RULE_SETUP case 8: /* rule 8 can match eol */ YY_RULE_SETUP -#line 233 "compilers/imcc/imcc.l" +#line 235 "compilers/imcc/imcc.l" { yy_pop_state(yyscanner); } @@ -2272,19 +2274,19 @@ YY_RULE_SETUP case 9: /* rule 9 can match eol */ YY_RULE_SETUP -#line 237 "compilers/imcc/imcc.l" +#line 239 "compilers/imcc/imcc.l" { - if (imcc->expect_pasm == 2) + if (imcc->write_pasm == 2) BEGIN(INITIAL); - imcc->expect_pasm = 0; + imcc->write_pasm = 0; return '\n'; } YY_BREAK case 10: YY_RULE_SETUP -#line 246 "compilers/imcc/imcc.l" +#line 248 "compilers/imcc/imcc.l" { yy_push_state(cmt5, yyscanner); } @@ -2292,14 +2294,14 @@ YY_RULE_SETUP case 11: /* rule 11 can match eol */ YY_RULE_SETUP -#line 250 "compilers/imcc/imcc.l" +#line 252 "compilers/imcc/imcc.l" { - if (imcc->expect_pasm == 2) + if (imcc->write_pasm == 2) BEGIN(INITIAL); else yy_pop_state(yyscanner); - imcc->expect_pasm = 0; + imcc->write_pasm = 0; return '\n'; } @@ -2307,7 +2309,7 @@ YY_RULE_SETUP case 12: /* rule 12 can match eol */ YY_RULE_SETUP -#line 262 "compilers/imcc/imcc.l" +#line 264 "compilers/imcc/imcc.l" { /* this is a stand-alone =cut, but we're not in POD mode, so ignore. */ SET_LINE_NUMBER; @@ -2316,7 +2318,7 @@ YY_RULE_SETUP case 13: /* rule 13 can match eol */ YY_RULE_SETUP -#line 267 "compilers/imcc/imcc.l" +#line 269 "compilers/imcc/imcc.l" { SET_LINE_NUMBER; imcc->in_pod = 1; @@ -2326,7 +2328,7 @@ YY_RULE_SETUP case 14: /* rule 14 can match eol */ YY_RULE_SETUP -#line 273 "compilers/imcc/imcc.l" +#line 275 "compilers/imcc/imcc.l" { SET_LINE_NUMBER; imcc->in_pod = 0; @@ -2335,458 +2337,458 @@ YY_RULE_SETUP YY_BREAK case 15: YY_RULE_SETUP -#line 279 "compilers/imcc/imcc.l" +#line 281 "compilers/imcc/imcc.l" { SET_LINE_NUMBER; } YY_BREAK case 16: /* rule 16 can match eol */ YY_RULE_SETUP -#line 281 "compilers/imcc/imcc.l" +#line 283 "compilers/imcc/imcc.l" { /* ignore */ } YY_BREAK case 17: YY_RULE_SETUP -#line 283 "compilers/imcc/imcc.l" +#line 285 "compilers/imcc/imcc.l" return ANNOTATE; YY_BREAK case 18: YY_RULE_SETUP -#line 284 "compilers/imcc/imcc.l" +#line 286 "compilers/imcc/imcc.l" return LEXICAL; YY_BREAK case 19: YY_RULE_SETUP -#line 285 "compilers/imcc/imcc.l" +#line 287 "compilers/imcc/imcc.l" return ARG; YY_BREAK case 20: YY_RULE_SETUP -#line 286 "compilers/imcc/imcc.l" +#line 288 "compilers/imcc/imcc.l" { SET_LINE_NUMBER; return SUB; } YY_BREAK case 21: YY_RULE_SETUP -#line 287 "compilers/imcc/imcc.l" +#line 289 "compilers/imcc/imcc.l" return ESUB; YY_BREAK case 22: YY_RULE_SETUP -#line 288 "compilers/imcc/imcc.l" +#line 290 "compilers/imcc/imcc.l" return PCC_BEGIN; YY_BREAK case 23: YY_RULE_SETUP -#line 289 "compilers/imcc/imcc.l" +#line 291 "compilers/imcc/imcc.l" return PCC_END; YY_BREAK case 24: YY_RULE_SETUP -#line 290 "compilers/imcc/imcc.l" +#line 292 "compilers/imcc/imcc.l" return PCC_CALL; YY_BREAK case 25: YY_RULE_SETUP -#line 291 "compilers/imcc/imcc.l" +#line 293 "compilers/imcc/imcc.l" return INVOCANT; YY_BREAK case 26: YY_RULE_SETUP -#line 292 "compilers/imcc/imcc.l" +#line 294 "compilers/imcc/imcc.l" return PCC_SUB; YY_BREAK case 27: YY_RULE_SETUP -#line 293 "compilers/imcc/imcc.l" +#line 295 "compilers/imcc/imcc.l" return PCC_BEGIN_RETURN; YY_BREAK case 28: YY_RULE_SETUP -#line 294 "compilers/imcc/imcc.l" +#line 296 "compilers/imcc/imcc.l" return PCC_END_RETURN; YY_BREAK case 29: YY_RULE_SETUP -#line 295 "compilers/imcc/imcc.l" +#line 297 "compilers/imcc/imcc.l" return PCC_BEGIN_YIELD; YY_BREAK case 30: YY_RULE_SETUP -#line 296 "compilers/imcc/imcc.l" +#line 298 "compilers/imcc/imcc.l" return PCC_END_YIELD; YY_BREAK case 31: YY_RULE_SETUP -#line 298 "compilers/imcc/imcc.l" +#line 300 "compilers/imcc/imcc.l" return METHOD; YY_BREAK case 32: YY_RULE_SETUP -#line 299 "compilers/imcc/imcc.l" +#line 301 "compilers/imcc/imcc.l" return MULTI; YY_BREAK case 33: YY_RULE_SETUP -#line 300 "compilers/imcc/imcc.l" +#line 302 "compilers/imcc/imcc.l" return MAIN; YY_BREAK case 34: YY_RULE_SETUP -#line 301 "compilers/imcc/imcc.l" +#line 303 "compilers/imcc/imcc.l" return LOAD; YY_BREAK case 35: YY_RULE_SETUP -#line 302 "compilers/imcc/imcc.l" +#line 304 "compilers/imcc/imcc.l" return INIT; YY_BREAK case 36: YY_RULE_SETUP -#line 303 "compilers/imcc/imcc.l" +#line 305 "compilers/imcc/imcc.l" return IMMEDIATE; YY_BREAK case 37: YY_RULE_SETUP -#line 304 "compilers/imcc/imcc.l" +#line 306 "compilers/imcc/imcc.l" return POSTCOMP; YY_BREAK case 38: YY_RULE_SETUP -#line 305 "compilers/imcc/imcc.l" +#line 307 "compilers/imcc/imcc.l" return SUBTAG; YY_BREAK case 39: YY_RULE_SETUP -#line 306 "compilers/imcc/imcc.l" +#line 308 "compilers/imcc/imcc.l" return ANON; YY_BREAK case 40: YY_RULE_SETUP -#line 307 "compilers/imcc/imcc.l" +#line 309 "compilers/imcc/imcc.l" return OUTER; YY_BREAK case 41: YY_RULE_SETUP -#line 308 "compilers/imcc/imcc.l" +#line 310 "compilers/imcc/imcc.l" return NEED_LEX; YY_BREAK case 42: YY_RULE_SETUP -#line 309 "compilers/imcc/imcc.l" +#line 311 "compilers/imcc/imcc.l" return VTABLE_METHOD; YY_BREAK case 43: YY_RULE_SETUP -#line 310 "compilers/imcc/imcc.l" +#line 312 "compilers/imcc/imcc.l" return NS_ENTRY; YY_BREAK case 44: YY_RULE_SETUP -#line 311 "compilers/imcc/imcc.l" +#line 313 "compilers/imcc/imcc.l" return SUB_INSTANCE_OF; YY_BREAK case 45: YY_RULE_SETUP -#line 312 "compilers/imcc/imcc.l" +#line 314 "compilers/imcc/imcc.l" return SUBID; YY_BREAK case 46: YY_RULE_SETUP -#line 314 "compilers/imcc/imcc.l" +#line 316 "compilers/imcc/imcc.l" return RESULT; YY_BREAK case 47: YY_RULE_SETUP -#line 315 "compilers/imcc/imcc.l" +#line 317 "compilers/imcc/imcc.l" return GET_RESULTS; YY_BREAK case 48: YY_RULE_SETUP -#line 316 "compilers/imcc/imcc.l" +#line 318 "compilers/imcc/imcc.l" return YIELDT; YY_BREAK case 49: YY_RULE_SETUP -#line 317 "compilers/imcc/imcc.l" +#line 319 "compilers/imcc/imcc.l" return SET_YIELD; YY_BREAK case 50: YY_RULE_SETUP -#line 318 "compilers/imcc/imcc.l" +#line 320 "compilers/imcc/imcc.l" return RETURN; YY_BREAK case 51: YY_RULE_SETUP -#line 319 "compilers/imcc/imcc.l" +#line 321 "compilers/imcc/imcc.l" return SET_RETURN; YY_BREAK case 52: YY_RULE_SETUP -#line 320 "compilers/imcc/imcc.l" +#line 322 "compilers/imcc/imcc.l" return TAILCALL; YY_BREAK case 53: YY_RULE_SETUP -#line 321 "compilers/imcc/imcc.l" +#line 323 "compilers/imcc/imcc.l" return LOADLIB; YY_BREAK case 54: YY_RULE_SETUP -#line 323 "compilers/imcc/imcc.l" +#line 325 "compilers/imcc/imcc.l" return ADV_FLAT; YY_BREAK case 55: YY_RULE_SETUP -#line 324 "compilers/imcc/imcc.l" +#line 326 "compilers/imcc/imcc.l" return ADV_SLURPY; YY_BREAK case 56: YY_RULE_SETUP -#line 325 "compilers/imcc/imcc.l" +#line 327 "compilers/imcc/imcc.l" return ADV_OPTIONAL; YY_BREAK case 57: YY_RULE_SETUP -#line 326 "compilers/imcc/imcc.l" +#line 328 "compilers/imcc/imcc.l" return ADV_OPT_FLAG; YY_BREAK case 58: YY_RULE_SETUP -#line 327 "compilers/imcc/imcc.l" +#line 329 "compilers/imcc/imcc.l" return ADV_NAMED; YY_BREAK case 59: YY_RULE_SETUP -#line 328 "compilers/imcc/imcc.l" +#line 330 "compilers/imcc/imcc.l" return ADV_ARROW; YY_BREAK case 60: YY_RULE_SETUP -#line 329 "compilers/imcc/imcc.l" +#line 331 "compilers/imcc/imcc.l" return ADV_INVOCANT; YY_BREAK case 61: YY_RULE_SETUP -#line 330 "compilers/imcc/imcc.l" +#line 332 "compilers/imcc/imcc.l" return ADV_CALL_SIG; YY_BREAK case 62: YY_RULE_SETUP -#line 332 "compilers/imcc/imcc.l" +#line 334 "compilers/imcc/imcc.l" return NAMESPACE; YY_BREAK case 63: YY_RULE_SETUP -#line 333 "compilers/imcc/imcc.l" +#line 335 "compilers/imcc/imcc.l" return HLL; YY_BREAK case 64: YY_RULE_SETUP -#line 335 "compilers/imcc/imcc.l" +#line 337 "compilers/imcc/imcc.l" return LOCAL; YY_BREAK case 65: YY_RULE_SETUP -#line 336 "compilers/imcc/imcc.l" +#line 338 "compilers/imcc/imcc.l" return CONST; YY_BREAK case 66: YY_RULE_SETUP -#line 337 "compilers/imcc/imcc.l" +#line 339 "compilers/imcc/imcc.l" return GLOBAL_CONST; YY_BREAK case 67: YY_RULE_SETUP -#line 338 "compilers/imcc/imcc.l" +#line 340 "compilers/imcc/imcc.l" return PARAM; YY_BREAK case 68: YY_RULE_SETUP -#line 339 "compilers/imcc/imcc.l" +#line 341 "compilers/imcc/imcc.l" return GOTO; YY_BREAK case 69: YY_RULE_SETUP -#line 340 "compilers/imcc/imcc.l" +#line 342 "compilers/imcc/imcc.l" return IF; YY_BREAK case 70: YY_RULE_SETUP -#line 341 "compilers/imcc/imcc.l" +#line 343 "compilers/imcc/imcc.l" return UNLESS; YY_BREAK case 71: YY_RULE_SETUP -#line 342 "compilers/imcc/imcc.l" +#line 344 "compilers/imcc/imcc.l" return PNULL; YY_BREAK case 72: YY_RULE_SETUP -#line 343 "compilers/imcc/imcc.l" +#line 345 "compilers/imcc/imcc.l" return INTV; YY_BREAK case 73: YY_RULE_SETUP -#line 344 "compilers/imcc/imcc.l" +#line 346 "compilers/imcc/imcc.l" return FLOATV; YY_BREAK case 74: YY_RULE_SETUP -#line 346 "compilers/imcc/imcc.l" +#line 348 "compilers/imcc/imcc.l" return PMCV; YY_BREAK case 75: YY_RULE_SETUP -#line 347 "compilers/imcc/imcc.l" +#line 349 "compilers/imcc/imcc.l" return STRINGV; YY_BREAK case 76: YY_RULE_SETUP -#line 348 "compilers/imcc/imcc.l" +#line 350 "compilers/imcc/imcc.l" return SHIFT_LEFT; YY_BREAK case 77: YY_RULE_SETUP -#line 349 "compilers/imcc/imcc.l" +#line 351 "compilers/imcc/imcc.l" return SHIFT_RIGHT; YY_BREAK case 78: YY_RULE_SETUP -#line 350 "compilers/imcc/imcc.l" +#line 352 "compilers/imcc/imcc.l" return SHIFT_RIGHT_U; YY_BREAK case 79: YY_RULE_SETUP -#line 351 "compilers/imcc/imcc.l" +#line 353 "compilers/imcc/imcc.l" return LOG_AND; YY_BREAK case 80: YY_RULE_SETUP -#line 352 "compilers/imcc/imcc.l" +#line 354 "compilers/imcc/imcc.l" return LOG_OR; YY_BREAK case 81: YY_RULE_SETUP -#line 353 "compilers/imcc/imcc.l" +#line 355 "compilers/imcc/imcc.l" return LOG_XOR; YY_BREAK case 82: YY_RULE_SETUP -#line 354 "compilers/imcc/imcc.l" +#line 356 "compilers/imcc/imcc.l" return RELOP_LT; YY_BREAK case 83: YY_RULE_SETUP -#line 355 "compilers/imcc/imcc.l" +#line 357 "compilers/imcc/imcc.l" return RELOP_LTE; YY_BREAK case 84: YY_RULE_SETUP -#line 356 "compilers/imcc/imcc.l" +#line 358 "compilers/imcc/imcc.l" return RELOP_GT; YY_BREAK case 85: YY_RULE_SETUP -#line 357 "compilers/imcc/imcc.l" +#line 359 "compilers/imcc/imcc.l" return RELOP_GTE; YY_BREAK case 86: YY_RULE_SETUP -#line 358 "compilers/imcc/imcc.l" +#line 360 "compilers/imcc/imcc.l" return RELOP_EQ; YY_BREAK case 87: YY_RULE_SETUP -#line 359 "compilers/imcc/imcc.l" +#line 361 "compilers/imcc/imcc.l" return RELOP_NE; YY_BREAK case 88: YY_RULE_SETUP -#line 360 "compilers/imcc/imcc.l" +#line 362 "compilers/imcc/imcc.l" return POW; YY_BREAK case 89: YY_RULE_SETUP -#line 362 "compilers/imcc/imcc.l" +#line 364 "compilers/imcc/imcc.l" return CONCAT; YY_BREAK case 90: YY_RULE_SETUP -#line 363 "compilers/imcc/imcc.l" +#line 365 "compilers/imcc/imcc.l" return DOT; YY_BREAK case 91: YY_RULE_SETUP -#line 365 "compilers/imcc/imcc.l" +#line 367 "compilers/imcc/imcc.l" return PLUS_ASSIGN; YY_BREAK case 92: YY_RULE_SETUP -#line 366 "compilers/imcc/imcc.l" +#line 368 "compilers/imcc/imcc.l" return MINUS_ASSIGN; YY_BREAK case 93: YY_RULE_SETUP -#line 367 "compilers/imcc/imcc.l" +#line 369 "compilers/imcc/imcc.l" return MUL_ASSIGN; YY_BREAK case 94: YY_RULE_SETUP -#line 368 "compilers/imcc/imcc.l" +#line 370 "compilers/imcc/imcc.l" return DIV_ASSIGN; YY_BREAK case 95: YY_RULE_SETUP -#line 369 "compilers/imcc/imcc.l" +#line 371 "compilers/imcc/imcc.l" return MOD_ASSIGN; YY_BREAK case 96: YY_RULE_SETUP -#line 370 "compilers/imcc/imcc.l" +#line 372 "compilers/imcc/imcc.l" return FDIV; YY_BREAK case 97: YY_RULE_SETUP -#line 371 "compilers/imcc/imcc.l" +#line 373 "compilers/imcc/imcc.l" return FDIV_ASSIGN; YY_BREAK case 98: YY_RULE_SETUP -#line 372 "compilers/imcc/imcc.l" +#line 374 "compilers/imcc/imcc.l" return BAND_ASSIGN; YY_BREAK case 99: YY_RULE_SETUP -#line 373 "compilers/imcc/imcc.l" +#line 375 "compilers/imcc/imcc.l" return BOR_ASSIGN; YY_BREAK case 100: YY_RULE_SETUP -#line 374 "compilers/imcc/imcc.l" +#line 376 "compilers/imcc/imcc.l" return BXOR_ASSIGN; YY_BREAK case 101: YY_RULE_SETUP -#line 375 "compilers/imcc/imcc.l" +#line 377 "compilers/imcc/imcc.l" return SHR_ASSIGN; YY_BREAK case 102: YY_RULE_SETUP -#line 376 "compilers/imcc/imcc.l" +#line 378 "compilers/imcc/imcc.l" return SHL_ASSIGN; YY_BREAK case 103: YY_RULE_SETUP -#line 377 "compilers/imcc/imcc.l" +#line 379 "compilers/imcc/imcc.l" return SHR_U_ASSIGN; YY_BREAK case 104: YY_RULE_SETUP -#line 378 "compilers/imcc/imcc.l" +#line 380 "compilers/imcc/imcc.l" return CONCAT_ASSIGN; YY_BREAK case 105: YY_RULE_SETUP -#line 380 "compilers/imcc/imcc.l" +#line 382 "compilers/imcc/imcc.l" { char *macro_name = NULL; int start_cond = YY_START; @@ -2832,7 +2834,7 @@ YY_RULE_SETUP YY_BREAK case 106: YY_RULE_SETUP -#line 423 "compilers/imcc/imcc.l" +#line 425 "compilers/imcc/imcc.l" { /* the initial whitespace catcher misses this one */ SET_LINE_NUMBER; @@ -2841,7 +2843,7 @@ YY_RULE_SETUP YY_BREAK case 107: YY_RULE_SETUP -#line 429 "compilers/imcc/imcc.l" +#line 431 "compilers/imcc/imcc.l" { const int c = yylex(valp,yyscanner,imcc); STRING *filename; @@ -2858,7 +2860,7 @@ YY_RULE_SETUP YY_BREAK case 108: YY_RULE_SETUP -#line 443 "compilers/imcc/imcc.l" +#line 445 "compilers/imcc/imcc.l" { if (valp) { char *label; @@ -2883,7 +2885,7 @@ YY_RULE_SETUP YY_BREAK case 109: YY_RULE_SETUP -#line 465 "compilers/imcc/imcc.l" +#line 467 "compilers/imcc/imcc.l" { if (valp) { char *label; @@ -2906,12 +2908,12 @@ YY_RULE_SETUP YY_BREAK case 110: YY_RULE_SETUP -#line 485 "compilers/imcc/imcc.l" +#line 487 "compilers/imcc/imcc.l" return COMMA; YY_BREAK case 111: YY_RULE_SETUP -#line 487 "compilers/imcc/imcc.l" +#line 489 "compilers/imcc/imcc.l" { /* trim last ':' */ YYCHOP(); @@ -2924,7 +2926,7 @@ YY_RULE_SETUP YY_BREAK case 112: YY_RULE_SETUP -#line 497 "compilers/imcc/imcc.l" +#line 499 "compilers/imcc/imcc.l" { char * const macro_name = mem_sys_strndup(yytext + 1, yyleng - 1); int failed = expand_macro(imcc, macro_name, yyscanner); @@ -2937,32 +2939,32 @@ YY_RULE_SETUP YY_BREAK case 113: YY_RULE_SETUP -#line 509 "compilers/imcc/imcc.l" +#line 511 "compilers/imcc/imcc.l" DUP_AND_RET(valp, FLOATC); YY_BREAK case 114: YY_RULE_SETUP -#line 510 "compilers/imcc/imcc.l" +#line 512 "compilers/imcc/imcc.l" DUP_AND_RET(valp, INTC); YY_BREAK case 115: YY_RULE_SETUP -#line 511 "compilers/imcc/imcc.l" +#line 513 "compilers/imcc/imcc.l" DUP_AND_RET(valp, INTC); YY_BREAK case 116: YY_RULE_SETUP -#line 512 "compilers/imcc/imcc.l" +#line 514 "compilers/imcc/imcc.l" DUP_AND_RET(valp, INTC); YY_BREAK case 117: YY_RULE_SETUP -#line 513 "compilers/imcc/imcc.l" +#line 515 "compilers/imcc/imcc.l" DUP_AND_RET(valp, INTC); YY_BREAK case 118: YY_RULE_SETUP -#line 515 "compilers/imcc/imcc.l" +#line 517 "compilers/imcc/imcc.l" { valp->s = mem_sys_strndup(yytext, yyleng); @@ -2971,7 +2973,7 @@ YY_RULE_SETUP YY_BREAK case 119: YY_RULE_SETUP -#line 521 "compilers/imcc/imcc.l" +#line 523 "compilers/imcc/imcc.l" { macro_frame_t *frame; @@ -3002,7 +3004,7 @@ YY_RULE_SETUP YY_BREAK case 120: YY_RULE_SETUP -#line 549 "compilers/imcc/imcc.l" +#line 551 "compilers/imcc/imcc.l" { /* charset:"..." */ valp->s = mem_sys_strndup(yytext, yyleng); @@ -3013,7 +3015,7 @@ YY_RULE_SETUP YY_BREAK case 121: YY_RULE_SETUP -#line 557 "compilers/imcc/imcc.l" +#line 559 "compilers/imcc/imcc.l" { if (valp) (valp)->s = yytext; if (imcc->state->pasm_file) @@ -3024,7 +3026,7 @@ YY_RULE_SETUP YY_BREAK case 122: YY_RULE_SETUP -#line 565 "compilers/imcc/imcc.l" +#line 567 "compilers/imcc/imcc.l" { if (valp) (valp)->s = yytext; @@ -3036,7 +3038,7 @@ YY_RULE_SETUP YY_BREAK case 123: YY_RULE_SETUP -#line 574 "compilers/imcc/imcc.l" +#line 576 "compilers/imcc/imcc.l" { if (valp) (valp)->s = yytext; @@ -3048,7 +3050,7 @@ YY_RULE_SETUP YY_BREAK case 124: YY_RULE_SETUP -#line 583 "compilers/imcc/imcc.l" +#line 585 "compilers/imcc/imcc.l" { if (valp) (valp)->s = yytext; @@ -3060,7 +3062,7 @@ YY_RULE_SETUP YY_BREAK case 125: YY_RULE_SETUP -#line 592 "compilers/imcc/imcc.l" +#line 594 "compilers/imcc/imcc.l" { IMCC_fataly(imcc, EXCEPTION_SYNTAX_ERROR, "'%s' is not a valid register name", yytext); @@ -3068,7 +3070,7 @@ YY_RULE_SETUP YY_BREAK case 126: YY_RULE_SETUP -#line 597 "compilers/imcc/imcc.l" +#line 599 "compilers/imcc/imcc.l" { if (imcc->state->pasm_file == 0) IMCC_fataly(imcc, EXCEPTION_SYNTAX_ERROR, @@ -3082,24 +3084,24 @@ YY_RULE_SETUP YY_BREAK case 127: YY_RULE_SETUP -#line 609 "compilers/imcc/imcc.l" +#line 611 "compilers/imcc/imcc.l" { return handle_identifier(imcc, valp, yytext); } YY_BREAK case 128: YY_RULE_SETUP -#line 611 "compilers/imcc/imcc.l" +#line 613 "compilers/imcc/imcc.l" /* skip */; YY_BREAK case 129: YY_RULE_SETUP -#line 613 "compilers/imcc/imcc.l" +#line 615 "compilers/imcc/imcc.l" { /* catch all except for state macro */ return yytext[0]; } YY_BREAK case YY_STATE_EOF(emit): -#line 618 "compilers/imcc/imcc.l" +#line 620 "compilers/imcc/imcc.l" { BEGIN(INITIAL); @@ -3112,12 +3114,12 @@ case YY_STATE_EOF(emit): } YY_BREAK case YY_STATE_EOF(INITIAL): -#line 629 "compilers/imcc/imcc.l" +#line 631 "compilers/imcc/imcc.l" yyterminate(); YY_BREAK case 130: YY_RULE_SETUP -#line 631 "compilers/imcc/imcc.l" +#line 633 "compilers/imcc/imcc.l" { /* the initial whitespace catcher misses this one */ SET_LINE_NUMBER; @@ -3127,19 +3129,19 @@ YY_RULE_SETUP case 131: /* rule 131 can match eol */ YY_RULE_SETUP -#line 637 "compilers/imcc/imcc.l" +#line 639 "compilers/imcc/imcc.l" { DUP_AND_RET(valp, '\n'); } YY_BREAK case 132: YY_RULE_SETUP -#line 641 "compilers/imcc/imcc.l" +#line 643 "compilers/imcc/imcc.l" return LABEL; YY_BREAK case 133: YY_RULE_SETUP -#line 643 "compilers/imcc/imcc.l" +#line 645 "compilers/imcc/imcc.l" { if (yylex(valp,yyscanner,imcc) != LABEL) @@ -3166,7 +3168,7 @@ YY_RULE_SETUP YY_BREAK case 134: YY_RULE_SETUP -#line 667 "compilers/imcc/imcc.l" +#line 669 "compilers/imcc/imcc.l" { if (valp) { if (!imcc->cur_macro_name) { @@ -3197,44 +3199,44 @@ YY_RULE_SETUP YY_BREAK case 135: YY_RULE_SETUP -#line 695 "compilers/imcc/imcc.l" +#line 697 "compilers/imcc/imcc.l" DUP_AND_RET(valp, ' '); YY_BREAK case 136: YY_RULE_SETUP -#line 696 "compilers/imcc/imcc.l" +#line 698 "compilers/imcc/imcc.l" DUP_AND_RET(valp, REG); YY_BREAK case 137: YY_RULE_SETUP -#line 697 "compilers/imcc/imcc.l" +#line 699 "compilers/imcc/imcc.l" DUP_AND_RET(valp, REG); YY_BREAK case 138: YY_RULE_SETUP -#line 698 "compilers/imcc/imcc.l" +#line 700 "compilers/imcc/imcc.l" DUP_AND_RET(valp, IDENTIFIER); YY_BREAK case 139: YY_RULE_SETUP -#line 699 "compilers/imcc/imcc.l" +#line 701 "compilers/imcc/imcc.l" DUP_AND_RET(valp, MACRO); YY_BREAK case 140: YY_RULE_SETUP -#line 700 "compilers/imcc/imcc.l" +#line 702 "compilers/imcc/imcc.l" DUP_AND_RET(valp, yytext[0]); YY_BREAK case YY_STATE_EOF(macro): -#line 701 "compilers/imcc/imcc.l" +#line 703 "compilers/imcc/imcc.l" yyterminate(); YY_BREAK case 141: YY_RULE_SETUP -#line 703 "compilers/imcc/imcc.l" +#line 705 "compilers/imcc/imcc.l" ECHO; YY_BREAK -#line 3238 "compilers/imcc/imclexer.c" +#line 3240 "compilers/imcc/imclexer.c" case YY_STATE_EOF(pod): case YY_STATE_EOF(cmt1): case YY_STATE_EOF(cmt2): @@ -4446,7 +4448,7 @@ void yyfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 703 "compilers/imcc/imcc.l" +#line 705 "compilers/imcc/imcc.l" @@ -5110,7 +5112,7 @@ imcc_compile_buffer_safe(ARGMOD(imc_info_t *imcc), yyscan_t yyscanner, buffer = YY_CURRENT_BUFFER; file = imcc_setup_input(imcc, yyscanner, source, source_c, is_file); - emit_open(imcc); + emit_open(imcc, source); success = imcc_run_compilation(imcc, yyscanner); imcc_cleanup_input(imcc, file, source_c, is_file); diff --git a/compilers/imcc/instructions.c b/compilers/imcc/instructions.c index ccca95c9b8..743c6dd1e9 100644 --- a/compilers/imcc/instructions.c +++ b/compilers/imcc/instructions.c @@ -38,6 +38,17 @@ These functions operate over this array and its contents. /* HEADERIZER HFILE: compilers/imcc/instructions.h */ /* HEADERIZER BEGIN: static */ +/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ + +static int e_pasm_open(ARGMOD(imc_info_t * imcc), ARGIN(STRING *path)) + __attribute__nonnull__(1) + __attribute__nonnull__(2) + FUNC_MODIFIES(* imcc); + +#define ASSERT_ARGS_e_pasm_open __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ + PARROT_ASSERT_ARG(imcc) \ + , PARROT_ASSERT_ARG(path)) +/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ /* HEADERIZER END: static */ static const char types[] = "INPS"; @@ -551,7 +562,7 @@ free_ins(ARGMOD(Instruction *ins)) =item C -Print details of instruction ins in file fd. +Print details of instruction C into file fd. =cut @@ -650,26 +661,75 @@ ins_print(ARGMOD(imc_info_t * imcc), PIOHANDLE io, ARGIN(const Instruction *ins) return len; } -/* for debug */ -static PIOHANDLE output; +/* + +=item C + +=cut + +*/ + +static int +e_pasm_open(ARGMOD(imc_info_t * imcc), ARGIN(STRING *path)) +{ + ASSERT_ARGS(e_pasm_open) + const Parrot_Interp interp = imcc->interp; + PMC *handle = PMCNULL; + + Parrot_io_open(interp, handle, path, Parrot_str_new_constant(interp, "w")); + imcc->write_pasm = Parrot_io_get_os_handle(interp, handle); + if (!imcc->write_pasm) + Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR, + "Cannot open output file %Ss", path); + + return 1; +} /* -=item C +=item C -Opens the emitter function C of the given C. Passes -the C to the open function. +Opens the output file for writing, either C or C. =cut */ void -emit_open(ARGMOD(imc_info_t * imcc)) +emit_open(ARGMOD(imc_info_t * imcc), ARGIN(STRING *path)) { ASSERT_ARGS(emit_open) imcc->dont_optimize = 0; - e_pbc_open(imcc); + if (UNLIKELY(imcc->write_pasm)) + e_pasm_open(imcc, path); + else + e_pbc_open(imcc); +} + +/* + +=item C + +Writes a pasm line to global output fh, and prints DEBUG_PBC output to stderr. + +=cut + +*/ + +void +e_pasm_out(ARGMOD(imc_info_t * imcc), ARGIN(const char *fmt), ...) +{ + ASSERT_ARGS(e_pasm_out) + va_list ap; + + if (!(imcc->write_pasm || (DEBUG_PBC & imcc->debug))) + return; + va_start(ap, fmt); + if (imcc->write_pasm) + Parrot_io_pprintf(imcc->interp, imcc->write_pasm, fmt, ap); + if (DEBUG_PBC & imcc->debug) + imcc_vfprintf(imcc, Parrot_io_STDERR(imcc->interp), fmt, ap); + va_end(ap); } /* @@ -690,31 +750,47 @@ emit_flush(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(void *param), ASSERT_ARGS(emit_flush) Instruction *ins; - e_pbc_new_sub(imcc, param, unit); + if (UNLIKELY(imcc->write_pasm)) { + for (ins = unit->instructions; ins; ins = ins->next) { + IMCC_debug(imcc, DEBUG_IMC, "emit %d\n", ins); - for (ins = unit->instructions; ins; ins = ins->next) { - IMCC_debug(imcc, DEBUG_IMC, "emit %d\n", ins); - e_pbc_emit(imcc, param, unit, ins); + if ((ins->type & ITLABEL) || ! *ins->opname) + ins_print(imcc, imcc->write_pasm, ins); + else { + Parrot_io_pprintf(imcc->interp, imcc->write_pasm, "\t%s ", ins->opname); + ins_print(imcc, imcc->write_pasm, ins); + } + Parrot_io_pprintf(imcc->interp, imcc->write_pasm, "\n"); + } } + else { + e_pbc_new_sub(imcc, param, unit); + + for (ins = unit->instructions; ins; ins = ins->next) { + IMCC_debug(imcc, DEBUG_IMC, "emit %d\n", ins); + e_pbc_emit(imcc, param, unit, ins); + } - e_pbc_end_sub(imcc, param, unit); + e_pbc_end_sub(imcc, param, unit); + } } /* -=item C +=item C Closes the given emitter. +Fixup globals in pasm or pbc output. =cut */ void -emit_close(ARGMOD(imc_info_t *imcc), ARGIN_NULLOK(void *param)) +emit_close(ARGMOD(imc_info_t *imcc)) { ASSERT_ARGS(emit_close) - e_pbc_close(imcc, param); + e_pbc_close(imcc); } /* diff --git a/compilers/imcc/instructions.h b/compilers/imcc/instructions.h index 3cc3031fe3..4561416958 100644 --- a/compilers/imcc/instructions.h +++ b/compilers/imcc/instructions.h @@ -102,7 +102,12 @@ Instruction * delete_ins(ARGMOD(IMC_Unit *unit), ARGMOD(Instruction *ins)) FUNC_MODIFIES(*unit) FUNC_MODIFIES(*ins); -void emit_close(ARGMOD(imc_info_t *imcc), ARGIN_NULLOK(void *param)) +void e_pasm_out(ARGMOD(imc_info_t * imcc), ARGIN(const char *fmt), ...) + __attribute__nonnull__(1) + __attribute__nonnull__(2) + FUNC_MODIFIES(* imcc); + +void emit_close(ARGMOD(imc_info_t *imcc)) __attribute__nonnull__(1) FUNC_MODIFIES(*imcc); @@ -114,8 +119,9 @@ void emit_flush( __attribute__nonnull__(3) FUNC_MODIFIES(* imcc); -void emit_open(ARGMOD(imc_info_t * imcc)) +void emit_open(ARGMOD(imc_info_t * imcc), ARGIN(STRING *path)) __attribute__nonnull__(1) + __attribute__nonnull__(2) FUNC_MODIFIES(* imcc); PARROT_CAN_RETURN_NULL @@ -213,13 +219,17 @@ void subst_ins( #define ASSERT_ARGS_delete_ins __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(unit) \ , PARROT_ASSERT_ARG(ins)) +#define ASSERT_ARGS_e_pasm_out __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ + PARROT_ASSERT_ARG(imcc) \ + , PARROT_ASSERT_ARG(fmt)) #define ASSERT_ARGS_emit_close __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(imcc)) #define ASSERT_ARGS_emit_flush __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(imcc) \ , PARROT_ASSERT_ARG(unit)) #define ASSERT_ARGS_emit_open __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(imcc)) + PARROT_ASSERT_ARG(imcc) \ + , PARROT_ASSERT_ARG(path)) #define ASSERT_ARGS_emitb __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(imcc)) #define ASSERT_ARGS_free_ins __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ diff --git a/compilers/imcc/main.c b/compilers/imcc/main.c index c3f186175c..910629ffd4 100644 --- a/compilers/imcc/main.c +++ b/compilers/imcc/main.c @@ -575,6 +575,32 @@ imcc_run_compilation_internal(ARGMOD(imc_info_t *imcc), ARGIN(STRING *source), /* +=item C + +Public interface to initialize imcc->write_pasm with -1 or 0. + +=cut + +*/ + +PARROT_EXPORT +void +imcc_set_to_pasm(ARGMOD(imc_info_t *imcc), ARGIN(Parrot_Int to_pasm)) +{ + ASSERT_ARGS(imcc_set_to_pasm) + + if (imcc->write_pasm) { + if (!to_pasm) + imcc->write_pasm = 0; + /* else already set to some filehandle */ + } + else { + imcc->write_pasm = to_pasm ? -1 : 0; + } +} + +/* + =item C Prepare IMCC for a reentrant compile. Push a new imc_info_t structure onto the diff --git a/compilers/imcc/pbc.c b/compilers/imcc/pbc.c index b698fda81e..030764c38a 100644 --- a/compilers/imcc/pbc.c +++ b/compilers/imcc/pbc.c @@ -2246,7 +2246,7 @@ e_pbc_end_sub(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(IMC_Unit *unit pragma = ins->symregs[0]->pcc_sub->pragma; - if (pragma & P_IMMEDIATE && (pragma & P_ANON)) { + if ((pragma & P_IMMEDIATE) && (pragma & P_ANON)) { /* clear global symbols temporarily -- TT #1324, for example */ imcc_globals *g = imcc->globals; SymHash ghash; @@ -2256,7 +2256,9 @@ e_pbc_end_sub(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(IMC_Unit *unit memmove(&ghash, &imcc->ghash, sizeof (SymHash)); memset(&imcc->ghash, 0, sizeof (SymHash)); - IMCC_debug(imcc, DEBUG_PBC, "immediate sub '%s'", ins->symregs[0]->name); + if (imcc->verbose) + IMCC_debug(imcc, DEBUG_PBC, ".pcc_sub :anon :immediate '%s':\n", + ins->symregs[0]->name); /* TODO: Don't use this function, it is deprecated (TT #2140). We need to find a better mechanism to do this. */ PackFile_fixup_subs(imcc->interp, PBC_IMMEDIATE, NULL); @@ -2376,8 +2378,9 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u const size_t code_size = get_code_size(imcc, unit, &ins_size); const size_t bytes = (old_size + code_size) * sizeof (opcode_t); - IMCC_debug(imcc, DEBUG_PBC, "code_size(ops) %d old_size %d\n", - code_size, old_size); + if ((imcc->debug & (DEBUG_PBC|DEBUG_PARROT)) == (DEBUG_PBC|DEBUG_PARROT)) + IMCC_debug(imcc, DEBUG_PBC, "# code_size(ops) %d old_size %d\n", + code_size, old_size); constant_folding(imcc, unit, interp_code); store_sub_size(imcc, code_size, ins_size); @@ -2421,6 +2424,11 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u add_const_pmc_sub(imcc, ins->symregs[0], imcc->npc, imcc->npc); } + /* PBC dump a label if it's not a sub. i.e. pasm output */ + else if ((ins->type & ITLABEL) && *ins->symregs[0]->name != '_') { + if (!(ins->symregs[0] && ins->symregs[0]->pcc_sub)) + e_pasm_out(imcc, "%s:\n", ins->symregs[0]->name); + } if (ins->opname && strcmp(ins->opname, ".annotate") == 0) { /* It's an annotation. */ @@ -2441,6 +2449,7 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u default: IMCC_fatal(imcc, 1, "e_pbc_emit:invalid type for annotation value\n"); } + e_pasm_out(imcc, ".annotate %s\n", ins->symregs[0]->color); PackFile_Annotations_add_entry(imcc->interp, interp_code->annotations, imcc->pc - interp_code->base.data, ins->symregs[0]->color, annotation_type, ins->symregs[1]->color); @@ -2474,7 +2483,8 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u if (!op_info) IMCC_fatal(imcc, 1, "e_emit_pbc: empty op %d 0x%x\n", imcc->npc, ins); - IMCC_debug(imcc, DEBUG_PBC, "%d %s", imcc->npc, op_info->full_name); + if (imcc->verbose) + IMCC_debug(imcc, DEBUG_PBC, "%d %s", imcc->npc, op_info->full_name); /* Start generating the bytecode */ *(imcc->pc)++ = bytecode_map_op(imcc, op_info); @@ -2509,7 +2519,8 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u r = r->reg; *(imcc->pc)++ = (opcode_t) r->color; - IMCC_debug(imcc, DEBUG_PBC, " %d", r->color); + if (imcc->verbose) + IMCC_debug(imcc, DEBUG_PBC, " %d", r->color); break; case PARROT_ARG_KC: r = ins->symregs[i]; @@ -2519,7 +2530,8 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u } else *(imcc->pc)++ = build_key(imcc, r, interp_code); - IMCC_debug(imcc, DEBUG_PBC, " %d", imcc->pc[-1]); + if (imcc->verbose) + IMCC_debug(imcc, DEBUG_PBC, " %d", imcc->pc[-1]); break; default: IMCC_fatal(imcc, 1, "e_pbc_emit:unknown argtype in parrot op\n"); @@ -2541,7 +2553,8 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u if (r->type & VT_CONSTP) r = r->reg; *(imcc->pc)++ = (opcode_t) r->color; - IMCC_debug(imcc, DEBUG_PBC, " %d", r->color); + if (imcc->verbose) + IMCC_debug(imcc, DEBUG_PBC, " %d", r->color); } } @@ -2556,16 +2569,16 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u /* -=item C +=item C -Closes this PMC unit. +Closes this PMC unit, i.e. fixup the globals. =cut */ void -e_pbc_close(ARGMOD(imc_info_t * imcc), SHIM(void *param)) +e_pbc_close(ARGMOD(imc_info_t * imcc)) { ASSERT_ARGS(e_pbc_close) fixup_globals(imcc); diff --git a/compilers/imcc/pbc.h b/compilers/imcc/pbc.h index 5d48632f53..3ad8baccc2 100644 --- a/compilers/imcc/pbc.h +++ b/compilers/imcc/pbc.h @@ -8,7 +8,7 @@ /* HEADERIZER BEGIN: compilers/imcc/pbc.c */ /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ -void e_pbc_close(ARGMOD(imc_info_t * imcc), void *param) +void e_pbc_close(ARGMOD(imc_info_t * imcc)) __attribute__nonnull__(1) FUNC_MODIFIES(* imcc); diff --git a/compilers/imcc/reg_alloc.c b/compilers/imcc/reg_alloc.c index 029e69e90c..4a84de5550 100644 --- a/compilers/imcc/reg_alloc.c +++ b/compilers/imcc/reg_alloc.c @@ -184,6 +184,32 @@ imc_reg_alloc(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(IMC_Unit *unit)) else function = "(not a sub)"; + if (unit->instructions->symreg_count + && (imcc->verbose || imcc->debug & (DEBUG_IMC|DEBUG_PBC))) + { + Instruction *ins = unit->instructions; + int pragma = ins->symregs[0]->pcc_sub->pragma; + + IMCC_info(imcc, 0, ".pcc_sub "); + if (pragma & P_IMMEDIATE) + IMCC_info(imcc, 0, ":immediate "); + if (pragma & P_ANON) + IMCC_info(imcc, 0, ":anon "); + if (pragma & P_MAIN) + IMCC_info(imcc, 0, ":main "); + if (pragma & P_VTABLE) + IMCC_info(imcc, 0, ":vtable "); + if (pragma & P_METHOD) + IMCC_info(imcc, 0, ":method "); + if (pragma & P_LOAD) + IMCC_info(imcc, 0, ":load "); + if (pragma & P_POSTCOMP) + IMCC_info(imcc, 0, ":postcomp "); + if (pragma & P_INIT) + IMCC_info(imcc, 0, ":init "); + IMCC_info(imcc, 0, "%s:\n", function); + } + IMCC_debug(imcc, DEBUG_IMC, "\n------------------------\n"); IMCC_debug(imcc, DEBUG_IMC, "processing sub %s\n", function); IMCC_debug(imcc, DEBUG_IMC, "------------------------\n\n"); @@ -229,7 +255,7 @@ imc_reg_alloc(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(IMC_Unit *unit)) dump_instructions(imcc, unit); done: - if (imcc->verbose || (imcc->debug & DEBUG_IMC)) + if (imcc->verbose || imcc->debug & DEBUG_IMC) print_stat(imcc, unit); else make_stat(unit, NULL, unit->n_regs_used); @@ -262,14 +288,15 @@ free_reglist(ARGMOD(IMC_Unit *unit)) =item C some statistics about register usage -printed with --verbose --verbose +printed with --verbose or -d80 =cut */ static void -make_stat(ARGMOD(IMC_Unit *unit), ARGMOD_NULLOK(int *sets), ARGMOD_NULLOK(int *cols)) +make_stat(ARGMOD(IMC_Unit *unit), + ARGMOD_NULLOK(int *sets), ARGMOD_NULLOK(int *cols)) { ASSERT_ARGS(make_stat) /* register usage summary */ @@ -316,7 +343,7 @@ make_stat(ARGMOD(IMC_Unit *unit), ARGMOD_NULLOK(int *sets), ARGMOD_NULLOK(int *c =item C -registes usage of .pir +initialize register usage counters =cut @@ -354,15 +381,10 @@ print_stat(ARGMOD(imc_info_t * imcc), ARGMOD(IMC_Unit *unit)) ASSERT_ARGS(print_stat) int sets[4] = {0, 0, 0, 0}; - const char * const function = - unit->instructions->symreg_count - ? unit->instructions->symregs[0]->name - : "(not a function)"; - make_stat(unit, sets, unit->n_regs_used); + IMCC_info(imcc, 1, - "sub %s:\n\tregisters in .pir:\t I%d, N%d, S%d, P%d\n", - function, + "\tregisters in .pir:\t I%d, N%d, S%d, P%d\n", unit->n_vars_used[0], unit->n_vars_used[1], unit->n_vars_used[2], unit->n_vars_used[3]); IMCC_info(imcc, 1, diff --git a/config/gen/config_h/feature_h.in b/config/gen/config_h/feature_h.in index f84e892a2c..2b2c7d2f37 100644 --- a/config/gen/config_h/feature_h.in +++ b/config/gen/config_h/feature_h.in @@ -230,6 +230,7 @@ for my $name (split / /,$alignof) { END_PRINT } } +print OUT <<'END_PRINT'; /* from config/auto/expect */ END_PRINT diff --git a/frontend/parrot/main.c b/frontend/parrot/main.c index 9539fa76ce..9f7930d500 100644 --- a/frontend/parrot/main.c +++ b/frontend/parrot/main.c @@ -35,6 +35,7 @@ struct init_args_t { Parrot_Int trace; Parrot_Int execute_packfile; Parrot_Int write_packfile; + Parrot_Int write_pasm; Parrot_Int have_pbc_file; Parrot_Int have_pasm_file; Parrot_Int turn_gc_off; @@ -755,6 +756,7 @@ parseflags(Parrot_PMC interp, int argc, ARGIN(const char *argv[]), args->run_core_name = "fast"; args->write_packfile = 0; + args->write_pasm = 0; args->execute_packfile = 1; args->have_pbc_file = 0; args->have_pasm_file = 0; @@ -854,6 +856,13 @@ parseflags(Parrot_PMC interp, int argc, ARGIN(const char *argv[]), outfile = opt.opt_arg; if (!Parrot_api_string_import(interp, opt.opt_arg, &args->outfile)) show_last_error_and_exit(interp); + { + const char * const ext = strrchr(outfile, '.'); + if (ext && ((strcmp(ext, ".pasm") == 0) || (strcmp(ext, ".pir") == 0))) { + args->write_packfile = 0; + args->write_pasm = 1; + } + } break; case 'r': args->write_packfile = 1; diff --git a/frontend/parrot2/main.c b/frontend/parrot2/main.c index 2db59979ee..520a51f213 100644 --- a/frontend/parrot2/main.c +++ b/frontend/parrot2/main.c @@ -691,6 +691,8 @@ parseflags(Parrot_PMC interp, int argc, ARGIN(const char *argv[]), case 'o': pargs[nargs++] = "-o"; pargs[nargs++] = opt.opt_arg; + if (strcmp(opt.opt_arg, ".pasm") == 0) + args->preprocess_only = 1; break; case 'r': pargs[nargs++] = "-r"; diff --git a/include/imcc/embed.h b/include/imcc/embed.h index 38e2b4a427..becb6b5880 100644 --- a/include/imcc/embed.h +++ b/include/imcc/embed.h @@ -72,6 +72,12 @@ void imcc_set_optimization_level( __attribute__nonnull__(2) FUNC_MODIFIES(*imcc); +PARROT_EXPORT +void imcc_set_to_pasm(ARGMOD(imc_info_t *imcc), ARGIN(Parrot_Int to_pasm)) + __attribute__nonnull__(1) + __attribute__nonnull__(2) + FUNC_MODIFIES(*imcc); + PARROT_EXPORT void imcc_set_verbosity(ARGMOD(imc_info_t *imcc), INTVAL verbose) __attribute__nonnull__(1) @@ -114,6 +120,9 @@ void imcc_destroy(ARGFREE(imc_info_t * imcc)); #define ASSERT_ARGS_imcc_set_optimization_level __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(imcc) \ , PARROT_ASSERT_ARG(opts)) +#define ASSERT_ARGS_imcc_set_to_pasm __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ + PARROT_ASSERT_ARG(imcc) \ + , PARROT_ASSERT_ARG(to_pasm)) #define ASSERT_ARGS_imcc_set_verbosity __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(imcc)) #define ASSERT_ARGS_exit_reentrant_compile __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ diff --git a/lib/Parrot/Test.pm b/lib/Parrot/Test.pm index c3e247fdc1..ede52d8344 100644 --- a/lib/Parrot/Test.pm +++ b/lib/Parrot/Test.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2012, Parrot Foundation. +# Copyright (C) 2004-2014, Parrot Foundation. =head1 NAME @@ -198,6 +198,53 @@ non-zero exit code. Runs the Parrot bytecode and passes the test if the exit code equals $exit_code, fails the test otherwise. +=item C + +Compile the Parrot Intermediate Representation and generate Parrot Assembler Code +with -O1 or dependant on the test filename. Pass if the generated PASM is $expected. + +=item C + +Compile the Parrot Intermediate Representation and generate Parrot Assembler Code +with -O1 or dependant on the test filename. +Pass if the generated PASM matches $expected. + +=item C + +Compile the Parrot Intermediate Representation and generate Parrot Assembler Code +with -O1 or dependant on the test filename. +Pass unless the generated PASM is $expected. + +=item C + +Compile the Parrot Intermediate Representation and generate Parrot Assembler Code +with -O1. Pass if the generated PASM is $expected. + +=item C + +Compile the Parrot Intermediate Representation and generate Parrot Assembler Code +with -O1. Pass if the generated PASM matches $expected. + +=item C + +Compile the Parrot Intermediate Representation and generate Parrot Assembler Code +with -O1. Pass unless the generated PASM is $expected. + +=item C + +Compile the Parrot Intermediate Representation and generate Parrot Assembler Code +with -O2. Pass if the generated PASM is $expected. + +=item C + +Compile the Parrot Intermediate Representation and generate Parrot Assembler Code +with -O2. Pass if the generated PASM matches $expected. + +=item C + +Compile the Parrot Intermediate Representation and generate Parrot Assembler Code +with -O2. Pass unless the generated PASM is $expected. + =item C Compiles and runs the C code, passing the test if a string comparison of the @@ -856,7 +903,118 @@ sub _generate_test_functions { create_sub($package, $func, $test_sub); } - ##### 2: Language test map ##### + ##### 2: PIR-to-PASM test map ##### + my %pir_2_pasm_test_map = ( + pir_2_pasm_is => 'is_eq', + pir_2_pasm_isnt => 'isnt_eq', + pir_2_pasm_like => 'like', + pir_2_pasm_unlike => 'unlike', + + pir_2o1_pasm_is => 'is_eq', + pir_2o1_pasm_isnt => 'isnt_eq', + pir_2o1_pasm_like => 'like', + pir_2o1_pasm_unlike => 'unlike', + + pir_2o2_pasm_is => 'is_eq', + pir_2o2_pasm_isnt => 'isnt_eq', + pir_2o2_pasm_like => 'like', + pir_2o2_pasm_unlike => 'unlike', + ); + + foreach my $func ( keys %pir_2_pasm_test_map ) { + push @EXPORT, $func; + no strict 'refs'; + + my $test_sub = sub { + local *__ANON__ = $func; + my ( $code, $expected, $desc, $opt, %extra ); + if ($func =~ /^pir_2o1_/) { + ( $code, $expected, $desc, %extra ) = @_; + $opt = '-O1'; + } + elsif ($func =~ /^pir_2o2_/) { + ( $code, $expected, $desc, %extra ) = @_; + $opt = '-O2'; + } + elsif ($func =~ /^pir_2_/) { + ( $code, $expected, $desc, %extra ) = @_; + } + else { + die "invalid $func"; + } + + # set up default description + unless ($desc) { + ( undef, my $file, my $line ) = caller(); + $desc = "($file line $line)"; + } + + # $test_no will be part of temporary file + my $test_no = $builder->current_test() + 1; + + # Name of the file with test code. + my $code_f = File::Spec->rel2abs( per_test( '.pir', $test_no ) ); + my $code_basef = basename($code_f); + + # output file + my $out_f = per_test( '.pasm', $test_no ); + + my ($cmd, $pass); + + # mangle windows line endings + convert_line_endings($expected); + + if ($func =~ /^pir_2_/) { + $opt = $code_basef =~ m!opt(.)! ? "-O$1" : "-O1"; + } + my $args = $ENV{TEST_PROG_ARGS} || ''; + $args .= " $opt -d1000 -o $out_f.tmp"; + $args =~ s/--run-exec//; + $cmd = qq{$parrot $args "$code_f"}; + write_code_to_file( $code, $code_f ); + my $exit_code = run_command + ( + $cmd, + CD => $path_to_parrot, + STDOUT => "/dev/null", + STDERR => $out_f + ); + + my $meth = $pir_2_pasm_test_map{$func}; + my $real_output = slurp_file($out_f); + { + + # The parrot open '--outfile=file.pasm' seems to create unnecessary whitespace + $real_output =~ s/^\s*$//gm; + $real_output =~ s/[\t ]+/ /gm; + $real_output =~ s/\s+$//gm; + $real_output =~ s/^\s+//gm; + + $expected =~ s/^\s+//gm; + $expected =~ s/\s+$//gm; + } + + # set a todo-item for Test::Builder to find + my $call_pkg = $builder->exported_to() || ''; + + local *{ $call_pkg . '::TODO' } = ## no critic Variables::ProhibitConditionalDeclarations + \$extra{todo} + if defined $extra{todo}; + + $pass = $builder->$meth( $real_output, $expected, $opt.' '.$desc ); + $builder->diag("'$cmd' failed with exit code $exit_code") + if $exit_code and not $pass; + + _unlink_or_retain( $out_f ); + _unlink_or_retain( $out_f.".tmp" ); + + return $pass; + }; + + create_sub($package, $func, $test_sub); + } + + ##### 3: Language test map ##### my %builtin_language_prefix = ( PIR_IMCC => 'pir', PASM_IMCC => 'pasm', @@ -920,11 +1078,11 @@ sub _generate_test_functions { create_sub($package, $func, $test_sub); } - ##### 3: Example test map ##### + ##### 4: Example test map ##### my %example_test_map = ( - example_output_is => 'language_output_is', - example_output_like => 'language_output_like', - example_output_isnt => 'language_output_isnt', + example_output_is => 'language_output_is', + example_output_like => 'language_output_like', + example_output_isnt => 'language_output_isnt', example_error_output_is => 'language_error_output_is', example_error_output_isnt => 'language_error_output_is', example_error_output_like => 'language_error_output_like', @@ -965,7 +1123,7 @@ sub _generate_test_functions { create_sub($package, $func, $test_sub); } - ##### 4: C test map ##### + ##### 5: C test map ##### my %c_test_map = ( c_output_is => 'is_eq', c_output_isnt => 'isnt_eq', diff --git a/src/pmc/imccompiler.pmc b/src/pmc/imccompiler.pmc index 027be6a19c..c17ce69f3f 100644 --- a/src/pmc/imccompiler.pmc +++ b/src/pmc/imccompiler.pmc @@ -1,5 +1,5 @@ /* -Copyright (C) 2011-2012, Parrot Foundation. +Copyright (C) 2011-2014, Parrot Foundation. =head1 NAME @@ -50,6 +50,7 @@ A compiler object to wrap IMCC pmclass IMCCompiler auto_attrs provides HLLCompiler provide invokable { ATTR void *imcc_info; ATTR INTVAL is_pasm; /* 0 = PIR, 1 = PASM */ + ATTR INTVAL to_pasm; /* 0 = PBC */ ATTR INTVAL current_eval; VTABLE void init() { @@ -69,6 +70,7 @@ pmclass IMCCompiler auto_attrs provides HLLCompiler provide invokable { Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "IMCCompiler: Must have type 0 (PIR) or 1 (PASM)"); attrs->is_pasm = is_pasm; + attrs->to_pasm = 0; attrs->imcc_info = (void*) imcc_new(INTERP); attrs->current_eval = 0; } @@ -244,6 +246,13 @@ pmclass IMCCompiler auto_attrs provides HLLCompiler provide invokable { /*METHOD get_exports(PMC *module) { }*/ + + METHOD void set_to_pasm(INTVAL to_pasm) { + Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); + imc_info_t * const imcc = (imc_info_t*)attrs->imcc_info; + attrs->to_pasm = to_pasm; + imcc_set_to_pasm(imcc, to_pasm); + } } /* diff --git a/t/compilers/imcc/imcpasm/cfg.t b/t/compilers/imcc/imcpasm/cfg.t new file mode 100644 index 0000000000..8f5ae54290 --- /dev/null +++ b/t/compilers/imcc/imcpasm/cfg.t @@ -0,0 +1,41 @@ +#!perl +# Copyright (C) 2005, 2014 Parrot Foundation. + +use strict; +use warnings; +use lib qw( . lib ../lib ../../lib ); +use Parrot::Test tests => 2; + +pir_2o1_pasm_is( <<'CODE', <<'OUT1', "unreachable 1" ); +.sub _test + print "ok\n" + end + noop + noop +.end +CODE +.pcc_sub _test: +print "ok\n" +end +OUT1 + +pir_2o1_pasm_is( <<'CODE', <<'OUT1', "unreachable 3" ); +.sub _test + goto L + print "ok\n" +L: + end + noop + noop +.end +CODE +.pcc_sub _test: +end +OUT1 + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: diff --git a/t/compilers/imcc/imcpasm/opt0.t b/t/compilers/imcc/imcpasm/opt0.t new file mode 100644 index 0000000000..6c5a1cfc7d --- /dev/null +++ b/t/compilers/imcc/imcpasm/opt0.t @@ -0,0 +1,67 @@ +#!perl +# Copyright (C) 2005,2014 Parrot Foundation. +# $Id$ + +use strict; +use warnings; +use lib qw( . lib ../lib ../../lib ); +use Parrot::Test tests => 4; + +# these tests are run with -O0 by TestCompiler and show +# generated PASM code for various optimizations at level 0 + +pir_2_pasm_is( <<'CODE', <<'OUT', "sub_n_ic_n" ); +.sub _ :anon + sub $N0, 2, $N1 + div $N0, 2, $N1 +.end +CODE +.pcc_sub :anon _: + sub N0, 2, N1 + div N0, 2, N1 + set_returns + returncc +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "added return - end" ); +.sub _test + noop + end +.end +CODE +.pcc_sub _test: + noop + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "added return - exit" ); +.sub _test + noop + exit 0 +.end +CODE +.pcc_sub _test: + noop + exit 0 +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "added return - nil" ); +.sub _test + noop +.end +CODE +.pcc_sub _test: + noop + set_returns + returncc +OUT + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: diff --git a/t/compilers/imcc/imcpasm/opt1.t b/t/compilers/imcc/imcpasm/opt1.t new file mode 100644 index 0000000000..cd268d184d --- /dev/null +++ b/t/compilers/imcc/imcpasm/opt1.t @@ -0,0 +1,1054 @@ +#!perl +# Copyright (C) 2005,2014, Parrot Foundation. + +use strict; +use warnings; +use lib qw( . lib ../lib ../../lib ); +use Parrot::Test tests => 77; +use Parrot::Config; + +my $output; + +# these tests are run with -O1 by TestCompiler and show +# generated PASM code for various optimizations at level 1 + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "branch opt if" ); +.sub _main + if $I0 goto L1 + branch L2 +L1: noop +L2: end +.end +CODE +.pcc_sub _main: +unless I0, L2 +noop +L2: +end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "branch opt gt" ); +.sub _main + if $I0 > 1 goto L1 + branch L2 +L1: noop +L2: end +.end +CODE +.pcc_sub _main: +le I0, 1, L2 +noop +L2: +end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "branch reorg" ); +.sub _main + if $I0 > 1 goto L1 + noop + branch L2 +L1: + noop + goto L3 +L2: + noop + print "ok\n" +L3: + end +.end +CODE +.pcc_sub _main: +lt 1, I0, L1 +noop +noop +print "ok\n" +L3: +end +L1: +noop +branch L3 +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "unreachable 3" ); +.sub _test + goto L + print "ok\n" +L: + end + noop + noop +.end +CODE +.pcc_sub _test: +end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "unused local label" ); +.sub _main + branch L2 +L2: end +.end +CODE +.pcc_sub _main: +end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "unused global label" ); +.sub _main + branch _L2 +_L2: end +.end +CODE +.pcc_sub _main: +end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "branch_branch and dead code" ); +.sub _test + goto l1 +l2: + noop + print "ok\n" + end +l1: + goto l3 +l4: + eq $I1, 0, l2 +l3: + goto l2 +.end +CODE +.pcc_sub _test: +noop +print "ok\n" +end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "branch_branch to self" ); +.sub _test +L1: + branch L1 + print "never\n" + end +.end +CODE +.pcc_sub _test: +L1: +branch L1 +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "branch_branch from conditional" ); +.sub _test + if $I0 goto l3 +l2: + print "ok\n" +l1: + goto l2 +l3: + goto l1 +.end +CODE +.pcc_sub _test: +if I0, l2 +l2: +print "ok\n" +branch l2 +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "branch_cond_loop" ); +.sub _test + $I0 = 10 +start: + unless $I0 goto end + print "looping\n" + dec $I0 + branch start +end: + print "ok\n" + branch start +.end +CODE +.pcc_sub _test: + set I0, 10 +start: + unless I0, end +start_post1: + print "looping\n" + dec I0 + if I0, start_post1 +end: + print "ok\n" + branch start +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "branch_cond_loop multi condition" ); +.sub _test + $I0 = 10 + branch entry +start: + dec $I0 +entry: + unless $I0 goto end + print "looping\n" + branch start +end: + print "ok\n" + branch start +.end +CODE +.pcc_sub _test: + set I0, 10 + branch entry +start: + dec I0 +entry: + unless I0, end +start_post1: + print "looping\n" + dec I0 + if I0, start_post1 +end: + print "ok\n" + branch start +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant add" ); +.sub _main + add $I0, 10, 15 + add $N0, 10.0, 15.0 + end +.end +CODE +.pcc_sub _main: + set I0, 25 + set N0, 25 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant sub" ); +.sub _main + sub $I0, 10, 15 + sub $N0, 10.0, 15.0 + end +.end +CODE +.pcc_sub _main: + set I0, -5 + set N0, -5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant mul" ); +.sub _main + mul $I0, 10, 15 + mul $N0, 10.0, 15.0 + end +.end +CODE +.pcc_sub _main: + set I0, 150 + set N0, 150 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant div" ); +.sub _main + div $I0, 10, 5 + div $N0, 10.0, 5.0 + end +.end +CODE +.pcc_sub _main: + div I0, 10, 5 + div N0, 10.0, 5.0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant mod" ); +.sub _main + mod $I0, 33, 10 + mod $N0, 33.0, 10.0 + end +.end +CODE +.pcc_sub _main: + set I0, 3 + set N0, 3 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant eq taken" ); +.sub _main + eq 10, 10, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant eq not taken" ); +.sub _main + eq 10, 20, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant eq taken" ); +.sub _main + eq 10.0, 10.0, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant eq not taken" ); +.sub _main + eq 10.0, 20.0, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant eq taken" ); +.sub _main + eq "xy", "xy", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant eq not taken" ); +.sub _main + eq "ab", "ba", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant ne taken" ); +.sub _main + ne 10, 20, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant ne not taken" ); +.sub _main + ne 10, 10, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant gt taken" ); +.sub _main + gt "xy", "ap", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant gt not taken" ); +.sub _main + gt "ab", "ba", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant ge taken" ); +.sub _main + ge "xy", "xy", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant ge not taken" ); +.sub _main + gt "ab", "ba", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant lt taken" ); +.sub _main + lt "xx", "xy", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant lt not taken" ); +.sub _main + lt "ba", "ba", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant le taken" ); +.sub _main + le "xy", "xy", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant le not taken" ); +.sub _main + le "bb", "ba", L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant if taken" ); +.sub _main + if 10, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant if not taken" ); +.sub _main + if 0, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant unless taken" ); +.sub _main + unless 0, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant unless not taken" ); +.sub _main + unless 1, L1 + set $I0, 5 +L1:end +.end +CODE +.pcc_sub _main: + set I0, 5 + end +OUT + +############################## + pir_2_pasm_is( <<'CODE', <<'OUT', "constant mix add" ); +.sub _main + add $N0, 10.0, 15 + end +.end +CODE +.pcc_sub _main: + set N0, 25 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant unary abs" ); +.sub _main + abs $I0, -10 + end +.end +CODE +.pcc_sub _main: + set I0, 10 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant set" ); +.sub _main + set $N0, 5 + end +.end +CODE +.pcc_sub _main: + set N0, 5 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength set I, 0" ); +.sub _main + set $I0, 0 + end +.end +CODE +.pcc_sub _main: + null I0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength set N, 0" ); +.sub _main + set $N0, 0.0 + end +.end +CODE +.pcc_sub _main: + null N0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "no strength set N, -0" ); +.sub _main + set $N0, -0.0 + end +.end +CODE +.pcc_sub _main: + set N0, -0.0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength add I, 0" ); +.sub _main + add $I0, 0 + end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength add I, I, 0" ); +.sub _main + add $I0, $I1, 0 + end +.end +CODE +.pcc_sub _main: + set I0, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength add I, 0, I" ); +.sub _main + add $I0, 0, $I1 + end +.end +CODE +.pcc_sub _main: + set I0, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength add I, 1" ); +.sub _main + add $I0, 1 + end +.end +CODE +.pcc_sub _main: + inc I0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength add N, 0, N" ); +.sub _main + add $N0, 0.0, $N1 + end +.end +CODE +.pcc_sub _main: + set N0, N1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength add N, 1" ); +.sub _main + add $N0, 1 + end +.end +CODE +.pcc_sub _main: + inc N0 + end +OUT + +############################### +pir_2_pasm_is( <<'CODE', <<'OUT', "strength sub I, 0" ); +.sub _main + sub $I0, 0 + end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength sub I, I, 0" ); +.sub _main + sub $I0, $I1, 0 + end +.end +CODE +.pcc_sub _main: + set I0, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength sub I, 0, I" ); +.sub _main + sub $I0, 0, $I1 + end +.end +CODE +.pcc_sub _main: + sub I0, 0, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength sub I, 1" ); +.sub _main + sub $I0, 1 + end +.end +CODE +.pcc_sub _main: + dec I0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength sub N, N, 0" ); +.sub _main + sub $N0, $N1, 0 + end +.end +CODE +.pcc_sub _main: + set N0, N1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength sub N, 1" ); +.sub _main + sub $N0, 1 + end +.end +CODE +.pcc_sub _main: + dec N0 + end +OUT + +############################# +pir_2_pasm_is( <<'CODE', <<'OUT', "strength mul I, 0" ); +.sub _main + mul $I0, 0 + end +.end +CODE +.pcc_sub _main: + null I0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength mul I, I, 0" ); +.sub _main + mul $I0, $I1, 0 + end +.end +CODE +.pcc_sub _main: + null I0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength mul I, 0, I" ); +.sub _main + mul $I0, 0, $I1 + end +.end +CODE +.pcc_sub _main: + null I0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength mul N, 0, N" ); +.sub _main + mul $N0, 0.0, $N1 + end +.end +CODE +.pcc_sub _main: + null N0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength mul I, 1" ); +.sub _main + mul $I0, 1 + end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength mul I, I, 1" ); +.sub _main + mul $I0, $I1, 1 + end +.end +CODE +.pcc_sub _main: + set I0, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength mul I, 1, I" ); +.sub _main + mul $I0, 1, $I1 + end +.end +CODE +.pcc_sub _main: + set I0, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength mul N, 1, N" ); +.sub _main + mul $N0, 1.0, $N1 + end +.end +CODE +.pcc_sub _main: + set N0, N1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength div I, 1" ); +.sub _main + div $I0, 1 + end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength div I, I, 1" ); +.sub _main + div $I0, $I1, 1 + end +.end +CODE +.pcc_sub _main: + set I0, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength div I, 1, I" ); +.sub _main + div $I0, 1, $I1 + end +.end +CODE +.pcc_sub _main: + div I0, 1, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength div N, 1" ); +.sub _main + div $N0, 1 + end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength div N, N, 1" ); +.sub _main + div $N0, $N1, 1 + end +.end +CODE +.pcc_sub _main: + set N0, N1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength fdiv I, 1" ); +.sub _main + fdiv $I0, 1 + end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength fdiv I, I, 1" ); +.sub _main + fdiv $I0, $I1, 1 + end +.end +CODE +.pcc_sub _main: + set I0, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength fdiv I, 1, I" ); +.sub _main + fdiv $I0, 1, $I1 + end +.end +CODE +.pcc_sub _main: + fdiv I0, 1, I1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength fdiv N, 1" ); +.sub _main + fdiv $N0, 1 + end +.end +CODE +.pcc_sub _main: + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "strength fdiv N, N, 1" ); +.sub _main + fdiv $N0, $N1, 1 + end +.end +CODE +.pcc_sub _main: + set N0, N1 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "multiple const syms" ); +.sub _main + set $I0, 0 + set $I1, 1 + add $N0, -1.0, 2 + add $N0, -1.0, 1 + add $N0, 1.0, 0 + end +.end +CODE +.pcc_sub _main: + null I0 + set I1, 1 + set N0, 1 + null N0 + set N0, 1 + end +OUT + +############################## + +$output = $PConfig{numvalsize} == 8 + ? '/^.pcc_sub _main: +set N0, 1\.6e\+0?22 +end$/ +' : '/^ +.pcc_sub _main: +set N0, 16000000000000000000000 +end$/ +'; + +pir_2_pasm_like( <<'CODE', $output, "constant add big nums" ); +.sub _main + add $N0, 10.0e20, 15.0e21 + end +.end +CODE + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant concat" ); +.sub _main + concat $S0, "Parrot ", "rocks" + end +.end +CODE +.pcc_sub _main: + set S0, "Parrot rocks" + end +OUT + +pir_2_pasm_like( <<'CODE', <<'OUT', "segv - last ins changed" ); +.sub main :main + func() +.end +.sub func + $I0 += 1 +.end +CODE +/\.pcc_sub func: +inc I\d +set_returns +returncc/ +OUT + +pir_2_pasm_like( <<'CODE', <<'OUT', "segv - last ins deleted" ); +.sub main :main + func() +.end +.sub func + $I0 += 0 +.end +CODE +/\.pcc_sub func: +set_returns +returncc/ +OUT + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: diff --git a/t/compilers/imcc/imcpasm/opt2.t b/t/compilers/imcc/imcpasm/opt2.t new file mode 100644 index 0000000000..b42ae20c65 --- /dev/null +++ b/t/compilers/imcc/imcpasm/opt2.t @@ -0,0 +1,144 @@ +#!perl +# Copyright (C) 2005,2014, Parrot Foundation. + +use strict; +use warnings; +use lib qw( . lib ../lib ../../lib ); +use Parrot::Test tests => 6; + +# these tests are run with -O2 by TestCompiler and show +# generated PASM code for various optimizations at level 2 + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "used once lhs" ); +.sub _main + $I1 = 1 + $I2 = 2 + print $I2 + end +.end +CODE +.pcc_sub _main: + print 2 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant propogation and resulting dead code" ); +.sub _main + set $I0, 5 +loop: + set $I1, 2 + add $I0, $I1 + lt $I0, 20, loop + print $I0 + end +.end +CODE +.pcc_sub _main: + set I0, 5 +loop: + add I0, 2 + lt I0, 20, loop + print I0 + end +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "don't move constant past a label" ); +.sub _main + set $I1, 10 + set $I0, 5 + lt $I1, 20, nxt +add: + add $I0, $I1, $I1 + print $I0 +nxt: + set $I1, 20 + branch add +.end +CODE +.pcc_sub _main: + set I1, 10 + set I0, 5 + branch nxt +add: + add I0, I1, I1 + print I0 +nxt: + set I1, 20 + branch add +OUT + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant prop and null_i" ); +.sub _main + null $I0 + add $I1, $I0, 5 + print $I1 +.end +CODE +.pcc_sub _main: + print 5 + set_returns + returncc +OUT + +############################## +#SKIP: { +# skip( "loop opt disabled for now", 1 ); + + pir_2_pasm_is( <<'CODE', <<'OUT', "remove invariant from loop" ); +.sub _main + set $I0, 5 +loop: + set $I1, 2 + add $I0, $I1 + lt $I0, 20, loop +next: + print $I0 + add $I0, $I1 + print $I0 + lt $I1, 4, next + end +.end +CODE +.pcc_sub _main: + set I0, 5 + set I1, 2 +loop: + add I0, 2 + lt I0, 20, loop +next: + print I0 + add I0, I1 + print I0 + lt I1, 4, next + end +OUT +#} + +############################## +pir_2_pasm_is( <<'CODE', <<'OUT', "constant prop repeated" ); +.sub _main + .local int a + .local int b + .local int sum + a = 10 + b = 5 + sum = a + b + print sum + end +.end +CODE +.pcc_sub _main: + print 15 + end +OUT + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: diff --git a/t/compilers/imcc/imcpasm/optc.t b/t/compilers/imcc/imcpasm/optc.t new file mode 100644 index 0000000000..5c29a10ded --- /dev/null +++ b/t/compilers/imcc/imcpasm/optc.t @@ -0,0 +1,413 @@ +#!perl +# Copyright (C) 2005-2010, Parrot Foundation. + +use strict; +use warnings; +use lib qw( . lib ../lib ../../lib ); +use Parrot::Test tests => 42; +use Test::More; + +# these tests are run with -Oc by TestCompiler and show +# generated PASM code for call optimization + +############################## + +pir_output_is( <<'CODE', <<'OUT', "karl trivial test" ); +.sub _main + $I1 = foo(10) + print $I1 + print "\n" +.end +.sub foo + .param int i + if i goto recurse + .return (0) + +recurse: + $I1= i - 1 + .tailcall foo($I1) +.end +CODE +0 +OUT + +pir_output_is( <<'CODE', <<'OUT', "karl spot bug 1" ); +.sub _main + foo(0, 1, 2, 3,4) +.end +.sub foo + .param int done + .param int i + .param int j + .param int k + .param int l + + unless done goto tc + print "i " + print i + print " j " + print j + print " k " + print k + print " l " + print l + + print "\n" + end +tc: + .tailcall foo(1, 9, i, j,k) +.end +CODE +i 9 j 1 k 2 l 3 +OUT + +pir_output_is( <<'CODE', <<'OUT', "karl tailcall 3 args" ); +.sub _main + foo(0, 1, 2, 3) +.end +.sub foo + .param int done + .param int i + .param int j + .param int k + unless done goto tc + print "i " + print i + print " j " + print j + print " k " + print k + print "\n" + end +tc: + .tailcall foo(1, j, i, i) +.end +CODE +i 2 j 1 k 1 +OUT + +pir_output_is( <<'CODE', <<'OUT', "cycle no exit 1" ); +.sub _main + foo(0, 1, 2, 3, 4, 5) +.end +.sub foo + .param int done + .param int i + .param int j + .param int k + .param int l + .param int m + + + unless done goto tc + print "i " + print i + print " j " + print j + print " k " + print k + print " l " + print l + print " m " + print m + + print "\n" + end +tc: + .tailcall foo(1, m,i,j,k,l) +.end +CODE +i 5 j 1 k 2 l 3 m 4 +OUT + +pir_output_is( <<'CODE', <<'OUT', "cycle no exit 2" ); +.sub _main + foo(0, 1, 2, 3, 4, 5) +.end +.sub foo + .param int done + .param int i + .param int j + .param int k + .param int l + .param int m + + + unless done goto tc + print "i " + print i + print " j " + print j + print " k " + print k + print " l " + print l + print " m " + print m + + print "\n" + end +tc: + .tailcall foo(1, m,l,j,i,k) +.end +CODE +i 5 j 4 k 2 l 1 m 3 +OUT + +pir_output_is( <<'CODE', <<'OUT', "2 unconnected cycles no exit " ); +.sub _main + foo(0, 1, 2, 3, 4, 5) +.end +.sub foo + .param int done + .param int i + .param int j + .param int k + .param int l + .param int m + + + unless done goto tc + print "i " + print i + print " j " + print j + print " k " + print k + print " l " + print l + print " m " + print m + + print "\n" + end +tc: + .tailcall foo(1, k,m,i,j,l) +.end +CODE +i 3 j 5 k 1 l 2 m 4 +OUT + +pir_output_is( <<'CODE', <<'OUT', "cycle with exit 1" ); +.sub _main + foo(0, 1, 2, 3, 4, 5) +.end +.sub foo + .param int done + .param int i + .param int j + .param int k + .param int l + .param int m + + + unless done goto tc + print "i " + print i + print " j " + print j + print " k " + print k + print " l " + print l + print " m " + print m + + print "\n" + end +tc: + .tailcall foo(1, j,i,j,i,j) +.end +CODE +i 2 j 1 k 2 l 1 m 2 +OUT + +pir_2_pasm_like( <<'CODE', <<'OUT', "in P param" ); +.sub _main + $P0 = new 'Undef' + $P0 = 42 + foo($P0) + noop + end +.end +.sub foo + .param pmc a + print a +.end +CODE +/\.sub _main + new (P\d), 'Undef' + set \1, 42 +@pcc_sub_call_\d: + set_args + set_p_pc (P\d+), foo + invokecc \2 + get_results + noop + end +\.end +\.sub foo + get_params + print P0 + set_returns + returncc +\.end/ +OUT + +pir_2_pasm_like( <<'CODE', <<'OUT', "tailcall 2" ); +.sub _main + foo(1, 2) +.end +.sub foo + .param int i + .param int j + .tailcall foo(j, i) +.end +CODE +/ set I(\d), I(\d) + set I\2, I(\d) + set I\3, I\1/ +OUT + +pir_output_is( <<'CODE', <<'OUT', "tailcall 3 args" ); +.sub _main + foo(0, 1, 2, 3) +.end +.sub foo + .param int done + .param int i + .param int j + .param int k + unless done goto tc + print "i " + print i + print " j " + print j + print " k " + print k + print "\n" + end +tc: + .tailcall foo(1, i, k, j) +.end +CODE +i 1 j 3 k 2 +OUT + +my @array = ( 'i', 'j', 'k' ); +my @b; +my_permute( sub { push @b, "@_" }, @array ); +my $x; +my $y; +foreach $x (@b) { + $x =~ tr/ /,/; + $y = $x; + $y =~ tr/ijk/123/; + pir_output_is( <<"CODE", <<"OUT", "tailcall 3 args $x" ); +.sub _main + foo(0, 1, 2, 3) +.end +.sub foo + .param int done + .param int i + .param int j + .param int k + unless done goto tc + print i + print "," + print j + print "," + print k + print "\\n" + end +tc: + .tailcall foo(1, $x ) +.end +CODE +$y +OUT +} +undef @b; + +@array = ( 'i', 'j', 'k', 'l' ); +my_permute( sub { push @b, "@_" }, @array ); +foreach $x (@b) { + $x =~ tr/ /,/; + $y = $x; + $y =~ tr/ijkl/1234/; + pir_output_is( <<"CODE", <<"OUT", "tailcall 4 args $x" ); +.sub _main + foo(0, 1, 2, 3, 4) +.end +.sub foo + .param int done + .param int i + .param int j + .param int k + .param int l + unless done goto tc + print i + print "," + print j + print "," + print k + print "," + print l + print "\\n" + end +tc: + .tailcall foo(1, $x ) +.end +CODE +$y +OUT +} + +undef @b; + +@array = ( 'i', 'j' ); +my_permute( sub { push @b, "@_" }, @array ); +foreach $x (@b) { + $x =~ tr/ /,/; + $y = $x; + $y =~ tr/ij/12/; + pir_output_is( <<"CODE", <<"OUT", "tailcall 2 args $x" ); +.sub _main + foo(0, 1, 2) +.end +.sub foo + .param int done + .param int i + .param int j + unless done goto tc + print i + print "," + print j + print "\\n" + end +tc: + .tailcall foo(1, $x ) +.end +CODE +$y +OUT +} + +sub my_permute { + my $code = shift; + my @idx = 0 .. $#_; + while ( $code->( @_[@idx] ) ) { + my $p = $#idx; + --$p while $idx[ $p - 1 ] > $idx[$p]; + my $q = $p or return; + push @idx, reverse splice @idx, $p; + ++$q while $idx[ $p - 1 ] > $idx[$q]; + @idx[ $p - 1, $q ] = @idx[ $q, $p - 1 ]; + } +} +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: diff --git a/t/compilers/imcc/imcpasm/pcc.t b/t/compilers/imcc/imcpasm/pcc.t new file mode 100644 index 0000000000..bd37932f09 --- /dev/null +++ b/t/compilers/imcc/imcpasm/pcc.t @@ -0,0 +1,26 @@ +#!perl +# Copyright (C) 2005,2014 Parrot Foundation. + +use strict; +use warnings; +use lib qw( . lib ../lib ../../lib ); +use Parrot::Test tests => 1; + +pir_2o1_pasm_is( <<'CODE', <<'OUT', 'end in :main' ); +.sub _main :main + noop +.end +CODE +.pcc_sub :main _main: + noop + set_returns + returncc +OUT + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: +