2 /*--------------------------------------------------------------------+
4 |--------------------------------------------------------------------|
6 |--------------------------------------------------------------------|
7 | First version: 03/04/2012 |
8 +--------------------------------------------------------------------+
10 +--------------------------------------------------------------------------+
11 | / __)( ) /__\ ( \/ ) |
12 | ( (__ )(__ /(__)\ \ / Chunky Loop Alteration wizardrY |
13 | \___)(____)(__)(__)(__) |
14 +--------------------------------------------------------------------------+
15 | Copyright (C) 2012 University of Paris-Sud |
17 | This library is free software; you can redistribute it and/or modify it |
18 | under the terms of the GNU Lesser General Public License as published by |
19 | the Free Software Foundation; either version 2.1 of the License, or |
20 | (at your option) any later version. |
22 | This library is distributed in the hope that it will be useful but |
23 | WITHOUT ANY WARRANTY; without even the implied warranty of |
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser |
25 | General Public License for more details. |
27 | You should have received a copy of the GNU Lesser General Public License |
28 | along with this software; if not, write to the Free Software Foundation, |
29 | Inc., 51 Franklin Street, Fifth Floor, |
30 | Boston, MA 02110-1301 USA |
32 | Clay, the Chunky Loop Alteration wizardrY |
33 | Written by Joel Poudroux, joel.poudroux@u-psud.fr |
34 +--------------------------------------------------------------------------*/
44 #include <osl/statement.h>
45 #include <osl/vector.h>
47 #include <clay/clay.h>
48 #include <clay/macros.h>
49 #include <clay/array.h>
50 #include <clay/list.h>
51 #include <clay/transformation.h>
52 #include <clay/stack.h>
53 #include <clay/data.h>
54 #include <clay/errors.h>
55 #include <clay/functions.h>
56 #include <clay/ident.h>
61 int clay_yy_scan_string
(char*);
62 extern
FILE* clay_yyin
;
63 void yy_scan_string
(char*);
64 extern
int clay_yylineno
;
66 // Scanner declarations
67 extern
void clay_scanner_free
();
68 extern
void clay_scanner_initialize
();
71 osl_scop_p clay_parser_scop
;
73 // Command line options
74 clay_options_p clay_parser_options
;
76 // Arrays are allocated differently
79 // The script is a stack system execution
80 clay_stack_t clay_parser_stack
;
82 // Current data wich will be pushed on the stack
83 clay_data_t clay_parser_current
;
85 // For the moment only 26 variables are availables (a-z)
86 clay_data_p clay_parser_vars
[26] = {NULL
};
88 // Current nb args of a clay function
91 // Function call level, for now we can't do this f(g())
92 // we have to use a temp variable
95 // Save the index in the stack on which data are unref
96 // it's use to get the data of variables
97 // when the function is finish the data will not to be to freed
98 clay_array_p clay_parser_unref
;
100 // Authorized functions in Clay (defined in functions.c)
101 extern
const clay_prototype_t functions
[];
104 void clay_parser_exec_function
(char *name
);
105 void clay_parser_print_error
(int);
108 %name
-prefix
"clay_yy"
111 %
union { char *sval
; }
113 %token
<ival
> INTEGER
115 %token
<sval
> IDENT_FUNCTION
116 %token
<sval
> IDENT_FUNCTION_NO_ARGS
134 if
(strlen
($1) > 1 ||
137 clay_parser_print_error
(CLAY_ERROR_UNK_VAR
);
139 int id
= (int)$1[0] - 'a';
140 if
(clay_parser_vars
[id
] != NULL
)
141 clay_data_free
(clay_parser_vars
[id
]);
143 clay_data_p tmp
= clay_stack_pop
(&clay_parser_stack
);
145 // if the type of expr is a ref (a variable), we need to
146 // dupplicate the data
147 // otherwise, we just put an invalid type on the stack
148 // to not free the allocated data
150 if
(tmp
->type
== REF_T
) {
151 if
(tmp
->data.obj
== NULL
)
152 clay_parser_print_error
(CLAY_ERROR_VAR_NULL
);
154 clay_parser_vars
[id
] = clay_data_clone
(tmp
->data.obj
);
157 clay_parser_vars
[id
] = clay_data_malloc
(tmp
->type
);
158 clay_parser_vars
[id
]->data
= tmp
->data
;
162 clay_stack_clear
(&clay_parser_stack
);
170 clay_stack_clear
(&clay_parser_stack
);
176 IDENT_FUNCTION_NO_ARGS
179 clay_parser_print_error
(CLAY_ERROR_CANT_CALL_SUBFUNC
);
184 if
(strcmp
($1, "break") == 0) {
189 clay_parser_exec_function
($1);
196 clay_parser_print_error
(CLAY_ERROR_CANT_CALL_SUBFUNC
);
203 clay_parser_exec_function
($1);
210 if
(strlen
($1) > 1 ||
213 clay_parser_print_error
(CLAY_ERROR_UNK_VAR
);
215 int id
= (int)$1[0] - 'a';
216 if
(clay_parser_vars
[id
] == NULL
)
217 clay_parser_print_error
(CLAY_ERROR_VAR_NULL
);
219 clay_parser_current.type
= REF_T
;
220 clay_parser_current.data.obj
= clay_parser_vars
[id
];
222 clay_stack_push
(&clay_parser_stack
, &clay_parser_current
);
229 clay_parser_current.type
= INTEGER_T
;
230 clay_parser_current.data.integer
= $1;
231 clay_stack_push
(&clay_parser_stack
, &clay_parser_current
);
234 |
// string (can contains only variable name)
237 clay_parser_current.type
= STRING_T
;
238 clay_parser_current.data.obj
= $2;
239 clay_stack_push
(&clay_parser_stack
, &clay_parser_current
);
246 clay_parser_current.type
= LIST_T
;
247 clay_list_p l
= clay_list_malloc
();
248 clay_parser_current.data.obj
= l
;
249 clay_list_add
(l
, clay_array_malloc
());
255 clay_stack_push
(&clay_parser_stack
, &clay_parser_current
);
261 clay_parser_current.type
= ARRAY_T
;
262 clay_parser_current.data.obj
= clay_array_malloc
();
267 clay_stack_push
(&clay_parser_stack
, &clay_parser_current
);
273 args
',' expr
{ nb_args
++; }
274 | expr
{ nb_args
++; }
281 clay_list_add
(clay_parser_current.data.obj
, clay_array_malloc
());
290 list_of_integer
',' INTEGER
293 clay_list_p l
= clay_parser_current.data.obj
;
294 clay_array_add
(l
->data
[l
->size
-1], $3);
296 clay_array_p a
= clay_parser_current.data.obj
;
297 clay_array_add
(a
, $3);
304 clay_list_p l
= clay_parser_current.data.obj
;
305 clay_array_add
(l
->data
[l
->size
-1], $1);
307 clay_array_p a
= clay_parser_current.data.obj
;
308 clay_array_add
(a
, $1);
318 * clay_yyerror function
320 int clay_yyerror
(void) {
321 fprintf
(stderr
,"[Clay] Error: syntax on line %d, maybe you forgot a `;'\n",
328 * clay_parser_clear_vars function
330 void clay_parser_free_vars
() {
333 for
(i
= 0 ; i
< 26 ; i
++)
334 if
(clay_parser_vars
[i
])
335 clay_data_free
(clay_parser_vars
[i
]);
340 * clay_parser_file function:
342 * \param[in] input Input file of the script
345 void clay_parser_file
(osl_scop_p scop
, FILE *input
, clay_options_p options
) {
346 clay_parser_scop
= scop
; // the scop is not NULL
347 clay_parser_options
= options
;
349 clay_parser_unref
= clay_array_malloc
();
350 clay_stack_init
(&clay_parser_stack
);
353 clay_scanner_initialize
();
358 clay_parser_free_vars
();
359 clay_array_free
(clay_parser_unref
);
364 * clay_parser_string function:
366 * \param[in] input Input string
369 void clay_parser_string
(osl_scop_p scop
, char *input
, clay_options_p options
) {
370 clay_parser_scop
= scop
; // the scop is not NULL
371 clay_parser_options
= options
;
373 clay_parser_unref
= clay_array_malloc
();
374 clay_stack_init
(&clay_parser_stack
);
376 clay_yy_scan_string
(input
);
381 clay_parser_free_vars
();
382 clay_array_free
(clay_parser_unref
);
387 * clay_parser_exec_function:
388 * \param[in] name function name
390 void clay_parser_exec_function
(char *name
) {
393 int top
= clay_parser_stack.sp
;
398 // search the function name
400 while
(i
< CLAY_FUNCTIONS_TOTAL
) {
401 if
(strcmp
(functions
[i
].name
, name
) == 0)
407 if
(i
== CLAY_FUNCTIONS_TOTAL
) {
408 // check if an alias exists
409 if
(strcmp
(name
, "fission") == 0) {
410 i
= CLAY_FUNCTION_SPLIT
;
411 } else if
(strcmp
(name
, "distribute") == 0) {
412 i
= CLAY_FUNCTION_SPLIT
;
413 } else if
(strcmp
(name
, "merge") == 0) {
414 i
= CLAY_FUNCTION_FUSE
;
415 } else
{ // Undefined function
416 fprintf
(stderr
, "[Clay] Error: line %d, unknown function `%s'\n",
417 clay_yylineno
, name
);
418 exit
(CLAY_ERROR_UNKNOWN_FUNCTION
);
422 // Different number of parameters
424 if
(nb_args
!= functions
[i
].argc
) {
426 "[Clay] Error: line %d, `%s' takes %d arguments\n"
427 "[Clay] prototype is: %s\n",
428 clay_yylineno
, name
, functions
[i
].argc
, functions
[i
].
string);
429 exit
(CLAY_ERROR_NB_ARGS
);
434 k
= top
- functions
[i
].argc
+ 1;
435 while
(j
< functions
[i
].argc
) {
437 // unref the data on the stack
438 // at the end of the function will be UNDEF_T on the stack
439 // to not free the referenced data
440 if
(functions
[i
].args
[j
] != MULTI_T
) {
441 if
(clay_parser_stack.stack
[k
].type
== REF_T
) {
442 tmp
= (clay_data_p
) clay_parser_stack.stack
[k
].data.obj
;
443 clay_parser_stack.stack
[k
].type
= tmp
->type
;
444 clay_parser_stack.stack
[k
].data
= tmp
->data
;
445 clay_array_add
(clay_parser_unref
, k
);
448 if
(clay_parser_stack.stack
[k
].type
!= functions
[i
].args
[j
]) {
450 "[Clay] Error: line %d, in function `%s' invalid type on argument %d\n"
451 "[Clay] prototype is: %s\n",
452 clay_yylineno
, name
, j
+1, functions
[i
].
string);
453 exit
(CLAY_ERROR_INVALID_TYPE
);
461 int status_result
= 0;
462 clay_betatree_p tree
;
466 result.type
= UNDEF_T
;
469 case CLAY_FUNCTION_SPLIT
:
470 status_result
= clay_split
(
472 clay_parser_stack.stack
[top
-1].data.obj
,
473 clay_parser_stack.stack
[top
].data.integer
,
474 clay_parser_options
);
477 case CLAY_FUNCTION_REORDER
:
478 status_result
= clay_reorder
(
480 clay_parser_stack.stack
[top
-1].data.obj
,
481 clay_parser_stack.stack
[top
].data.obj
,
482 clay_parser_options
);
485 case CLAY_FUNCTION_INTERCHANGE
:
486 status_result
= clay_interchange
(
488 clay_parser_stack.stack
[top
-3].data.obj
,
489 clay_parser_stack.stack
[top
-2].data.integer
,
490 clay_parser_stack.stack
[top
-1].data.integer
,
491 clay_parser_stack.stack
[top
].data.integer
,
492 clay_parser_options
);
495 case CLAY_FUNCTION_REVERSE
:
496 status_result
= clay_reverse
(
498 clay_parser_stack.stack
[top
-1].data.obj
,
499 clay_parser_stack.stack
[top
].data.integer
,
500 clay_parser_options
);
503 case CLAY_FUNCTION_FUSE
:
504 status_result
= clay_fuse
(
506 clay_parser_stack.stack
[top
].data.obj
,
507 clay_parser_options
);
510 case CLAY_FUNCTION_SKEW
:
511 status_result
= clay_skew
(
513 clay_parser_stack.stack
[top
-2].data.obj
,
514 clay_parser_stack.stack
[top
-1].data.integer
,
515 clay_parser_stack.stack
[top
].data.integer
,
516 clay_parser_options
);
519 case CLAY_FUNCTION_ISS
:
520 status_result
= clay_iss
(
522 clay_parser_stack.stack
[top
-1].data.obj
,
523 clay_parser_stack.stack
[top
].data.obj
,
525 clay_parser_options
);
528 case CLAY_FUNCTION_STRIPMINE
:
529 status_result
= clay_stripmine
(
531 clay_parser_stack.stack
[top
-3].data.obj
,
532 clay_parser_stack.stack
[top
-2].data.integer
,
533 clay_parser_stack.stack
[top
-1].data.integer
,
534 clay_parser_stack.stack
[top
].data.integer
,
535 clay_parser_options
);
538 case CLAY_FUNCTION_UNROLL
:
539 status_result
= clay_unroll
(
541 clay_parser_stack.stack
[top
-1].data.obj
,
542 clay_parser_stack.stack
[top
].data.integer
,
544 clay_parser_options
);
547 case CLAY_FUNCTION_UNROLL_NOEPILOG
:
548 status_result
= clay_unroll
(
550 clay_parser_stack.stack
[top
-1].data.obj
,
551 clay_parser_stack.stack
[top
].data.integer
,
553 clay_parser_options
);
556 case CLAY_FUNCTION_TILE
:
557 status_result
= clay_tile
(
559 clay_parser_stack.stack
[top
-4].data.obj
,
560 clay_parser_stack.stack
[top
-3].data.integer
,
561 clay_parser_stack.stack
[top
-2].data.integer
,
562 clay_parser_stack.stack
[top
-1].data.integer
,
563 clay_parser_stack.stack
[top
].data.integer
,
564 clay_parser_options
);
567 case CLAY_FUNCTION_SHIFT
:
568 status_result
= clay_shift
(
570 clay_parser_stack.stack
[top
-2].data.obj
,
571 clay_parser_stack.stack
[top
-1].data.integer
,
572 clay_parser_stack.stack
[top
].data.obj
,
573 clay_parser_options
);
576 case CLAY_FUNCTION_PEEL
:
577 status_result
= clay_peel
(
579 clay_parser_stack.stack
[top
-1].data.obj
,
580 clay_parser_stack.stack
[top
].data.obj
,
581 clay_parser_options
);
584 case CLAY_FUNCTION_CONTEXT
:
585 status_result
= clay_context
(
587 clay_parser_stack.stack
[top
].data.obj
,
588 clay_parser_options
);
591 case CLAY_FUNCTION_DIMREORDER
:
592 status_result
= clay_dimreorder
(
594 clay_parser_stack.stack
[top
-2].data.obj
,
595 clay_parser_stack.stack
[top
-1].data.integer
,
596 clay_parser_stack.stack
[top
].data.obj
,
597 clay_parser_options
);
600 case CLAY_FUNCTION_DIMPRIVATIZE
:
601 status_result
= clay_dimprivatize
(
603 clay_parser_stack.stack
[top
-2].data.obj
,
604 clay_parser_stack.stack
[top
-1].data.integer
,
605 clay_parser_stack.stack
[top
].data.integer
,
606 clay_parser_options
);
609 case CLAY_FUNCTION_DIMCONTRACT
:
610 status_result
= clay_dimcontract
(
612 clay_parser_stack.stack
[top
-2].data.obj
,
613 clay_parser_stack.stack
[top
-1].data.integer
,
614 clay_parser_stack.stack
[top
].data.integer
,
615 clay_parser_options
);
618 case CLAY_FUNCTION_ADDARRAY
:
619 result.type
= INTEGER_T
;
620 status_result
= clay_add_array
(
622 clay_parser_stack.stack
[top
].data.obj
,
623 &result.data.integer
,
624 clay_parser_options
);
627 case CLAY_FUNCTION_GETBETALOOP
:
628 tree
= clay_betatree_create
(clay_parser_scop
);
629 integer
= clay_parser_stack.stack
[top
].data.integer
;
630 result.type
= ARRAY_T
;
631 result.data.obj
= clay_ident_find_loop
(tree
, integer
);
633 if
(!result.data.obj
)
634 clay_parser_print_error
(CLAY_ERROR_IDENT_NAME_NOT_FOUND
);
636 clay_betatree_free
(tree
);
639 case CLAY_FUNCTION_GETBETASTMT
:
640 integer
= clay_parser_stack.stack
[top
].data.integer
;
641 result.type
= ARRAY_T
;
642 result.data.obj
= clay_ident_find_stmt
(clay_parser_scop
, integer
);
644 if
(!result.data.obj
)
645 clay_parser_print_error
(CLAY_ERROR_IDENT_STMT_NOT_FOUND
);
648 case CLAY_FUNCTION_GETBETALOOPBYNAME
:
649 data
= clay_parser_stack.stack
[top
].data.obj
;
650 result.type
= ARRAY_T
;
651 result.data.obj
= clay_ident_find_iterator
(clay_parser_scop
,
653 if
(!result.data.obj
)
654 clay_parser_print_error
(CLAY_ERROR_IDENT_NAME_NOT_FOUND
);
657 case CLAY_FUNCTION_GETARRAYID
:
658 data
= clay_parser_stack.stack
[top
].data.obj
;
659 result.type
= INTEGER_T
;
660 status_result
= clay_get_array_id
(
663 &result.data.integer
,
664 clay_parser_options
);
667 case CLAY_FUNCTION_PRINT
:
668 clay_data_print
(stderr
, &clay_parser_stack.stack
[top
]);
671 case CLAY_FUNCTION_REPLACEARRAY
:
672 status_result
= clay_replace_array
(
674 clay_parser_stack.stack
[top
-1].data.integer
,
675 clay_parser_stack.stack
[top
].data.integer
,
676 clay_parser_options
);
679 case CLAY_FUNCTION_DATACOPY
:
680 status_result
= clay_datacopy
(
682 clay_parser_stack.stack
[top
-4].data.integer
,
683 clay_parser_stack.stack
[top
-3].data.integer
,
684 clay_parser_stack.stack
[top
-2].data.obj
,
685 clay_parser_stack.stack
[top
-1].data.integer
,
686 clay_parser_stack.stack
[top
].data.obj
,
687 clay_parser_options
);
690 case CLAY_FUNCTION_BLOCK
:
691 status_result
= clay_block
(
693 clay_parser_stack.stack
[top
-1].data.obj
,
694 clay_parser_stack.stack
[top
].data.obj
,
695 clay_parser_options
);
699 fprintf
(stderr
, "[Clay] Error: can't call the function %s (%s).\n",
700 functions
[i
].name
, __func__
);
705 // don't free data which are unref
706 for
(i
= 0 ; i
< clay_parser_unref
->size
; i
++)
707 clay_parser_stack.stack
[clay_parser_unref
->data
[i
]].type
= UNDEF_T
;
709 clay_parser_unref
->size
= 0; // small optimization, don't remalloc each time
711 // clear args on the stack
712 for
(i
= 0 ; i
< nb_args
; i
++)
713 clay_data_clear
(clay_stack_pop
(&clay_parser_stack
));
716 if
(result.type
!= UNDEF_T
)
717 clay_stack_push
(&clay_parser_stack
, &result
);
720 if
(status_result
!= CLAY_SUCCESS
)
721 clay_parser_print_error
(status_result
);
726 * clay_parser_print_error function:
729 void clay_parser_print_error
(int status_result
) {
730 switch
(status_result
) {
731 case CLAY_ERROR_BETA_NOT_FOUND
:
732 fprintf
(stderr
,"[Clay] Error: line %d: the beta vector was not found\n",
735 case CLAY_ERROR_NOT_BETA_LOOP
:
736 fprintf
(stderr
,"[Clay] Error: line %d: the beta is not a loop\n",
739 case CLAY_ERROR_NOT_BETA_STMT
:
740 fprintf
(stderr
,"[Clay] Error: line %d: the beta is not a statement\n",
743 case CLAY_ERROR_REORDER_ARRAY_TOO_SMALL
:
744 fprintf
(stderr
,"[Clay] Error: line %d, the order array is too small\n",
747 case CLAY_ERROR_REORDER_ARRAY_SIZE
:
748 fprintf
(stderr
,"[Clay] Error: line %d, the order array is too small or too big\n",
751 case CLAY_ERROR_DEPTH_OVERFLOW
:
752 fprintf
(stderr
,"[Clay] Error: line %d, depth overflow\n",
755 case CLAY_ERROR_WRONG_COEFF
:
756 fprintf
(stderr
,"[Clay] Error: line %d, wrong coefficient\n",
759 case CLAY_ERROR_BETA_EMPTY
:
760 fprintf
(stderr
,"[Clay] Error: line %d, the beta vector is empty\n",
763 case CLAY_ERROR_BETA_NOT_IN_A_LOOP
:
764 fprintf
(stderr
,"[Clay] Error: line %d, the beta need to be in a loop\n",
767 case CLAY_ERROR_WRONG_BLOCK_SIZE
:
768 fprintf
(stderr
,"[Clay] Error: line %d, block value is incorrect\n",
771 case CLAY_ERROR_WRONG_FACTOR
:
772 fprintf
(stderr
,"[Clay] Error: line %d, wrong factor\n",
775 case CLAY_ERROR_DEPTH_OUTER
:
776 fprintf
(stderr
,"[Clay] Error: line %d, the depth is not 'outer'\n",
779 case CLAY_ERROR_VECTOR_EMPTY
:
780 fprintf
(stderr
,"[Clay] Error: line %d, the vector is empty\n",
783 case CLAY_ERROR_IDENT_NAME_NOT_FOUND
:
784 fprintf
(stderr
,"[Clay] Error: line %d, the iterator name was not found\n",
787 case CLAY_ERROR_IDENT_STMT_NOT_FOUND
:
788 fprintf
(stderr
,"[Clay] Error: line %d, the statement was not found\n",
791 case CLAY_ERROR_INEQU
:
792 fprintf
(stderr
,"[Clay] Error: line %d, the inequality seems "
796 case CLAY_ERROR_VECTOR
:
797 fprintf
(stderr
,"[Clay] Error: line %d, the vector seems to be wrong\n",
800 case CLAY_ERROR_REORDER_OVERFLOW_VALUE
:
801 fprintf
(stderr
,"[Clay] Error: line %d, there is an overflow value on the reorder array\n",
804 case CLAY_ERROR_CANT_PRIVATIZE
:
805 fprintf
(stderr
,"[Clay] Error: line %d, privatization failed\n",
808 case CLAY_ERROR_ARRAYS_EXT_EMPTY
:
809 fprintf
(stderr
,"[Clay] Error: arrays extensions is empty\n");
811 case CLAY_ERROR_ID_EXISTS
:
812 fprintf
(stderr
,"[Clay] Error: line %d, the id already exists\n",
815 case CLAY_ERROR_UNK_VAR
:
816 fprintf
(stderr
,"[Clay] Error: line %d, error on the variable\n"
817 " (for now only a-z variables are accepted)\n",
820 case CLAY_ERROR_VAR_NULL
:
821 fprintf
(stderr
,"[Clay] Error: line %d, the variable was not defined\n",
824 case CLAY_ERROR_CANT_CALL_SUBFUNC
:
825 fprintf
(stderr
,"[Clay] Error: line %d, sorry you can't at the moment call\n"
826 " a function in an other function. Please use a temp\n"
830 case CLAY_ERROR_ARRAY_NOT_FOUND
:
831 fprintf
(stderr
,"[Clay] Error: line %d, the array was not found\n",
834 case CLAY_ERROR_ARRAY_NOT_FOUND_IN_THE_BETA
:
836 "[Clay] Error: line %d, the array was not found in the given beta\n",
839 case CLAY_ERROR_BETAS_NOT_SAME_DIMS
:
840 fprintf
(stderr
,"[Clay] Error: line %d, the betas don't have the same dimensions\n",
843 case CLAY_ERROR_BETAS_NOT_SAME_DOMAIN
:
844 fprintf
(stderr
,"[Clay] Error: line %d, the betas don't have the same domain\n",
847 case CLAY_ERROR_ONE_HAS_EXTBODY
:
848 fprintf
(stderr
,"[Clay] Error: line %d, one of the statement has an extbody\n"
849 " but the other one\n",
853 fprintf
(stderr
,"[Clay] Error: unknown error %d (%s)\n",
854 status_result
, __func__
);