From bc8496bd7db8b897cd168b11e7866b68e2fffe8f Mon Sep 17 00:00:00 2001 From: Reini Urban Date: Tue, 4 Mar 2014 12:38:45 -0600 Subject: [PATCH] re-add PASM output to imcc, re-add imcpasm tests one new IMCCompiler api method: set_to_pasm remove static output in imcc/instructions.c detect .pasm -o outfile extension add and fix old t/compilers/imcc/imcpasm/*.t tests and the pir_2*_ Parrot::Test methods change Parrot::Test pir_2_pasm method to use -d1000, which is equivalent to pasm output, just to stderr. use new LIKELY/UNLIKELY macros --- .gitignore | 1 + compilers/imcc/debug.c | 30 +- compilers/imcc/imc.c | 2 +- compilers/imcc/imc.h | 2 +- compilers/imcc/imcc.l | 16 +- compilers/imcc/imclexer.c | 316 ++++----- compilers/imcc/instructions.c | 111 +++- compilers/imcc/instructions.h | 16 +- compilers/imcc/main.c | 26 + compilers/imcc/pbc.c | 34 +- compilers/imcc/pbc.h | 2 +- compilers/imcc/reg_alloc.c | 44 +- config/gen/config_h/feature_h.in | 1 + frontend/parrot/main.c | 9 + frontend/parrot2/main.c | 2 + include/imcc/embed.h | 7 + lib/Parrot/Test.pm | 172 ++++- src/pmc/imccompiler.pmc | 9 + t/compilers/imcc/imcpasm/cfg.t | 41 ++ t/compilers/imcc/imcpasm/opt0.t | 67 ++ t/compilers/imcc/imcpasm/opt1.t | 1054 ++++++++++++++++++++++++++++++ t/compilers/imcc/imcpasm/opt2.t | 144 ++++ t/compilers/imcc/imcpasm/optc.t | 413 ++++++++++++ t/compilers/imcc/imcpasm/pcc.t | 26 + 24 files changed, 2325 insertions(+), 220 deletions(-) create mode 100644 t/compilers/imcc/imcpasm/cfg.t create mode 100644 t/compilers/imcc/imcpasm/opt0.t create mode 100644 t/compilers/imcc/imcpasm/opt1.t create mode 100644 t/compilers/imcc/imcpasm/opt2.t create mode 100644 t/compilers/imcc/imcpasm/optc.t create mode 100644 t/compilers/imcc/imcpasm/pcc.t diff --git a/.gitignore b/.gitignore index 7978f970a3..a3be6052d5 100644 --- a/.gitignore +++ b/.gitignore @@ -396,6 +396,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 0953bb24d0..ac5147528a 100644 --- a/compilers/imcc/debug.c +++ b/compilers/imcc/debug.c @@ -259,12 +259,28 @@ IMCC_debug_ins(ARGMOD(imc_info_t *imcc), int level, ARGIN(const Instruction *ins { ASSERT_ARGS(IMCC_debug_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%lx %s ", PTR2ULONG(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 } /* @@ -283,14 +299,14 @@ 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]; @@ -303,11 +319,11 @@ dump_instructions(ARGMOD(imc_info_t * imcc), ARGIN(const IMC_Unit *unit)) 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/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 0e742f6da6..cd44b599d1 100644 --- a/compilers/imcc/imc.h +++ b/compilers/imcc/imc.h @@ -461,12 +461,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 e3e039c1a0..0e69900143 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'; } @@ -1364,7 +1366,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 1cc1970da2..b273eb54b2 100644 --- a/compilers/imcc/imclexer.c +++ b/compilers/imcc/imclexer.c @@ -1768,6 +1768,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') @@ -1790,7 +1792,7 @@ static int handle_identifier(ARGMOD(imc_info_t *imcc), YYSTYPE *valp, ARGIN(cons } while (0) #define YY_INPUT(buf, result, max_size) \ - (result) = Parrot_io_internal_read((Interp *)yyextra->interp, (PIOHANDLE)yyin, (buf), (max_size)) + (result) = Parrot_io_internal_read(yyextra->interp, (PIOHANDLE)yyin, (buf), (max_size)) @@ -1802,7 +1804,7 @@ static int handle_identifier(ARGMOD(imc_info_t *imcc), YYSTYPE *valp, ARGIN(cons -#line 1806 "compilers/imcc/imclexer.c" +#line 1808 "compilers/imcc/imclexer.c" #define INITIAL 0 #define emit 1 @@ -2078,11 +2080,11 @@ YY_DECL } { -#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); } @@ -2097,7 +2099,7 @@ YY_DECL return 0; } -#line 2101 "compilers/imcc/imclexer.c" +#line 2103 "compilers/imcc/imclexer.c" while ( 1 ) /* loops until end-of-file is reached */ { @@ -2165,13 +2167,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); @@ -2181,7 +2183,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 */ @@ -2196,7 +2198,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? */ @@ -2237,7 +2239,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; @@ -2253,7 +2255,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); @@ -2261,7 +2263,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); @@ -2272,7 +2274,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); } @@ -2280,19 +2282,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); } @@ -2300,14 +2302,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'; } @@ -2315,7 +2317,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; @@ -2324,7 +2326,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; @@ -2334,7 +2336,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; @@ -2343,458 +2345,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; @@ -2840,7 +2842,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; @@ -2849,7 +2851,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; @@ -2866,7 +2868,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; @@ -2891,7 +2893,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; @@ -2914,12 +2916,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(); @@ -2932,7 +2934,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); @@ -2945,32 +2947,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); @@ -2979,7 +2981,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; @@ -3010,7 +3012,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); @@ -3021,7 +3023,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) @@ -3032,7 +3034,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; @@ -3044,7 +3046,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; @@ -3056,7 +3058,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; @@ -3068,7 +3070,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); @@ -3076,7 +3078,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, @@ -3090,24 +3092,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); @@ -3120,12 +3122,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; @@ -3135,19 +3137,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) @@ -3174,7 +3176,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) { @@ -3205,44 +3207,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 3246 "compilers/imcc/imclexer.c" +#line 3248 "compilers/imcc/imclexer.c" case YY_STATE_EOF(pod): case YY_STATE_EOF(cmt1): case YY_STATE_EOF(cmt2): @@ -4456,7 +4458,7 @@ void yyfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 702 "compilers/imcc/imcc.l" +#line 704 "compilers/imcc/imcc.l" @@ -5119,7 +5121,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 b50e418ad4..69bf626488 100644 --- a/compilers/imcc/instructions.c +++ b/compilers/imcc/instructions.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2010, Parrot Foundation. + * Copyright (C) 2002-2015, Parrot Foundation. */ #include @@ -38,8 +38,21 @@ 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"; + /* =item C -Print details of instruction ins in file fd. +Print details of instruction C into file fd. =cut @@ -650,21 +663,73 @@ ins_print(ARGMOD(imc_info_t * imcc), PIOHANDLE io, ARGIN(const Instruction *ins) /* -=item C +=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; -Opens the emitter function C of the given C. Passes -the C to the open function. + 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 + +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); } /* @@ -685,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 231e00fa99..ce2a0b00de 100644 --- a/compilers/imcc/main.c +++ b/compilers/imcc/main.c @@ -572,6 +572,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), 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 c368d2cdac..8ac546b1e4 100644 --- a/compilers/imcc/pbc.c +++ b/compilers/imcc/pbc.c @@ -2270,7 +2270,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; @@ -2280,7 +2280,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); @@ -2400,8 +2402,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); @@ -2445,6 +2448,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. */ @@ -2465,6 +2473,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); @@ -2498,7 +2507,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); @@ -2533,7 +2543,8 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u r = r->reg; *(imcc->pc)++ = 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]; @@ -2543,7 +2554,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"); @@ -2566,6 +2578,8 @@ e_pbc_emit(ARGMOD(imc_info_t * imcc), SHIM(void *param), ARGIN(const IMC_Unit *u r = r->reg; *(imcc->pc)++ = r->color; IMCC_debug(imcc, DEBUG_PBC, " %d", r->color); + if (imcc->verbose) + IMCC_debug(imcc, DEBUG_PBC, " %d", r->color); } } @@ -2580,16 +2594,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 4ee924636e..8f4fbefb19 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 2cc2233c51..4a8e04e459 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; @@ -779,6 +780,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; @@ -878,6 +880,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 0d24d97a9b..3b7f4f758b 100644 --- a/frontend/parrot2/main.c +++ b/frontend/parrot2/main.c @@ -686,6 +686,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..57f31ec2cb 100644 --- a/include/imcc/embed.h +++ b/include/imcc/embed.h @@ -72,6 +72,11 @@ void imcc_set_optimization_level( __attribute__nonnull__(2) FUNC_MODIFIES(*imcc); +PARROT_EXPORT +void imcc_set_to_pasm(ARGMOD(imc_info_t *imcc), Parrot_Int to_pasm) + __attribute__nonnull__(1) + FUNC_MODIFIES(*imcc); + PARROT_EXPORT void imcc_set_verbosity(ARGMOD(imc_info_t *imcc), INTVAL verbose) __attribute__nonnull__(1) @@ -114,6 +119,8 @@ 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)) #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 cf9ce97499..6ee13bebcd 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 @@ -883,7 +930,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', @@ -947,11 +1105,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', @@ -992,7 +1150,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 22e3c4dbd8..92ead22101 100644 --- a/src/pmc/imccompiler.pmc +++ b/src/pmc/imccompiler.pmc @@ -50,6 +50,7 @@ A compiler object to wrap IMCC, the internal PIR and PASM compiler. 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() :no_wb { @@ -69,6 +70,7 @@ pmclass IMCCompiler auto_attrs provides HLLCompiler provide invokable { Parrot_ex_throw_from_c_noargs(INTERP, 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) :no_wb { }*/ + + 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: +