2 * $Id: astproc.c,v 1.21 2007/11/11 22:35:22 khansen Exp $
4 * Revision 1.21 2007/11/11 22:35:22 khansen
7 * Revision 1.20 2007/08/19 10:17:39 khansen
8 * allow symbols to be used without having been declared
10 * Revision 1.19 2007/08/12 18:58:12 khansen
11 * ability to generate pure 6502 binary (--pure-binary switch)
13 * Revision 1.18 2007/08/12 02:42:46 khansen
16 * Revision 1.17 2007/08/09 22:06:10 khansen
17 * ability to pass in reference to local label as argument to macro
19 * Revision 1.16 2007/08/09 20:48:46 khansen
20 * disable buggy code that can cause crash
22 * Revision 1.15 2007/08/09 20:33:40 khansen
25 * Revision 1.14 2007/08/08 22:40:01 khansen
26 * improved symbol lookup, definitions must precede usage
28 * Revision 1.13 2007/07/22 13:33:26 khansen
29 * convert tabs to whitespaces
31 * Revision 1.12 2005/01/09 11:17:57 kenth
33 * fixed bug in process_data(), merge_data()
34 * no longer truncation warning when fits in signed byte/word
36 * Revision 1.11 2005/01/05 02:28:13 kenth
38 * support for anonymous unions
41 * Revision 1.10 2004/12/29 21:44:41 kenth
43 * static indexing, sizeof improved
45 * Revision 1.9 2004/12/25 02:22:35 kenth
46 * fixed bug in reduce_user_storage()
48 * Revision 1.8 2004/12/19 19:58:29 kenth
51 * Revision 1.7 2004/12/18 16:57:39 kenth
52 * STORAGE_NODE(WORD/DWORD_DATATYPE) converts to BYTE
54 * Revision 1.6 2004/12/16 13:19:47 kenth
57 * Revision 1.5 2004/12/14 01:49:05 kenth
60 * Revision 1.4 2004/12/11 02:01:25 kenth
61 * added forward/backward branching
63 * Revision 1.3 2004/12/09 11:18:13 kenth
64 * added: warning, error node processing
66 * Revision 1.2 2004/12/06 04:52:24 kenth
67 * Major updates (xorcyst 1.1.0)
69 * Revision 1.1 2004/06/30 07:55:31 kenth
75 * (C) 2004 Kent Hansen
77 * The XORcyst is free software; you can redistribute it and/or modify
78 * it under the terms of the GNU General Public License as published by
79 * the Free Software Foundation; either version 2 of the License, or
80 * (at your option) any later version.
82 * The XORcyst is distributed in the hope that it will be useful,
83 * but WITHOUT ANY WARRANTY; without even the implied warranty of
84 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85 * GNU General Public License for more details.
87 * You should have received a copy of the GNU General Public License
88 * along with The XORcyst; if not, write to the Free Software
89 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
93 * This file contains functions that process the Abstract Syntax Tree (AST).
94 * After the assembly file has been parsed into an AST, a number of passes are
95 * made on it to process it and transform it. The functions here are
96 * concerned with things like
98 * - symbol table generation
99 * - equates substitution
101 * - code and symbol validation
115 #define IS_SIGNED_BYTE_VALUE(v) (((v) >= -128) && ((v) <= 127))
116 #define IS_UNSIGNED_BYTE_VALUE(v) (((v) >= 0) && ((v) <= 255))
117 #define IS_BYTE_VALUE(v) (IS_SIGNED_BYTE_VALUE(v) || IS_UNSIGNED_BYTE_VALUE(v))
119 #define IS_SIGNED_WORD_VALUE(v) (((v) >= -32768) && ((v) <= 32767))
120 #define IS_UNSIGNED_WORD_VALUE(v) (((v) >= 0) && ((v) <= 65535))
121 #define IS_WORD_VALUE(v) (IS_SIGNED_WORD_VALUE(v) || IS_UNSIGNED_WORD_VALUE(v))
123 /*---------------------------------------------------------------------------*/
125 /** Number of errors issued during processing. */
126 static int err_count
= 0;
128 /** Number of warnings issued during processing. */
129 static int warn_count
= 0;
131 /* Keeps track of number of global labels encountered. */
132 static int label_count
= 0;
134 /* Keeps track of whether statement is in dataseg or codeseg. */
135 static int in_dataseg
= 0;
137 /* Default symbol modifiers, i.e. ZEROPAGE_FLAG, PUBLIC_FLAG */
138 static int symbol_modifiers
= 0;
140 /* Used when we are outputting pure 6502 binary */
141 static int dataseg_pc
;
142 static int codeseg_pc
;
144 /*---------------------------------------------------------------------------*/
146 /** Mapping from regular ASCII characters to custom character values.
147 * Used to transform .char arrays to regular .db arrays.
149 static unsigned char charmap
[256];
152 * Resets the custom character map.
153 * Every ASCII character is mapped to itself.
155 static void reset_charmap()
158 for (i
=0; i
<256; i
++) {
159 charmap
[i
] = (char)i
;
163 /*---------------------------------------------------------------------------*/
164 /* Forward/backward branching stuff */
166 struct tag_forward_branch_info
{
168 int index
; /* Index into refs */
172 typedef struct tag_forward_branch_info forward_branch_info
;
174 struct tag_backward_branch_info
{
179 typedef struct tag_backward_branch_info backward_branch_info
;
183 static forward_branch_info forward_branch
[BRANCH_MAX
];
185 static backward_branch_info backward_branch
[BRANCH_MAX
];
188 * Zaps forward/backward branch data.
190 static void branch_init()
193 for (i
=0; i
<BRANCH_MAX
; i
++) {
194 for (j
=0; j
<128; j
++) {
195 forward_branch
[i
].refs
[j
] = NULL
;
197 forward_branch
[i
].index
= 0;
198 forward_branch
[i
].counter
= 0;
199 backward_branch
[i
].decl
= NULL
;
200 backward_branch
[i
].counter
= 0;
204 /*---------------------------------------------------------------------------*/
208 * @param loc File location of error
209 * @param fmt printf-style format string
211 static void err(location loc
, const char *fmt
, ...)
216 fprintf(stderr
, "%s:", loc
.file
);
217 LOCATION_PRINT(stderr
, loc
);
218 fprintf(stderr
, ": error: ");
219 vfprintf(stderr
, fmt
, ap
);
220 fprintf(stderr
, "\n");
229 * @param loc File location of warning
230 * @param fmt printf-style format string
232 static void warn(location loc
, const char *fmt
, ...)
235 if (!xasm_args
.no_warn
) {
237 fprintf(stderr
, "%s:", loc
.file
);
238 LOCATION_PRINT(stderr
, loc
);
239 fprintf(stderr
, ": warning: ");
240 vfprintf(stderr
, fmt
, ap
);
241 fprintf(stderr
, "\n");
249 * Gets the number of errors encountered during processing.
250 * @return Number of errors
252 int astproc_err_count()
257 /*---------------------------------------------------------------------------*/
260 * Gets the processor function for a node type from a map.
261 * Used by astproc_walk().
262 * @param type The node type
263 * @param map A mapping from node types to processor functions
265 static astnodeproc
astproc_node_type_to_proc(astnode_type type
, const astnodeprocmap
*map
)
267 for (; map
->proc
!= NULL
; map
+= 1) {
268 if (map
->type
== type
) {
275 /*---------------------------------------------------------------------------*/
278 * Walks an abstract syntax tree recursively.
279 * @param n Node to walk
280 * @param arg Optional argument to pass to processor function
281 * @param map Mapping of node types to processor functions
283 static void astproc_walk_recursive(astnode
*n
, void *arg
, const astnodeprocmap
*map
, astnode
**next
)
287 if (n
== NULL
) { return; }
288 astnodeproc p
= astproc_node_type_to_proc(astnode_get_type(n
), map
);
290 if (!p(n
, arg
, next
))
291 return; /* Don't walk children */
293 /* Walk the node's children recursively */
294 for (c
=n
->first_child
; c
!= NULL
; c
= t
) {
295 t
= c
->next_sibling
; /* default next node */
296 astproc_walk_recursive(c
, arg
, map
, &t
);
301 * Generic tree walker function.
303 * @param arg General-purpose argument passed to each node handler function
304 * @param map Array of (nodetype, handler function) tuples
306 void astproc_walk(astnode
*n
, void *arg
, const astnodeprocmap
*map
)
309 astproc_walk_recursive(n
, arg
, map
, &dummy
);
312 /*---------------------------------------------------------------------------*/
315 * Don't do any processing of this node or its children on this pass.
317 static int noop(astnode
*n
, void *arg
, astnode
**next
)
323 * Substitutes an identifier node with subst_expr if the id is equal to subst_id.
324 * @param id A node of type IDENTIFIER_NODE
325 * @param arg Array of length 2, containing (expr, id) pair
327 static int substitute_id(astnode
*id
, void *arg
, astnode
**next
)
329 /* arg is array containing expression and identifier */
330 astnode
**array
= (astnode
**)arg
;
331 astnode
*subst_expr
= array
[0];
332 astnode
*subst_id
= array
[1];
333 if (astnode_equal(id
, subst_id
)) {
334 /* They're equal, replace it by expression. */
335 astnode
*cl
= astnode_clone(subst_expr
, id
->loc
);
336 /* ### Generalize: traverse all children, set the flag */
337 if (astnode_get_type(cl
) == LOCAL_ID_NODE
) {
338 cl
->flags
|= 0x80; /* don't globalize it */
340 astnode_replace(id
, cl
);
341 astnode_finalize(id
);
350 * Substitutes expr for id in list.
351 * Used by macro expander to substitute a macro body parameter name with the
352 * actual expression used in the macro expansion.
353 * @param expr An expression
354 * @param id An identifier
355 * @param list A list of statements (macro body)
357 static void substitute_expr_for_id(astnode
*expr
, astnode
*id
, astnode
*list
)
359 /* Prepare argument to astproc_walk */
363 /* Table of callback functions for our purpose. */
364 static astnodeprocmap map
[] = {
365 { IDENTIFIER_NODE
, substitute_id
},
369 astproc_walk(list
, array
, map
);
372 /*---------------------------------------------------------------------------*/
375 * Globalizes a macro expanded local.
376 * This is done simply by concatenating the local label identifier with the
377 * global macro invocation counter.
378 * @param n A node of type LOCAL_LABEL_NODE or LOCAL_ID_NODE
379 * @param arg Namespace counter (int)
381 static int globalize_macro_expanded_local(astnode
*n
, void *arg
, astnode
**next
)
383 /* Only globalize if it's a reference to a label defined in the macro */
384 if (!(n
->flags
& 0x80)) {
387 /* Make it global by appending the macro expansion counter to the id */
389 snprintf(str
, sizeof (str
), "#%d", count
);
390 if (astnode_is_type(n
, LOCAL_LABEL_NODE
)) {
391 /* LOCAL_LABEL_NODE, use label field */
392 n
->label
= realloc(n
->label
, strlen(n
->label
)+strlen(str
)+1);
393 strcat(n
->label
, str
);
395 /* LOCAL_ID_NODE, use ident field */
396 assert(astnode_is_type(n
, LOCAL_ID_NODE
));
397 n
->ident
= realloc(n
->ident
, strlen(n
->ident
)+strlen(str
)+1);
398 strcat(n
->ident
, str
);
405 * Globalizes all locals in the body of a macro expansion.
406 * Used by the macro expander to ensure that local labels in macro expansions
408 * @param exp_body The expanded macro body
409 * @param count Unique macro namespace counter
411 static void globalize_macro_expanded_locals(astnode
*exp_body
, int count
)
413 /* Table of callback functions for our purpose. */
414 static astnodeprocmap map
[] = {
415 { LOCAL_ID_NODE
, globalize_macro_expanded_local
},
416 { LOCAL_LABEL_NODE
, globalize_macro_expanded_local
},
420 astproc_walk(exp_body
, (void *)count
, map
);
424 * Expands a macro; that is, replaces a macro invocation in the AST with the
425 * macro body. Substitutes parameter names for values.
426 * @param macro Must be a node of type MACRO_NODE
427 * @param arg Not used
429 static int expand_macro(astnode
*macro
, void *arg
, astnode
**next
)
439 /* Keeps track of the current/total number of macro expansions */
440 static int macro_expansion_count
= 0;
442 id
= astnode_get_child(macro
, 0);
443 assert(astnode_is_type(id
, IDENTIFIER_NODE
));
444 symtab_entry
*e
= symtab_lookup(id
->ident
);
446 err(macro
->loc
, "unknown macro or directive `%s'", id
->ident
);
447 astnode_remove(macro
);
448 astnode_finalize(macro
);
451 else if (e
->type
!= MACRO_SYMBOL
) {
452 err(macro
->loc
, "cannot expand `%s'; not a macro", e
->id
);
453 astnode_remove(macro
);
454 astnode_finalize(macro
);
458 decl
= (astnode
*)e
->def
;
459 formals
= astnode_get_child(decl
, 1);
460 actuals
= astnode_get_child(macro
, 1);
461 if (astnode_get_child_count(formals
) != astnode_get_child_count(actuals
)) {
462 err(macro
->loc
, "macro `%s' does not take %d argument(s)", id
->ident
, astnode_get_child_count(actuals
) );
463 astnode_remove(macro
);
464 astnode_finalize(macro
);
467 /* Expand the body */
468 decl_body
= astnode_get_child(decl
, 2);
469 exp_body
= astnode_clone(decl_body
, macro
->loc
);
470 assert(astnode_get_type(exp_body
) == LIST_NODE
);
471 /* Substitute actuals for formals */
472 for (i
=0; i
<astnode_get_child_count(actuals
); i
++) {
473 /* The id to substitute */
474 id
= astnode_get_child(formals
, i
);
475 /* The expression to substitute it with */
476 expr
= astnode_get_child(actuals
, i
);
478 substitute_expr_for_id(expr
, id
, exp_body
);
480 /* Make locals a bit more global */
481 globalize_macro_expanded_locals(exp_body
, macro_expansion_count
);
482 /* Replace MACRO_NODE by the macro body instance */
484 astnode
*stmts
= astnode_remove_children(exp_body
);
485 astnode_replace(macro
, stmts
);
487 astnode_finalize(exp_body
);
490 astnode_finalize(macro
);
491 macro_expansion_count
++;
496 /*---------------------------------------------------------------------------*/
499 * Does constant folding of expression.
500 * If the expression can be folded, the original expression is replaced by the
501 * new one, and the original expression is finalized.
502 * @param expr Expression
503 * @return Original expression, if couldn't fold, otherwise new, folded expression
505 astnode
*astproc_fold_constants(astnode
*expr
)
510 if (expr
== NULL
) { return NULL
; }
512 if (astnode_is_type(expr
, ARITHMETIC_NODE
)) {
513 /* Fold operands recursively */
514 lhs
= astproc_fold_constants(LHS(expr
));
515 rhs
= astproc_fold_constants(RHS(expr
));
516 switch (expr
->oper
) {
534 /* See if it can be folded */
535 if ( (astnode_is_type(lhs
, INTEGER_NODE
)) &&
536 (astnode_is_type(rhs
, INTEGER_NODE
)) ) {
537 /* Both sides are integer literals, so fold. */
538 switch (expr
->oper
) {
539 case PLUS_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
+ rhs
->integer
, expr
->loc
); break;
540 case MINUS_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
- rhs
->integer
, expr
->loc
); break;
541 case MUL_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
* rhs
->integer
, expr
->loc
); break;
542 case DIV_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
/ rhs
->integer
, expr
->loc
); break;
543 case MOD_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
% rhs
->integer
, expr
->loc
); break;
544 case AND_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
& rhs
->integer
, expr
->loc
); break;
545 case OR_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
| rhs
->integer
, expr
->loc
); break;
546 case XOR_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
^ rhs
->integer
, expr
->loc
); break;
547 case SHL_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
<< rhs
->integer
, expr
->loc
); break;
548 case SHR_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
>> rhs
->integer
, expr
->loc
); break;
549 case LT_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
< rhs
->integer
, expr
->loc
); break;
550 case GT_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
> rhs
->integer
, expr
->loc
); break;
551 case EQ_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
== rhs
->integer
, expr
->loc
); break;
552 case NE_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
!= rhs
->integer
, expr
->loc
); break;
553 case LE_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
<= rhs
->integer
, expr
->loc
); break;
554 case GE_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
>= rhs
->integer
, expr
->loc
); break;
557 fprintf(stderr
, "internal error: operator not handled in astproc_fold_constants()\n");
562 if (folded
!= expr
) {
563 /* Replace expression by folded one. */
564 astnode_replace(expr
, folded
);
565 astnode_finalize(expr
);
569 else if ( (astnode_is_type(lhs
, STRING_NODE
)) &&
570 (astnode_is_type(rhs
, STRING_NODE
)) ) {
571 /* Both sides are string literals. */
572 /* Folding is defined only for certain operators. */
573 switch (expr
->oper
) {
575 /* String concatenation. */
576 folded
= astnode_create(STRING_NODE
, expr
->loc
);
577 folded
->string
= (char *)malloc(strlen(lhs
->string
) + strlen(rhs
->string
) + 1);
578 if (folded
->string
!= NULL
) {
579 strcpy(folded
->string
, lhs
->string
);
580 strcat(folded
->string
, rhs
->string
);
584 /* String comparison. */
585 case LT_OPERATOR
: folded
= astnode_create_integer(strcmp(lhs
->string
, rhs
->string
) < 0, expr
->loc
); break;
586 case GT_OPERATOR
: folded
= astnode_create_integer(strcmp(lhs
->string
, rhs
->string
) > 0, expr
->loc
); break;
587 case EQ_OPERATOR
: folded
= astnode_create_integer(strcmp(lhs
->string
, rhs
->string
) == 0, expr
->loc
); break;
588 case NE_OPERATOR
: folded
= astnode_create_integer(strcmp(lhs
->string
, rhs
->string
) != 0, expr
->loc
); break;
589 case LE_OPERATOR
: folded
= astnode_create_integer(strcmp(lhs
->string
, rhs
->string
) <= 0, expr
->loc
); break;
590 case GE_OPERATOR
: folded
= astnode_create_integer(strcmp(lhs
->string
, rhs
->string
) >= 0, expr
->loc
); break;
596 if (folded
!= expr
) {
597 /* Replace expression by folded one. */
598 astnode_replace(expr
, folded
);
599 astnode_finalize(expr
);
603 else if ((astnode_get_type(lhs
) == STRING_NODE
) &&
604 (astnode_get_type(rhs
) == INTEGER_NODE
) &&
605 (expr
->oper
== PLUS_OPERATOR
)) {
606 /* Left side is string and right side is integer.
607 Result is a string. */
609 snprintf(str
, sizeof (str
), "%d", rhs
->integer
);
610 folded
= astnode_create(STRING_NODE
, expr
->loc
);
611 folded
->string
= (char *)malloc(strlen(lhs
->string
) + strlen(str
) + 1);
612 if (folded
->string
!= NULL
) {
613 strcpy(folded
->string
, lhs
->string
);
614 strcat(folded
->string
, str
);
616 /* Replace expression by folded one. */
617 astnode_replace(expr
, folded
);
618 astnode_finalize(expr
);
621 else if ((astnode_get_type(rhs
) == STRING_NODE
) &&
622 (astnode_get_type(lhs
) == INTEGER_NODE
) &&
623 (expr
->oper
== PLUS_OPERATOR
)) {
624 /* Left side is integer and right side is string.
625 Result is a string. */
627 snprintf(str
, sizeof (str
), "%d", lhs
->integer
);
628 folded
= astnode_create(STRING_NODE
, expr
->loc
);
629 folded
->string
= (char *)malloc(strlen(str
) + strlen(rhs
->string
) + 1);
630 if (folded
->string
!= NULL
) {
631 strcpy(folded
->string
, str
);
632 strcat(folded
->string
, rhs
->string
);
634 /* Replace expression by folded one. */
635 astnode_replace(expr
, folded
);
636 astnode_finalize(expr
);
639 /* Use some mathematical identities... */
640 else if ((astnode_is_type(lhs
, INTEGER_NODE
) && (lhs
->integer
== 0))
641 && (expr
->oper
== PLUS_OPERATOR
)) {
643 astnode_remove_child(expr
, rhs
);
644 astnode_replace(expr
, rhs
);
645 astnode_finalize(expr
);
648 else if ((astnode_is_type(rhs
, INTEGER_NODE
) && (rhs
->integer
== 0))
649 && (expr
->oper
== PLUS_OPERATOR
)) {
651 astnode_remove_child(expr
, lhs
);
652 astnode_replace(expr
, lhs
);
653 astnode_finalize(expr
);
656 else if ((astnode_is_type(lhs
, INTEGER_NODE
) && (lhs
->integer
== 1))
657 && (expr
->oper
== MUL_OPERATOR
)) {
659 astnode_remove_child(expr
, rhs
);
660 astnode_replace(expr
, rhs
);
661 astnode_finalize(expr
);
664 else if ((astnode_is_type(rhs
, INTEGER_NODE
) && (rhs
->integer
== 1))
665 && ((expr
->oper
== MUL_OPERATOR
) || (expr
->oper
== DIV_OPERATOR
)) ) {
668 astnode_remove_child(expr
, lhs
);
669 astnode_replace(expr
, lhs
);
670 astnode_finalize(expr
);
674 /* No chance of folding this one. */
683 case UMINUS_OPERATOR
:
685 /* See if it can be folded */
686 if (astnode_is_type(lhs
, INTEGER_NODE
)) {
688 switch (expr
->oper
) {
689 case NEG_OPERATOR
: folded
= astnode_create_integer(~lhs
->integer
, expr
->loc
); break;
690 case NOT_OPERATOR
: folded
= astnode_create_integer(!lhs
->integer
, expr
->loc
); break;
691 case LO_OPERATOR
: folded
= astnode_create_integer(lhs
->integer
& 0xFF, expr
->loc
); break;
692 case HI_OPERATOR
: folded
= astnode_create_integer((lhs
->integer
>> 8) & 0xFF, expr
->loc
); break;
693 case UMINUS_OPERATOR
: folded
= astnode_create_integer(-lhs
->integer
, expr
->loc
); break;
696 /* Replace expression by folded one. */
697 astnode_replace(expr
, folded
);
698 astnode_finalize(expr
);
702 /* Couldn't fold this one. */
707 /* Couldn't fold it, return original expression */
711 /*---------------------------------------------------------------------------*/
714 * Substitutes identifier if it has a constant definition in symbol table.
715 * @param expr Node of type IDENTIFIER_NODE
717 static astnode
*substitute_ident(astnode
*expr
)
721 e
= symtab_lookup(expr
->ident
);
723 if (e
->type
== CONSTANT_SYMBOL
) {
724 /* This is a defined symbol that should be
725 replaced by the expression it stands for */
726 c
= astnode_clone((astnode
*)e
->def
, expr
->loc
);
727 astnode_replace(expr
, c
);
728 astnode_finalize(expr
);
736 * Substitutes sizeof with proper constant.
737 * @param expr Node of type SIZEOF_NODE
739 static astnode
*reduce_sizeof(astnode
*expr
)
749 if (astnode_is_type(LHS(expr
), IDENTIFIER_NODE
)) {
750 /* Identifier might be the name of a user-defined type, OR
751 it might be the name of a variable of a user-defined type */
755 e
= symtab_global_lookup(id
->ident
);
762 type
= astnode_create_datatype(USER_DATATYPE
, astnode_clone(id
, id
->loc
), id
->loc
);
766 type
= astnode_clone(LHS(e
->def
), id
->loc
);
767 if (astnode_is_type(e
->def
, STORAGE_NODE
)) {
768 count
= astnode_clone(RHS(e
->def
), id
->loc
);
771 count
= astnode_create_integer(astnode_get_child_count(e
->def
)-1, id
->loc
);
776 /* Can't take sizeof of this symbol type */
782 type
= astnode_create_datatype(USER_DATATYPE
, astnode_clone(id
, id
->loc
), id
->loc
);
784 /* Replace identifier by datatype node */
785 astnode_replace(id
, type
);
786 astnode_finalize(id
);
789 switch (type
->datatype
) {
792 c
= astnode_create_integer(1, expr
->loc
);
793 astnode_replace(expr
, c
);
794 astnode_finalize(expr
);
799 c
= astnode_create_integer(2, expr
->loc
);
800 astnode_replace(expr
, c
);
801 astnode_finalize(expr
);
806 c
= astnode_create_integer(4, expr
->loc
);
807 astnode_replace(expr
, c
);
808 astnode_finalize(expr
);
814 e
= symtab_global_lookup(id
->ident
);
820 /* Datatype is defined, replace sizeof with proper expression */
821 c
= astnode_clone((astnode
*)(e
->struc
.size
), ((astnode
*)(e
->struc
.size
))->loc
);
822 astnode_replace(expr
, c
);
823 astnode_finalize(expr
);
831 c
= astnode_create_integer(1, expr
->loc
);
832 astnode_replace(expr
, c
);
833 astnode_finalize(expr
);
839 /* Dunno the size of this symbol type */
844 /* Datatype not defined, error */
845 err(expr
->loc
, "size of `%s' is unknown", id
->ident
);
847 c
= astnode_create_integer(1, expr
->loc
);
848 astnode_replace(expr
, c
);
849 astnode_finalize(expr
);
855 err(expr
->loc
, "substitute_sizeof(): unknown type");
859 c
= astnode_create_arithmetic(
861 astnode_clone(expr
, expr
->loc
),
865 astnode_replace(expr
, c
);
866 astnode_finalize(expr
);
873 * Substitutes A::B with an expression.
874 * If A is a struct: substitute with offset of B
875 * If A is a union: substitute with 0
876 * If A is an enumeration: substitute with value for B
877 * @param expr Node of type SCOPE_NODE
879 static astnode
*reduce_scope(astnode
*expr
)
886 /* Look up the namespace */
887 namespace = LHS(expr
);
888 ns
= symtab_lookup(namespace->ident
);
890 /* Look up the local symbol */
891 symtab_push(ns
->symtab
);
893 sym
= symtab_lookup(symbol
->ident
);
895 /* See if we can replace it */
900 /* Replace with field offset */
901 c
= astnode_clone(sym
->field
.offset
, sym
->field
.offset
->loc
);
902 astnode_replace(expr
, c
);
903 astnode_finalize(expr
);
908 /* Replace with enum entry value */
909 c
= astnode_clone(sym
->def
, sym
->def
->loc
);
910 astnode_replace(expr
, c
);
911 astnode_finalize(expr
);
924 static astnode
*reduce_expression(astnode
*expr
);
927 * Handles remainder of fields in A.B.C.D . ..., where one or more fields may be indexed.
928 * @param expr Node of type DOT_NODE, INDEX_NODE or IDENTIFIER_NODE
930 static astnode
*reduce_dot_recursive(astnode
*expr
)
939 astnode
*index
= NULL
;
940 /* Get identifiers involved: 'right' is field in 'left' */
942 if (astnode_is_type(left
, INDEX_NODE
)) {
943 left
= LHS(left
); /* Need identifier */
946 if (astnode_is_type(right
, DOT_NODE
)) {
947 right
= LHS(right
); /* Need identifier */
949 if (astnode_is_type(right
, INDEX_NODE
)) {
951 right
= LHS(right
); /* Need identifier */
953 /* Lookup 'right' in 'left's symbol table (on stack) */
954 field
= symtab_lookup(right
->ident
);
955 /* Look up variable's type definition */
956 type
= LHS(field
->def
);
957 /* Copy its offset */
958 offset
= astnode_clone(field
->field
.offset
, right
->loc
);
960 /* Create expression: identifier + sizeof(datatype) * index */
961 offset
= astnode_create_arithmetic(
964 astnode_create_arithmetic(
966 astnode_create_sizeof(astnode_clone(type
, type
->loc
), expr
->loc
),
967 astnode_clone(index
, index
->loc
),
973 /* See if more subfields to process */
975 if (astnode_is_type(expr
, DOT_NODE
)) {
977 def
= symtab_global_lookup(LHS(type
)->ident
);
978 symtab_push(def
->symtab
);
979 term
= reduce_dot_recursive(expr
);
982 offset
= astnode_create_arithmetic(
993 * Transforms A.B.C.D . ... to A + offset(B) + offset(C) + ...
994 * No error checking, since validate_dotref() should have been called previously.
995 * @param expr Node of type DOT_NODE
997 static astnode
*reduce_dot(astnode
*expr
)
999 symtab_entry
*father
;
1006 astnode
*index
= NULL
;
1007 /* Look up parent in global symbol table */
1008 left
= LHS(expr
); /* expr := left . right */
1009 if (astnode_is_type(left
, INDEX_NODE
)) {
1011 left
= LHS(left
); /* Need identifier */
1013 father
= symtab_lookup(left
->ident
);
1014 /* Look up variable's type definition */
1015 type
= LHS(father
->def
); /* DATATYPE_NODE */
1016 def
= symtab_lookup(LHS(type
)->ident
);
1017 /* 1st term of sum is the leftmost structure identifier */
1018 term1
= astnode_clone(left
, left
->loc
);
1019 if (index
!= NULL
) {
1020 /* Create expression: identifier + sizeof(datatype) * index */
1021 term1
= astnode_create_arithmetic(
1024 astnode_create_arithmetic(
1026 astnode_create_sizeof(astnode_clone(type
, type
->loc
), expr
->loc
),
1027 astnode_clone(index
, index
->loc
),
1033 /* Add offsets recursively */
1034 symtab_push(def
->symtab
);
1035 term2
= reduce_dot_recursive(expr
);
1037 /* Calculate final sum */
1038 sum
= astnode_create_arithmetic(
1044 sum
= reduce_expression(sum
);
1045 /* Replace dotted expression by sum */
1046 astnode_replace(expr
, sum
);
1047 astnode_finalize(expr
);
1052 * Reduces MASK operation to a field mask.
1053 * @param mask A node of type MASK_NODE
1055 static astnode
*reduce_mask(astnode
*mask
)
1063 /* Child is a scope node, record::field */
1065 /* Look up the namespace */
1066 namespace = LHS(expr
);
1067 ns
= symtab_lookup(namespace->ident
);
1069 /* Make sure it's a record */
1070 if (ns
->type
!= RECORD_SYMBOL
) {
1071 err(expr
->loc
, "`%s' is not a record");
1073 c
= astnode_create_integer(0, expr
->loc
);
1074 astnode_replace(mask
, c
);
1075 astnode_finalize(mask
);
1079 /* Look up the local symbol */
1080 symtab_push(ns
->symtab
);
1082 sym
= symtab_lookup(symbol
->ident
);
1084 /* Calculate field mask */
1085 // mask = ((1 << width) - 1) << offset
1086 c
= astnode_create_arithmetic(
1088 astnode_create_arithmetic(
1090 astnode_create_arithmetic(
1092 astnode_create_integer(1, expr
->loc
),
1093 astnode_clone(sym
->field
.size
, expr
->loc
),
1096 astnode_create_integer(1, expr
->loc
),
1099 astnode_clone(sym
->field
.offset
, expr
->loc
),
1102 c
= reduce_expression(c
);
1103 astnode_replace(mask
, c
);
1104 astnode_finalize(mask
);
1114 * Reduces identifier[expression] to identifier + sizeof(identifier type) * expression
1116 static astnode
*reduce_index(astnode
*expr
)
1124 assert(astnode_is_type(id
, IDENTIFIER_NODE
));
1125 index
= reduce_expression(RHS(expr
));
1126 /* Lookup identifier */
1127 e
= symtab_lookup(id
->ident
);
1129 /* Get its datatype */
1131 /* Create expression: identifier + sizeof(datatype) * index */
1132 c
= astnode_create_arithmetic(
1134 astnode_clone(id
, id
->loc
),
1135 astnode_create_arithmetic(
1137 astnode_create_sizeof(astnode_clone(type
, type
->loc
), expr
->loc
),
1138 astnode_clone(index
, index
->loc
),
1143 /* Replace index expression */
1144 astnode_replace(expr
, c
);
1145 astnode_finalize(expr
);
1150 * Substitutes all identifiers that represent EQU defines with their
1151 * corresponding expression.
1152 * @param expr The expression whose defines to substitute
1154 static astnode
*substitute_defines(astnode
*expr
)
1156 switch (astnode_get_type(expr
)) {
1157 case ARITHMETIC_NODE
:
1158 substitute_defines(LHS(expr
));
1159 substitute_defines(RHS(expr
));
1162 case IDENTIFIER_NODE
:
1163 expr
= substitute_ident(expr
);
1167 expr
= reduce_sizeof(expr
);
1171 expr
= reduce_mask(expr
);
1175 substitute_defines(LHS(expr
));
1176 substitute_defines(RHS(expr
));
1180 substitute_defines(LHS(expr
));
1181 substitute_defines(RHS(expr
));
1194 static astnode
*reduce_highlevel_constructs(astnode
*expr
)
1196 switch (astnode_get_type(expr
)) {
1197 case ARITHMETIC_NODE
:
1198 reduce_highlevel_constructs(LHS(expr
));
1199 reduce_highlevel_constructs(RHS(expr
));
1203 expr
= reduce_scope(expr
);
1207 expr
= reduce_dot(expr
);
1211 expr
= reduce_index(expr
);
1222 * Really reduces an expression.
1223 * @param expr Expression to attempt to reduce
1225 static astnode
*reduce_expression_complete(astnode
*expr
)
1227 return astproc_fold_constants( reduce_highlevel_constructs( substitute_defines(expr
) ) );
1231 * Reduces an expression.
1232 * It does two things:
1233 * 1. Substitute all equates by their value
1234 * 2. Folds constants in the resulting expression
1235 * If the expression is reduced, the original expression is replaced by the
1236 * new one, the original is finalized, and a pointer to the new expression
1238 * If the expression is not reduced, the original pointer is returned.
1240 static astnode
*reduce_expression(astnode
*expr
)
1242 return astproc_fold_constants( substitute_defines(expr
) );
1246 * Reduces RECORD instance to a single byte (DB statement).
1247 * @param r Record's symbol table entry
1248 * @param expr Record initializer
1249 * @param flat List on which to append the reduced form
1251 static void reduce_record(symtab_entry
*r
, astnode
*init
, astnode
*flat
)
1253 ordered_field_list
*list
;
1260 if (!astnode_is_type(init
, STRUC_NODE
)) {
1261 err(init
->loc
, "record initializer expected");
1264 /* Go through fields */
1265 symtab_push(r
->symtab
);
1266 result
= astnode_create_integer(0, init
->loc
);
1267 for (val
= init
->first_child
, list
= r
->struc
.fields
; (val
!= NULL
) && (list
!= NULL
); list
= list
->next
, val
= val
->next_sibling
) {
1268 if (astnode_is_type(val
, NULL_NODE
)) {
1271 if (astnode_is_type(val
, STRUC_NODE
)) {
1272 err(init
->loc
, "record field initializer expected");
1275 /* Get field definition */
1277 /* Calculate field mask */
1278 // mask = ((1 << width) - 1) << offset
1279 mask
= astnode_create_arithmetic(
1281 astnode_create_arithmetic(
1283 astnode_create_arithmetic(
1285 astnode_create_integer(1, val
->loc
),
1286 astnode_clone(e
->field
.size
, val
->loc
),
1289 astnode_create_integer(1, val
->loc
),
1292 astnode_clone(e
->field
.offset
, val
->loc
),
1295 /* Shift val left e->field.offset bits, AND with mask */
1296 term
= astnode_create_arithmetic(
1298 astnode_create_arithmetic(
1300 astnode_clone(val
, val
->loc
),
1301 astnode_clone(e
->field
.offset
, val
->loc
),
1307 /* OR the value with the result so far */
1308 result
= astnode_create_arithmetic(
1314 result
= reduce_expression(result
);
1316 /* Determine reason for stopping loop */
1318 err(init
->loc
, "too many field initializers");
1320 /* Make byte data node (packed record value) */
1321 repl
= astnode_create_data(
1322 astnode_create_datatype(BYTE_DATATYPE
, NULL
, init
->loc
),
1326 astnode_add_child(flat
, repl
);
1331 * Reduces ENUM instance to DB.
1332 * @param e Enumeration's symbol table entry
1333 * @param expr Expression
1334 * @param flat List on which to append the reduced form
1336 static void reduce_enum(symtab_entry
*e
, astnode
*expr
, astnode
*list
)
1340 if (!astnode_is_type(expr
, IDENTIFIER_NODE
)) {
1341 err(expr
->loc
, "identifier expected");
1344 /* Look up the enumeration symbol */
1345 symtab_push(e
->symtab
);
1346 sym
= symtab_lookup(expr
->ident
);
1348 /* Make byte data node (symbol value) */
1349 repl
= astnode_create_data(
1350 astnode_create_datatype(BYTE_DATATYPE
, NULL
, expr
->loc
),
1351 astnode_clone(sym
->def
, expr
->loc
),
1354 astnode_add_child(list
, repl
);
1358 static void flatten_struc_recursive(symtab_entry
*s
, astnode
*init
, astnode
*flat
);
1361 * Flattens a union initializer to a sequence of native data values.
1362 * Verify similar to flattening of structure, but only single field allowed.
1363 * @param s Union's symbol table definition
1364 * @param init Union initializer
1365 * @param flat List on which to append the flattened form
1367 static void flatten_union_recursive(symtab_entry
*s
, astnode
*init
, astnode
*flat
)
1377 ordered_field_list
*list
;
1379 if (!astnode_is_type(init
, STRUC_NODE
)) {
1380 err(init
->loc
, "union initializer expected");
1383 /* Go through fields */
1384 symtab_push(s
->symtab
);
1385 fill
= astnode_clone(s
->struc
.size
, flat
->loc
);
1386 for (val
= init
->first_child
, list
= s
->struc
.fields
; (val
!= NULL
) && (list
!= NULL
); list
= list
->next
, val
= val
->next_sibling
) {
1387 if (astnode_is_type(val
, NULL_NODE
)) {
1390 if (!astnode_equal(fill
, s
->struc
.size
)) {
1391 err(init
->loc
, "only one field of union can be initialized");
1394 /* Get field definition */
1396 /* Symbol definition is STORAGE_NODE w/ two children: type and count */
1398 count
= RHS(e
->def
);
1399 /* Decide what to do based on field type and value */
1400 switch (type
->datatype
) {
1404 case DWORD_DATATYPE
:
1405 if (astnode_is_type(val
, STRUC_NODE
)) {
1406 /* Handle multi-value array */
1407 temp
= astnode_clone(val
, val
->loc
);
1408 valvals
= astnode_remove_children(temp
);
1409 astnode_finalize(temp
);
1410 astnode_add_child(flat
,
1411 astnode_create_data(
1412 astnode_create_datatype(type
->datatype
, NULL
, type
->loc
),
1417 num
= astnode_get_child_count(val
);
1419 /* Output single value */
1420 astnode_add_child(flat
,
1421 astnode_create_data(
1422 astnode_create_datatype(type
->datatype
, NULL
, type
->loc
),
1423 astnode_clone(val
, val
->loc
),
1427 num
= astnode_is_type(val
, STRING_NODE
) ? strlen(val
->string
) : 1;
1429 if (num
> count
->integer
) {
1430 err(val
->loc
, "initializer for field `%s' exceeds field size", e
->id
);
1432 /* Fill in remainder of field if necessary: count - 1 */
1433 else if (count
->integer
> num
) {
1434 astnode_add_child(flat
,
1435 astnode_create_storage(
1436 astnode_create_datatype(type
->datatype
, NULL
, type
->loc
),
1437 astproc_fold_constants(
1438 astnode_create_arithmetic(
1440 astnode_clone(count
, count
->loc
),
1441 astnode_create_integer(num
, flat
->loc
),
1452 t
= symtab_global_lookup(LHS(type
)->ident
);
1455 flatten_struc_recursive(t
, val
, flat
);
1459 flatten_union_recursive(t
, val
, flat
);
1463 reduce_record(t
, val
, flat
);
1467 reduce_enum(t
, val
, flat
);
1475 /* Decrease fill amount according to field size */
1476 fill
= astproc_fold_constants(
1477 astnode_create_arithmetic(
1480 astnode_clone(e
->field
.size
, flat
->loc
),
1486 err(init
->loc
, "too many field initializers");
1488 if (fill
->integer
> 0) {
1489 /* Fill remainder of union with zeroes */
1490 astnode_add_child(flat
,
1491 astnode_create_storage(
1492 astnode_create_datatype(BYTE_DATATYPE
, NULL
, flat
->loc
),
1502 * Flattens a structure initializer to a sequence of native data values.
1503 * @param s Structure's symbol table definition
1504 * @param init Structure initializer
1505 * @param flat List on which to append the flattened form
1507 static void flatten_struc_recursive(symtab_entry
*s
, astnode
*init
, astnode
*flat
)
1517 ordered_field_list
*list
;
1519 if (!astnode_is_type(init
, STRUC_NODE
)) {
1520 err(init
->loc
, "structure initializer expected");
1523 /* Go through fields */
1524 symtab_push(s
->symtab
);
1525 fill
= astnode_clone(s
->struc
.size
, flat
->loc
);
1526 for (val
= init
->first_child
, list
= s
->struc
.fields
; (val
!= NULL
) && (list
!= NULL
); list
= list
->next
, val
= val
->next_sibling
) {
1528 /* Check if normal field or anonymous union */
1529 if (e
->type
== UNION_SYMBOL
) {
1530 if (astnode_is_type(val
, NULL_NODE
)) {
1531 /* Output union size bytes to fill in field */
1532 astnode_add_child(flat
,
1533 astnode_create_storage(
1534 astnode_create_datatype(BYTE_DATATYPE
, NULL
, val
->loc
),
1535 astnode_clone(e
->struc
.size
, val
->loc
),
1540 flatten_union_recursive(e
, val
, flat
);
1541 /* Decrease fill amount according to union size */
1542 fill
= astproc_fold_constants(
1543 astnode_create_arithmetic(
1546 astnode_clone(e
->struc
.size
, flat
->loc
),
1553 /* Symbol definition is STORAGE_NODE w/ two children: type and count */
1555 count
= RHS(e
->def
);
1556 /* Decide what to do based on field type and value */
1557 switch (type
->datatype
) {
1561 case DWORD_DATATYPE
:
1562 if (astnode_is_type(val
, NULL_NODE
)) {
1563 /* Output field_size bytes to fill in field */
1564 astnode_add_child(flat
,
1565 astnode_create_storage(
1566 astnode_create_datatype(type
->datatype
, NULL
, type
->loc
),
1567 astnode_clone(count
, count
->loc
),
1572 if (astnode_is_type(val
, STRUC_NODE
)) {
1573 /* Handle multi-value array */
1574 temp
= astnode_clone(val
, val
->loc
);
1575 valvals
= astnode_remove_children(temp
);
1576 astnode_finalize(temp
);
1577 astnode_add_child(flat
,
1578 astnode_create_data(
1579 astnode_create_datatype(type
->datatype
, NULL
, type
->loc
),
1584 num
= astnode_get_child_count(val
);
1586 /* Output single value */
1587 astnode_add_child(flat
,
1588 astnode_create_data(
1589 astnode_create_datatype(type
->datatype
, NULL
, type
->loc
),
1590 astnode_clone(val
, val
->loc
),
1594 num
= astnode_is_type(val
, STRING_NODE
) ? strlen(val
->string
) : 1;
1596 if (astnode_is_type(count
, INTEGER_NODE
) && (count
->integer
< num
)) {
1597 err(val
->loc
, "initializer for field `%s' exceeds field size", e
->id
);
1599 /* Fill in remainder of field if necessary: count - 1 */
1600 else if ( (astnode_is_type(count
, INTEGER_NODE
) && (count
->integer
> num
))
1601 || !astnode_is_type(count
, INTEGER_NODE
) ) {
1602 astnode_add_child(flat
,
1603 astnode_create_storage(
1604 astnode_create_datatype(type
->datatype
, NULL
, flat
->loc
),
1605 astproc_fold_constants(
1606 astnode_create_arithmetic(
1608 astnode_clone(count
, flat
->loc
),
1609 astnode_create_integer(num
, flat
->loc
),
1621 t
= symtab_global_lookup(LHS(type
)->ident
);
1622 if (astnode_is_type(val
, NULL_NODE
)) {
1623 /* Output sizeof(type) bytes to fill in */
1624 astnode_add_child(flat
,
1625 astnode_create_storage(
1626 astnode_create_datatype(BYTE_DATATYPE
, NULL
, val
->loc
),
1627 astnode_clone(t
->struc
.size
, val
->loc
),
1634 flatten_struc_recursive(t
, val
, flat
);
1638 flatten_union_recursive(t
, val
, flat
);
1642 reduce_record(t
, val
, flat
);
1646 reduce_enum(t
, val
, flat
);
1655 /* Decrease fill amount according to field size */
1656 fill
= astproc_fold_constants(
1657 astnode_create_arithmetic(
1660 astnode_clone(e
->field
.size
, flat
->loc
),
1667 err(init
->loc
, "too many field initializers");
1669 else if (list
!= NULL
) {
1670 /* All fields not initialized; fill remainder of struc with zeroes */
1671 astnode_add_child(flat
,
1672 astnode_create_storage(
1673 astnode_create_datatype(BYTE_DATATYPE
, NULL
, flat
->loc
),
1679 astnode_finalize(fill
);
1685 * Converts data that is expressed in a high-level form (such as structure initializers)
1686 * to a simple sequence of bytes.
1687 * @param n The source node to flatten
1688 * @param type The type of data that n is an instance of
1689 * @param list List on which to append the resulting sequence of items (bytes/words/dwords)
1691 static void flatten_user_data(astnode
*n
, astnode
*type
, astnode
*list
)
1694 def
= symtab_global_lookup(LHS(type
)->ident
);
1696 switch (def
->type
) {
1698 flatten_struc_recursive(def
, n
, list
);
1702 flatten_union_recursive(def
, n
, list
);
1706 reduce_record(def
, n
, list
);
1710 reduce_enum(def
, n
, list
);
1719 /*---------------------------------------------------------------------------*/
1722 * Loads the character map specified by the node.
1723 * @param n Node of type CHARMAP_NODE
1725 static int load_charmap(astnode
*n
, void *arg
, astnode
**next
)
1727 /* TODO: should probably be done in the parsing phase (same path resolution as for INCSRC and INCBIN) */
1729 file
= astnode_get_child(n
, 0);
1730 if (charmap_parse(file
->file_path
, charmap
) == 0) {
1731 err(n
->loc
, "could not open `%s' for reading", file
->file_path
);
1737 * First-time processing of instruction node.
1738 * @param instr Node of type INSTRUCTION_NODE
1739 * @param arg Not used
1741 static int process_instruction(astnode
*instr
, void *arg
, astnode
**next
)
1745 err(instr
->loc
, "instructions not allowed in data segment");
1746 astnode_remove(instr
);
1747 astnode_finalize(instr
);
1751 expr
= astnode_get_child(instr
, 0);
1752 reduce_expression(expr
);
1758 * First-time processing of data node.
1759 * @param data Node of type DATA_NODE
1760 * @param arg Not used
1762 static int process_data(astnode
*data
, void *arg
, astnode
**next
)
1770 type
= astnode_get_child(data
, 0);
1771 assert(astnode_is_type(type
, DATATYPE_NODE
));
1773 err(data
->loc
, "value not allowed in data segment");
1774 /* Replace with storage node */
1777 astnode_create_storage(
1778 astnode_create_datatype(BYTE_DATATYPE
, NULL
, data
->loc
),
1779 astnode_create_integer(1, data
->loc
),
1783 astnode_finalize(data
);
1786 if (type
->datatype
== USER_DATATYPE
) {
1787 /* Make sure the type exists */
1788 if (symtab_global_lookup(LHS(type
)->ident
) == NULL
) {
1789 err(data
->loc
, "unknown type `%s'", LHS(type
)->ident
);
1790 astnode_remove(data
);
1791 astnode_finalize(data
);
1794 /* Attempt to reduce user data to native data */
1795 list
= astnode_create(LIST_NODE
, data
->loc
);
1796 for (expr
= type
->next_sibling
; expr
!= NULL
; expr
= expr
->next_sibling
) {
1797 flatten_user_data(expr
, type
, list
);
1799 /* Replace initializers with generated list */
1800 stmts
= astnode_remove_children(list
);
1801 astnode_replace(data
, stmts
);
1802 astnode_finalize(data
);
1803 astnode_finalize(list
);
1808 /* Go through the list of data values, replacing defines and folding constants */
1809 for (j
=1; j
<astnode_get_child_count(data
); j
++) {
1810 expr
= astnode_get_child(data
, j
);
1811 /* Substitute defines and fold constants */
1812 expr
= reduce_expression(expr
);
1813 /* If it's a string, replace by array of integers */
1814 /* (makes it easier to process later... favour regularity) */
1815 if (astnode_is_type(expr
, STRING_NODE
)) {
1816 astnode_remove_child(data
, expr
); /* Remove string */
1817 for (k
=strlen(expr
->string
)-1; k
>=0; k
--) {
1818 /* Check if we should map character from custom charmap */
1819 if (type
->datatype
== CHAR_DATATYPE
) {
1820 expr
->string
[k
] = charmap
[(unsigned)expr
->string
[k
]];
1822 /* Append character value to array */
1823 astnode_insert_child(data
, astnode_create_integer((unsigned char)expr
->string
[k
], data
->loc
), j
);
1825 if (type
->datatype
== CHAR_DATATYPE
) {
1826 /* It's normal byte array now */
1827 type
->datatype
= BYTE_DATATYPE
;
1829 j
+= strlen(expr
->string
)-1;
1830 astnode_finalize(expr
);
1837 * First-time processing of storage node.
1838 * @param storage Node of type STORAGE_NODE
1839 * @param arg Not used
1841 static int process_storage(astnode
*storage
, void *arg
, astnode
**next
)
1847 type
= LHS(storage
);
1848 expr
= RHS(storage
);
1849 /* If not BYTE_DATATYPE, multiply by word/dword-size */
1850 switch (type
->datatype
) {
1852 case CHAR_DATATYPE
: item_size
= 1; break;
1853 case WORD_DATATYPE
: item_size
= 2; break;
1854 case DWORD_DATATYPE
: item_size
= 4; break;
1855 default: item_size
= 1; break; // ### Hmmm...
1857 if (item_size
!= 1) {
1858 new_expr
= astnode_create_arithmetic(
1860 astnode_clone(expr
, expr
->loc
),
1861 astnode_create_integer(item_size
, expr
->loc
),
1864 astnode_replace(expr
, new_expr
);
1865 astnode_finalize(expr
);
1867 type
->datatype
= BYTE_DATATYPE
;
1869 /* Substitute defines and fold constants */
1870 expr
= reduce_expression(expr
);
1871 // TODO: Validate range somewhere else than here please... ???
1872 if (astnode_is_type(expr
, INTEGER_NODE
)) {
1873 if ((expr
->integer
<= 0) || (expr
->integer
>= 0x10000)) {
1874 err(storage
->loc
, "operand out of range");
1882 * @param equ Node of type EQU_NODE
1883 * @param arg Not used
1885 static int process_equ(astnode
*equ
, void *arg
, astnode
**next
)
1890 expr
= astnode_clone(astnode_get_child(equ
, 1), equ
->loc
);
1891 expr
= reduce_expression(expr
);
1892 id
= astnode_get_child(equ
, 0);
1893 assert(astnode_is_type(id
, IDENTIFIER_NODE
));
1894 e
= symtab_lookup(id
->ident
);
1896 // TODO: Check that expression is a constant?
1897 symtab_enter(id
->ident
, CONSTANT_SYMBOL
, expr
, 0);
1899 /* Symbol is being redefined */
1900 /* This is not allowed for EQU equate! */
1901 if (!astnode_equal((astnode
*)(e
->def
), expr
)) {
1902 warn(equ
->loc
, "redefinition of `%s' is not identical; ignored", id
->ident
);
1905 astnode_remove(equ
);
1906 astnode_finalize(equ
);
1912 * @param assign Node of type ASSIGN_NODE
1913 * @param arg Not used
1915 static int process_assign(astnode
*assign
, void *arg
, astnode
**next
)
1920 /* If it's part of ENUM declaration, don't touch */
1921 if (astnode_has_ancestor_of_type(assign
, ENUM_DECL_NODE
)) {
1924 /* Very similar to EQU, except symbol 1) can be
1925 redefined and 2) is volatile (see end of proc) */
1926 expr
= astnode_clone(astnode_get_child(assign
, 1), assign
->loc
);
1927 expr
= reduce_expression(expr
);
1928 id
= astnode_get_child(assign
, 0);
1929 assert(astnode_is_type(id
, IDENTIFIER_NODE
));
1930 e
= symtab_lookup(id
->ident
);
1932 /* Symbol is being defined for the first time */
1933 /* Note that the VOLATILE_FLAG is set */
1934 symtab_enter(id
->ident
, CONSTANT_SYMBOL
, expr
, VOLATILE_FLAG
);
1936 /* Symbol is being redefined */
1937 /* This is OK for ASSIGN equate, simply replace definition */
1938 // ### store a list of definitions, otherwise we leak
1939 expr
->loc
= e
->def
->loc
;
1942 astnode_remove(assign
);
1943 astnode_finalize(assign
);
1948 * Process IFDEF-node.
1949 * @param ifdef Node of type IFDEF_NODE
1950 * @param arg Not used
1952 static int process_ifdef(astnode
*ifdef
, void *arg
, astnode
**next
)
1957 id
= astnode_get_child(ifdef
, 0);
1958 assert(astnode_is_type(id
, IDENTIFIER_NODE
));
1959 e
= symtab_lookup(id
->ident
);
1961 /* Symbol is defined. */
1962 /* Replace IFDEF node by the true-branch statement list */
1963 stmts
= astnode_remove_children(astnode_get_child(ifdef
, 1));
1964 astnode_replace(ifdef
, stmts
);
1967 /* Symbol is not defined. */
1968 /* Replace IFDEF node by the false-branch statement list (if any) */
1969 stmts
= astnode_remove_children( astnode_get_child(ifdef
, 2));
1970 if (stmts
!= NULL
) {
1971 astnode_replace(ifdef
, stmts
);
1974 astnode_remove(ifdef
);
1977 astnode_finalize(ifdef
);
1982 * Process IFNDEF-node.
1983 * @param ifndef Node of type IFNDEF_NODE
1984 * @param arg Not used
1986 static int process_ifndef(astnode
*ifndef
, void *arg
, astnode
**next
)
1991 id
= astnode_get_child(ifndef
, 0);
1992 assert(astnode_is_type(id
, IDENTIFIER_NODE
));
1993 e
= symtab_lookup(id
->ident
);
1995 /* Symbol is not defined. */
1996 /* Replace IFNDEF node by the true-branch statement list */
1997 stmts
= astnode_remove_children(astnode_get_child(ifndef
, 1));
1998 astnode_replace(ifndef
, stmts
);
2001 /* Symbol is defined. */
2002 /* Replace IFNDEF node by the false-branch statement list, if any */
2003 stmts
= astnode_remove_children(astnode_get_child(ifndef
, 2));
2004 if (stmts
!= NULL
) {
2005 astnode_replace(ifndef
, stmts
);
2008 astnode_remove(ifndef
);
2011 astnode_finalize(ifndef
);
2017 * @param if_node Node of type IF_NODE
2018 * @param arg Not used
2020 static int process_if(astnode
*if_node
, void *arg
, astnode
**next
)
2026 /* IF_NODE has a list of CASE, DEFAULT nodes as children */
2027 for (c
= astnode_get_first_child(if_node
); c
!= NULL
; c
= astnode_get_next_sibling(c
) ) {
2028 if (astnode_is_type(c
, CASE_NODE
)) {
2029 /* The expression which is being tested */
2030 expr
= astnode_get_child(c
, 0);
2031 /* Try to reduce expression to literal */
2032 expr
= reduce_expression(expr
);
2033 /* Resulting expression must be an integer literal,
2034 since this is static evaluation.
2035 In other words, it can't contain label references.
2037 if (astnode_is_type(expr
, INTEGER_NODE
)) {
2038 /* Non-zero is true, zero is false */
2039 if (expr
->integer
) {
2040 /* Replace IF node by the true-branch statement list */
2041 stmts
= astnode_remove_children( astnode_get_child(c
, 1) );
2042 astnode_replace(if_node
, stmts
);
2043 astnode_finalize(if_node
);
2048 /* Error, expression is not constant */
2049 err(expr
->loc
, "conditional expression does not evaluate to literal");
2051 } else { /* DEFAULT_NODE */
2052 /* Replace IF node by the false-branch statement list */
2053 stmts
= astnode_remove_children(c
);
2054 astnode_replace(if_node
, stmts
);
2055 astnode_finalize(if_node
);
2060 /* No match, remove IF node from AST */
2061 astnode_remove(if_node
);
2062 astnode_finalize(if_node
);
2067 * Process dataseg-node.
2068 * @param dataseg Node of type DATASEG_NODE
2069 * @param arg Not used
2071 static int process_dataseg(astnode
*dataseg
, void *arg
, astnode
**next
)
2073 symbol_modifiers
= dataseg
->modifiers
;
2074 in_dataseg
= 1; /* true */
2079 * Process codeseg-node.
2080 * @param codeseg Node of type CODESEG_NODE
2081 * @param arg Not used
2083 static int process_codeseg(astnode
*codeseg
, void *arg
, astnode
**next
)
2085 symbol_modifiers
= 0;
2086 in_dataseg
= 0; /* false */
2092 * @param n Node of type ORG_NODE
2093 * @param arg Not used
2095 static int process_org(astnode
*org
, void *arg
, astnode
**next
)
2097 if (!xasm_args
.pure_binary
) {
2098 err(org
->loc
, "org directive can only be used when output format is pure 6502 binary");
2100 astnode
*addr
= astnode_get_child(org
, 0);
2101 addr
= reduce_expression_complete(addr
);
2102 if (astnode_is_type(addr
, INTEGER_NODE
)) {
2104 if ((addr
->integer
< 0) || (addr
->integer
>= 0x10000)) {
2105 err(org
->loc
, "org address out of 64K range");
2108 err(org
->loc
, "org address does not evaluate to literal");
2109 astnode_remove(org
);
2110 astnode_finalize(org
);
2117 * Process REPT node.
2118 * @param rept Node of type REPT_NODE
2119 * @param arg Not used
2121 static int process_rept(astnode
*rept
, void *arg
, astnode
**next
)
2126 count
= astnode_get_child(rept
, 0);
2127 /* Try to reduce count expression to literal */
2128 count
= reduce_expression_complete(count
);
2129 /* Resulting expression must be an integer literal,
2130 since this is static evaluation.
2132 if (astnode_is_type(count
, INTEGER_NODE
)) {
2133 if (count
->integer
< 0) {
2134 warn(rept
->loc
, "REPT ignored; negative repeat count (%d)", count
->integer
);
2135 astnode_remove(rept
);
2136 astnode_finalize(rept
);
2137 } else if (count
->integer
> 0) {
2138 /* Expand body <count> times */
2139 list
= astnode_clone(astnode_get_child(rept
, 1), rept
->loc
);
2140 stmts
= astnode_remove_children(list
);
2141 astnode_finalize(list
);
2142 while (--count
->integer
> 0) {
2143 list
= astnode_clone(astnode_get_child(rept
, 1), rept
->loc
);
2144 astnode_add_sibling(stmts
, astnode_remove_children(list
) );
2145 astnode_finalize(list
);
2147 astnode_replace(rept
, stmts
);
2148 astnode_finalize(rept
);
2152 astnode_remove(rept
);
2153 astnode_finalize(rept
);
2156 err(rept
->loc
, "repeat count does not evaluate to literal");
2157 astnode_remove(rept
);
2158 astnode_finalize(rept
);
2164 * Process WHILE node.
2165 * @param while_node Node of type WHILE_NODE
2166 * @param arg Not used
2168 static int process_while(astnode
*while_node
, void *arg
, astnode
**next
)
2173 expr
= astnode_get_child(while_node
, 0);
2174 /* Try to reduce expression to literal */
2175 expr
= reduce_expression(astnode_clone(expr
, expr
->loc
));
2176 /* Resulting expression must be an integer literal,
2177 since this is static evaluation.
2179 if (astnode_is_type(expr
, INTEGER_NODE
)) {
2180 /* Expand body if the expression is true */
2181 if (expr
->integer
) {
2182 list
= astnode_clone(astnode_get_child(while_node
, 1), while_node
->loc
);
2183 stmts
= astnode_remove_children(list
);
2184 astnode_finalize(list
);
2185 astnode_replace(while_node
, stmts
);
2186 astnode_add_sibling(stmts
, while_node
); /* Clever huh? */
2189 astnode_remove(while_node
);
2190 astnode_finalize(while_node
);
2193 err(while_node
->loc
, "while expression does not evaluate to literal");
2194 astnode_remove(while_node
);
2195 astnode_finalize(while_node
);
2197 astnode_finalize(expr
);
2201 /*---------------------------------------------------------------------------*/
2204 * Enters a macro into the symbol table.
2205 * @param n Must be a node of type MACRO_DECL_NODE
2206 * @param arg Not used
2208 static int enter_macro(astnode
*macro_def
, void *arg
, astnode
**next
)
2210 astnode
*id
= astnode_get_child(macro_def
, 0);
2211 assert(astnode_get_type(id
) == IDENTIFIER_NODE
);
2212 if (symtab_enter(id
->ident
, MACRO_SYMBOL
, macro_def
, 0) == NULL
) {
2213 /* ### This could be allowed, you know... */
2214 err(macro_def
->loc
, "duplicate symbol `%s'", id
->ident
);
2216 astnode_remove(macro_def
);
2221 * Enters a label into the symbol table.
2222 * @param label Must be a node of type LABEL_NODE
2224 static int enter_label(astnode
*label
, void *arg
, astnode
**next
)
2228 /* Make sure it's unique first */
2229 if (symtab_lookup(label
->ident
)) {
2230 err(label
->loc
, "duplicate symbol `%s'", label
->ident
);
2231 astnode_remove(label
);
2232 astnode_finalize(label
);
2234 e
= symtab_enter(label
->ident
, LABEL_SYMBOL
, label
, (in_dataseg
? DATA_FLAG
: 0) | symbol_modifiers
);
2235 /* Check if hardcoded address */
2236 addr
= reduce_expression_complete(RHS(label
));
2237 if (astnode_is_type(addr
, INTEGER_NODE
)) {
2239 e
->address
= addr
->integer
;
2240 e
->flags
|= ADDR_FLAG
;
2241 } else if (!astnode_is_type(addr
, CURRENT_PC_NODE
)) {
2242 err(label
->loc
, "label address does not evaluate to literal");
2250 * Enters a variable declaration in symbol table.
2251 * @param var Must be a node of type VAR_DECL_NODE
2253 static int enter_var(astnode
*var
, void *arg
, astnode
**next
)
2256 astnode
*id
= LHS(var
);
2257 assert(astnode_get_type(id
) == IDENTIFIER_NODE
);
2258 e
= symtab_lookup(id
->ident
);
2260 if (!(e
->flags
& EXTRN_FLAG
) || (e
->type
!= VAR_SYMBOL
)) {
2261 err(var
->loc
, "duplicate symbol `%s'", id
->ident
);
2262 astnode_remove(var
);
2263 astnode_finalize(var
);
2266 /* Allow a symbol declared as extrn to be defined in the same unit */
2267 symtab_remove(id
->ident
);
2269 if ((var
->modifiers
& ZEROPAGE_FLAG
) && !in_dataseg
) {
2270 warn(var
->loc
, "zeropage modifier has no effect in code segment");
2271 var
->modifiers
&= ~ZEROPAGE_FLAG
;
2273 symtab_enter(id
->ident
, VAR_SYMBOL
, astnode_clone(RHS(var
), var
->loc
), (in_dataseg
? DATA_FLAG
: 0) | var
->modifiers
| symbol_modifiers
);
2278 * Enters a procedure declaration in symbol table.
2279 * @param proc Must be a node of type PROC_NODE
2281 static int enter_proc(astnode
*proc
, void *arg
, astnode
**next
)
2286 err(proc
->loc
, "procedures not allowed in data segment");
2287 astnode_remove(proc
);
2288 astnode_finalize(proc
);
2292 assert(astnode_get_type(id
) == IDENTIFIER_NODE
);
2293 e
= symtab_lookup(id
->ident
);
2295 if (!(e
->flags
& EXTRN_FLAG
) || (e
->type
!= PROC_SYMBOL
)) {
2296 err(proc
->loc
, "duplicate symbol `%s'", id
->ident
);
2297 astnode_remove(proc
);
2298 astnode_finalize(proc
);
2301 /* Allow a symbol declared as extrn to be defined in the same unit */
2302 symtab_remove(id
->ident
);
2304 /* Enter it! RHS(proc) is the list of procedure statements */
2305 symtab_enter(id
->ident
, PROC_SYMBOL
, RHS(proc
), (in_dataseg
? DATA_FLAG
: 0) );
2311 * Enters a simple <identifier> <storage> structure member.
2312 * @param c Node of type VAR_DECL_NODE
2313 * @param offset Offset of this field
2314 * @param plist List of symbol table's entries
2315 * @param struc_id Structure identifier (for error messages)
2316 * @return New offset (old offset + size of this field)
2318 static astnode
*enter_struc_atomic_field(astnode
*c
, astnode
*offset
, ordered_field_list
***plist
, astnode
*struc_id
)
2321 astnode
*field_data
;
2322 astnode
*field_size
;
2324 /* c has two children: id and STORAGE_NODE */
2326 assert(astnode_get_type(field_id
) == IDENTIFIER_NODE
);
2327 field_data
= RHS(c
);
2328 reduce_expression(RHS(field_data
));
2329 if (astnode_is_type(field_data
, DATA_NODE
)) {
2330 err(c
->loc
, "data initialization not allowed here");
2336 astnode_clone(field_data
, field_data
->loc
),
2340 err(c
->loc
, "duplicate symbol `%s' in structure `%s'", field_id
->ident
, struc_id
->ident
);
2343 /* Add to ordered list of fields */
2344 (**plist
) = malloc(sizeof(ordered_field_list
));
2345 (**plist
)->entry
= fe
;
2346 (**plist
)->next
= NULL
;
2347 *plist
= &((**plist
)->next
);
2348 /* Set field offset */
2349 fe
->field
.offset
= astnode_clone(offset
, offset
->loc
);
2350 /* Calculate field size in bytes: sizeof(datatype) * count */
2351 field_size
= astnode_create_arithmetic(
2353 astnode_create_sizeof(astnode_clone(LHS(field_data
), field_data
->loc
), field_data
->loc
),
2354 astnode_clone(RHS(field_data
), field_data
->loc
),
2357 field_size
= reduce_expression(field_size
);
2358 /* Set field size */
2359 fe
->field
.size
= astnode_clone(field_size
, field_size
->loc
);
2360 /* Add field size to total offset */
2361 offset
= astnode_create_arithmetic(
2367 offset
= reduce_expression(offset
);
2371 static void enter_union_fields(symtab_entry
*, astnode
*);
2374 * Attempts to enter an (anonymous) union's members into structure's symbol table.
2375 * @param n Node of type UNION_DECL_NODE
2376 * @param offset Current parent structure offset
2377 * @param plist Ordered list of parent structure's fields
2379 astnode
*enter_struc_union_field(astnode
*n
, astnode
*offset
, ordered_field_list
***plist
, astnode
*struc_id
)
2381 ordered_field_list
*ls
;
2388 if (astnode_is_type(union_id
, IDENTIFIER_NODE
)) {
2389 err(n
->loc
, "anonymous union expected");
2392 snprintf(id_str
, sizeof (id_str
), "%d", id
++);
2393 se
= symtab_enter(id_str
, UNION_SYMBOL
, n
, 0);
2394 enter_union_fields(se
, n
);
2395 /* Add to ordered list of fields */
2396 (**plist
) = malloc(sizeof(ordered_field_list
));
2397 (**plist
)->entry
= se
;
2398 (**plist
)->next
= NULL
;
2399 *plist
= &((**plist
)->next
);
2400 /* Add to parent structure as well, with same offsets */
2401 for (ls
= se
->struc
.fields
; ls
!= NULL
; ls
= ls
->next
) {
2402 /* Try to enter field in structure's symbol table */
2406 astnode_clone(ls
->entry
->def
, ls
->entry
->def
->loc
),
2410 err(ls
->entry
->def
->loc
, "duplicate symbol `%s' in structure `%s'", ls
->entry
->id
, struc_id
->ident
);
2413 /* Set field offset */
2414 fe
->field
.offset
= astnode_clone(offset
, offset
->loc
);
2415 /* Set field size */
2416 fe
->field
.size
= astnode_clone(se
->struc
.size
, offset
->loc
);
2418 /* Advance offset by size of union */
2419 offset
= astnode_create_arithmetic(
2422 astnode_clone(se
->struc
.size
, offset
->loc
),
2425 offset
= reduce_expression(offset
);
2430 * Enters struc type into symbol table based on AST node.
2431 * - Creates a symbol table for the structure
2432 * - Validates and enters all its fields
2433 * - Calculates offset of each field in the structure, and total size
2434 * @param struc_def Node of type STRUC_DECL_NODE
2436 static int enter_struc(astnode
*struc_def
, void *arg
, astnode
**next
)
2438 ordered_field_list
**plist
;
2442 astnode
*struc_id
= LHS(struc_def
);
2443 assert(astnode_is_type(struc_id
, IDENTIFIER_NODE
));
2444 se
= symtab_enter(struc_id
->ident
, STRUC_SYMBOL
, struc_def
, 0);
2446 err(struc_def
->loc
, "duplicate symbol `%s'", struc_id
->ident
);
2448 /* Put the fields of the structure in local symbol table */
2449 se
->symtab
= symtab_create();
2450 offset
= astnode_create_integer(0, struc_def
->loc
); /* offset = 0 */
2451 plist
= &se
->struc
.fields
;
2452 for (c
= struc_id
->next_sibling
; c
!= NULL
; c
= c
->next_sibling
) {
2453 /* Check if it's a field declaration */
2454 if (astnode_is_type(c
, VAR_DECL_NODE
)) {
2455 offset
= enter_struc_atomic_field(c
, offset
, &plist
, struc_id
);
2457 /* Check if (anonymous) union */
2458 else if (astnode_is_type(c
, UNION_DECL_NODE
)) {
2459 offset
= enter_struc_union_field(c
, offset
, &plist
, struc_id
);
2461 err(c
->loc
, "field declaration expected");
2465 /* Store total size of structure */
2466 se
->struc
.size
= offset
;
2467 /* Restore previous symbol table */
2470 /* ### Remove STRUC node from AST */
2471 // astnode_remove(struc_def);
2472 // astnode_finalize(struc_def);
2477 * Enters fields of union into its symbol table.
2479 static void enter_union_fields(symtab_entry
*se
, astnode
*union_def
)
2481 ordered_field_list
**plist
;
2484 astnode
*field_data
;
2485 astnode
*field_size
;
2488 se
->symtab
= symtab_create();
2489 se
->struc
.size
= astnode_create_integer(0, union_def
->loc
);
2490 plist
= &se
->struc
.fields
;
2491 /* Process field declarations */
2492 for (c
= RHS(union_def
); c
!= NULL
; c
= c
->next_sibling
) {
2493 if (!astnode_is_type(c
, VAR_DECL_NODE
)) {
2494 err(c
->loc
, "field declaration expected");
2497 /* c has two children: id and STORAGE_NODE */
2499 assert(astnode_get_type(field_id
) == IDENTIFIER_NODE
);
2500 field_data
= RHS(c
);
2501 reduce_expression(RHS(field_data
));
2502 if (astnode_is_type(field_data
, DATA_NODE
)) {
2503 err(c
->loc
, "data initialization not allowed here");
2506 /* Calculate field size in bytes: sizeof(datatype) * count */
2507 field_size
= astnode_create_arithmetic(
2509 astnode_create_sizeof(astnode_clone(LHS(field_data
), field_data
->loc
), field_data
->loc
),
2510 astnode_clone(RHS(field_data
), field_data
->loc
),
2513 field_size
= reduce_expression(field_size
);
2514 if (!astnode_is_type(field_size
, INTEGER_NODE
)) {
2515 err(c
->loc
, "union member must be of constant size");
2516 astnode_finalize(field_size
);
2517 /* Use default size: 1 byte */
2518 field_size
= astnode_create_integer(1, field_data
->loc
);
2523 astnode_clone(field_data
, field_data
->loc
),
2527 err(c
->loc
, "duplicate symbol `%s' in union `%s'", field_id
->ident
, se
->id
);
2528 astnode_finalize(field_size
);
2531 /* Add to ordered list of fields */
2532 (*plist
) = malloc(sizeof(ordered_field_list
));
2533 (*plist
)->entry
= fe
;
2534 (*plist
)->next
= NULL
;
2535 plist
= &((*plist
)->next
);
2536 /* Set field offset (0 for all) and size */
2537 fe
->field
.offset
= astnode_create_integer(0, union_def
->loc
);
2538 fe
->field
.size
= astnode_clone(field_size
, field_size
->loc
);
2539 /* See if field size of this member is largest so far */
2540 if (se
->struc
.size
->integer
< field_size
->integer
) {
2541 astnode_finalize(se
->struc
.size
);
2542 se
->struc
.size
= field_size
;
2544 astnode_finalize(field_size
);
2551 * Enters union type into symbol table based on AST node.
2552 * @param union_def Node of type UNION_DECL_NODE
2554 static int enter_union(astnode
*union_def
, void *arg
, astnode
**next
)
2557 astnode
*union_id
= astnode_get_child(union_def
, 0);
2558 assert(astnode_is_type(union_id
, IDENTIFIER_NODE
));
2559 if (astnode_is_type(union_id
, NULL_NODE
)) {
2560 err(union_def
->loc
, "anonymous union not allowed in global scope");
2562 assert(astnode_get_type(union_id
) == IDENTIFIER_NODE
);
2563 se
= symtab_enter(union_id
->ident
, UNION_SYMBOL
, union_def
, 0);
2565 err(union_def
->loc
, "duplicate symbol `%s'", union_id
->ident
);
2567 /* Put the fields of the union in local symbol table */
2568 enter_union_fields(se
, union_def
);
2571 /* ### Remove UNION node from AST */
2572 // astnode_remove(union_def);
2573 // astnode_finalize(union_def);
2578 * Enters enumerated type into symbol table based on AST node.
2579 * @param n Node of type ENUM_DECL_NODE
2581 static int enter_enum(astnode
*enum_def
, void *arg
, astnode
**next
)
2587 astnode
*enum_id
= astnode_get_child(enum_def
, 0);
2588 assert(astnode_get_type(enum_id
) == IDENTIFIER_NODE
);
2589 se
= symtab_enter(enum_id
->ident
, ENUM_SYMBOL
, enum_def
, 0);
2591 err(enum_def
->loc
, "duplicate symbol `%s'", enum_id
->ident
);
2593 /* Add all the enum symbols to its own symbol table */
2594 se
->symtab
= symtab_create();
2596 for (c
= enum_id
->next_sibling
; c
!= NULL
; c
= c
->next_sibling
) {
2597 if (astnode_is_type(c
, IDENTIFIER_NODE
)) {
2600 val
= astnode_create_integer(0, c
->loc
);
2602 val
= astnode_create_integer(val
->integer
+1, c
->loc
);
2606 val
= reduce_expression_complete(astnode_clone(RHS(c
), RHS(c
)->loc
));
2607 if (!astnode_is_type(val
, INTEGER_NODE
)) {
2608 err(c
->loc
, "initializer does not evaluate to integer literal");
2609 astnode_finalize(val
);
2610 /* Use default value */
2611 val
= astnode_create_integer(0, c
->loc
);
2614 if (symtab_enter(id
->ident
, CONSTANT_SYMBOL
, val
, 0) == NULL
) {
2615 err(c
->loc
, "duplicate symbol `%s' in enumeration `%s'", id
->ident
, enum_id
->ident
);
2621 /* ### Remove ENUM node from AST */
2622 // astnode_remove(enum_def);
2623 // astnode_finalize(enum_def);
2628 * Enters record type into symbol table based on AST node.
2629 * @param n Node of type RECORD_DECL_NODE
2631 static int enter_record(astnode
*record_def
, void *arg
, astnode
**next
)
2633 ordered_field_list
**plist
;
2636 astnode
*field_width
;
2641 astnode
*record_id
= astnode_get_child(record_def
, 0);
2642 assert(astnode_get_type(record_id
) == IDENTIFIER_NODE
);
2643 se
= symtab_enter(record_id
->ident
, RECORD_SYMBOL
, record_def
, 0);
2645 err(record_def
->loc
, "duplicate symbol `%s'", record_id
->ident
);
2648 /* Add all the record fields to record's own symbol table */
2649 se
->symtab
= symtab_create();
2651 plist
= &se
->struc
.fields
;
2652 for (c
= record_id
->next_sibling
; c
!= NULL
; c
= c
->next_sibling
) {
2653 /* c has two children: field identifier and its width */
2655 field_width
= astnode_clone(reduce_expression(RHS(c
)), RHS(c
)->loc
);
2656 /* Validate the width -- must be positive integer literal */
2657 if (!astnode_is_type(field_width
, INTEGER_NODE
)) {
2658 err(c
->loc
, "record member `%s' is not of constant size", field_id
->ident
);
2661 if ((field_width
->integer
<= 0) || (field_width
->integer
>= 8)) {
2662 err(c
->loc
, "width of record member `%s' is out of range (%d)", field_id
->ident
, field_width
->integer
);
2665 /* Attempt to enter field in record's symbol table */
2666 fe
= symtab_enter(field_id
->ident
, VAR_SYMBOL
, c
, 0);
2668 err(c
->loc
, "duplicate symbol `%s' in record `%s'", field_id
->ident
, record_id
->ident
);
2671 /* Add to ordered list of fields */
2672 (*plist
) = malloc(sizeof(ordered_field_list
));
2673 (*plist
)->entry
= fe
;
2674 (*plist
)->next
= NULL
;
2675 plist
= &((*plist
)->next
);
2676 /* Set field offset */
2677 offset
= offset
- field_width
->integer
;
2678 fe
->field
.offset
= astnode_create_integer(offset
, c
->loc
);
2679 /* Set field size (width) */
2680 fe
->field
.size
= field_width
;
2684 err(record_def
->loc
, "size of record `%s' (%d) exceeds 8 bits", record_id
->ident
, size
);
2686 /* Set size of record (in bits) */
2687 se
->struc
.size
= astnode_create_integer(size
, record_def
->loc
);
2691 /* ### Remove RECORD node from AST */
2692 // astnode_remove(record_def);
2693 // astnode_finalize(record_def);
2698 * Globalizes a local.
2699 * The node is morphed into its global equivalent (LABEL_NODE or IDENTIFIER_NODE).
2700 * @param n A node of type LOCAL_LABEL_NODE or LOCAL_ID_NODE
2701 * @param arg Pointer to namespace counter
2703 static int globalize_local(astnode
*n
, void *arg
, astnode
**next
)
2706 /* Make it global by appending namespace counter to the id */
2707 snprintf(str
, sizeof (str
), "#%d", label_count
);
2708 if (astnode_is_type(n
, LOCAL_LABEL_NODE
)) {
2709 /* Local label definition, use label field */
2710 n
->label
= realloc(n
->label
, strlen(n
->label
)+strlen(str
)+1);
2711 strcat(n
->label
, str
);
2712 /* This node is now a unique, global label */
2713 n
->type
= LABEL_NODE
;
2714 /* Make sure it's unique */
2715 if (symtab_lookup(n
->label
)) {
2716 err(n
->loc
, "duplicate symbol `%s'", n
->label
);
2718 astnode_finalize(n
);
2721 symtab_enter(n
->label
, LABEL_SYMBOL
, n
, (in_dataseg
? DATA_FLAG
: 0) );
2724 /* Local label reference, use ident field */
2725 n
->ident
= realloc(n
->ident
, strlen(n
->ident
)+strlen(str
)+1);
2726 strcat(n
->ident
, str
);
2727 /* This node is now a unique, global identifier */
2728 n
->type
= IDENTIFIER_NODE
;
2734 * Tags symbols as extrn.
2735 * @param n A node of type EXTRN_NODE
2737 static int tag_extrn_symbols(astnode
*extrn
, void *arg
, astnode
**next
)
2743 type
= astnode_get_child(extrn
, 0);
2744 /* Go through the list of identifiers */
2745 list
= astnode_get_child(extrn
, 1);
2746 for (id
=astnode_get_first_child(list
); id
!= NULL
; id
=astnode_get_next_sibling(id
) ) {
2747 e
= symtab_lookup(id
->ident
);
2749 if (!(e
->flags
& EXTRN_FLAG
)) {
2750 /* Error, can't import a symbol that's defined locally! */
2751 // TODO: this is okay?
2752 err(extrn
->loc
, "`%s' declared as extrn but is defined locally", id
->ident
);
2756 // TODO: store external unit name
2757 switch (astnode_get_type(type
)) {
2759 symtab_enter(id
->ident
, VAR_SYMBOL
, astnode_create_data(astnode_clone(type
, extrn
->loc
), NULL
, extrn
->loc
), EXTRN_FLAG
);
2763 /* type->integer is (LABEL|PROC)_SYMBOL */
2764 symtab_enter(id
->ident
, type
->integer
, NULL
, EXTRN_FLAG
);
2772 astnode_remove(extrn
);
2773 astnode_finalize(extrn
);
2780 static int process_message(astnode
*message
, void *arg
, astnode
**next
)
2782 astnode
*expr
= reduce_expression_complete(LHS(message
));
2783 if (astnode_is_type(expr
, STRING_NODE
)) {
2784 printf("%s\n", expr
->string
);
2785 } else if (astnode_is_type(expr
, INTEGER_NODE
)) {
2786 printf("%d\n", expr
->integer
);
2788 err(expr
->loc
, "string or integer argument expected");
2790 astnode_remove(message
);
2791 astnode_finalize(message
);
2798 static int process_warning(astnode
*warning
, void *arg
, astnode
**next
)
2800 astnode
*expr
= reduce_expression_complete(LHS(warning
));
2801 if (astnode_is_type(expr
, STRING_NODE
)) {
2802 warn(warning
->loc
, expr
->string
);
2804 err(warning
->loc
, "string argument expected");
2806 astnode_remove(warning
);
2807 astnode_finalize(warning
);
2814 static int process_error(astnode
*error
, void *arg
, astnode
**next
)
2816 astnode
*expr
= reduce_expression_complete(LHS(error
));
2817 if (astnode_is_type(expr
, STRING_NODE
)) {
2818 err(error
->loc
, expr
->string
);
2820 err(expr
->loc
, "string argument expected");
2822 astnode_remove(error
);
2823 astnode_finalize(error
);
2828 * Processes a forward branch declaration.
2829 * @param forward_branch Node of type FORWARD_BRANCH_DECL_NODE
2830 * @param arg Not used
2832 static int process_forward_branch_decl(astnode
*n
, void *arg
, astnode
**next
)
2837 assert(!strchr(n
->ident
, '#'));
2838 /* Get branch info structure for label (+, ++, ...) */
2839 forward_branch_info
*fwd
= &forward_branch
[strlen(n
->ident
)-1];
2840 /* Morph n to globally unique label */
2841 snprintf(str
, sizeof (str
), "#%d", fwd
->counter
);
2842 n
->label
= (char *)realloc(n
->ident
, strlen(n
->ident
)+strlen(str
)+1);
2843 strcat(n
->label
, str
);
2844 n
->type
= LABEL_NODE
;
2845 symtab_enter(n
->label
, LABEL_SYMBOL
, n
, 0);
2846 /* Fix reference identifiers */
2847 for (i
=0; i
<fwd
->index
; i
++) {
2849 l
->ident
= (char *)realloc(l
->ident
, strlen(n
->ident
)+1);
2850 strcpy(l
->ident
, n
->ident
);
2852 /* Prepare for next declaration */
2859 * Processes a backward branch declaration.
2860 * @param n Node of type BACKWARD_BRANCH_DECL_NODE
2861 * @param arg Not used
2863 static int process_backward_branch_decl(astnode
*n
, void *arg
, astnode
**next
)
2866 assert(!strchr(n
->ident
, '#'));
2867 /* Get branch info */
2868 backward_branch_info
*bwd
= &backward_branch
[strlen(n
->ident
)-1];
2870 /* Morph n to globally unique label */
2871 snprintf(str
, sizeof (str
), "#%d", bwd
->counter
);
2872 n
->label
= (char *)realloc(n
->ident
, strlen(n
->ident
)+strlen(str
)+1);
2873 strcat(n
->label
, str
);
2874 n
->type
= LABEL_NODE
;
2875 symtab_enter(n
->label
, LABEL_SYMBOL
, n
, 0);
2876 /* Prepare for next declaration */
2882 * Processes a forward branch label reference.
2883 * @param n Node of type FORWARD_BRANCH_NODE
2884 * @param arg Not used
2886 static int process_forward_branch(astnode
*n
, void *arg
, astnode
**next
)
2888 /* Add n to proper forward_branch array */
2889 forward_branch_info
*fwd
= &forward_branch
[strlen(n
->ident
)-1];
2890 fwd
->refs
[fwd
->index
++] = n
;
2891 /* Change to identifier node */
2892 n
->type
= IDENTIFIER_NODE
;
2897 * Processes a backward branch label reference.
2898 * @param n Node of type BACKWARD_BRANCH_NODE
2899 * @param arg Not used
2901 static int process_backward_branch(astnode
*n
, void *arg
, astnode
**next
)
2903 /* Get branch info */
2904 backward_branch_info
*bwd
= &backward_branch
[strlen(n
->ident
)-1];
2905 /* Make sure it's a valid reference */
2906 if (bwd
->decl
!= NULL
) {
2908 n
->ident
= (char *)realloc(n
->ident
, strlen(bwd
->decl
->ident
)+1);
2909 strcpy(n
->ident
, bwd
->decl
->ident
);
2911 /* Change to identifier node */
2912 n
->type
= IDENTIFIER_NODE
;
2916 /*---------------------------------------------------------------------------*/
2918 static int is_field_ref(astnode
*n
)
2920 astnode
*p
= astnode_get_parent(n
);
2922 if (astnode_is_type(p
, DOT_NODE
)) return 1;
2923 /* Case 2: id.id[expr] */
2924 if (astnode_is_type(p
, INDEX_NODE
) && (n
== LHS(p
)) && astnode_is_type(astnode_get_parent(p
), DOT_NODE
) ) return 1;
2929 * Checks that the given identifier node is present in symbol table.
2930 * Issues error if it is not, and replaces with integer 0.
2931 * @param n A node of type IDENTIFIER_NODE
2933 static int validate_ref(astnode
*n
, void *arg
, astnode
**next
)
2936 symbol_ident_list list
;
2937 symtab_entry
*enum_def
;
2939 if (is_field_ref(n
)) {
2940 return 1; /* Validated by validate_dotref() */
2942 symtab_entry
* e
= symtab_lookup(n
->ident
);
2944 /* Maybe it is part of an enumeration */
2945 symtab_list_type(ENUM_SYMBOL
, &list
);
2946 for (i
=0; i
<list
.size
; i
++) {
2947 enum_def
= symtab_lookup(list
.idents
[i
]);
2948 symtab_push(enum_def
->symtab
);
2949 e
= symtab_lookup(n
->ident
);
2952 /* Replace id by SCOPE_NODE */
2953 astnode
*scope
= astnode_create_scope(
2954 astnode_create_identifier(enum_def
->id
, n
->loc
),
2955 astnode_clone(n
, n
->loc
), n
->loc
);
2956 astnode_replace(n
, scope
);
2957 astnode_finalize(n
);
2963 symtab_list_finalize(&list
);
2965 strtok(n
->ident
, "#"); /* Remove globalize junk */
2966 // err(n->loc, "unknown symbol `%s'", n->ident);
2967 /* ### Replace by integer 0 */
2968 //astnode_replace(n, astnode_create_integer(0, n->loc) );
2969 //astnode_finalize(n);
2970 warn(n
->loc
, "`%s' undeclared; assuming external label", n
->ident
);
2971 e
= symtab_enter(n
->ident
, LABEL_SYMBOL
, NULL
, EXTRN_FLAG
);
2980 * Validates top-level (not part of structure) indexed identifier.
2981 * @param n Node of type INDEX_NODE
2982 * @param arg Not used
2984 static int validate_index(astnode
*n
, void *arg
, astnode
**next
)
2989 if (is_field_ref(LHS(n
))) {
2990 return 1; /* Validated by validate_dotref() */
2993 if (!astnode_is_type(id
, IDENTIFIER_NODE
)) {
2994 err(n
->loc
, "identifier expected");
2995 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
2996 astnode_finalize(n
);
2999 e
= symtab_lookup(id
->ident
);
3002 if (!astnode_is_type(type
, DATATYPE_NODE
)) {
3003 err(n
->loc
, "`%s' cannot be indexed", id
->ident
);
3004 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
3005 astnode_finalize(n
);
3008 // TODO: bounds check
3009 astnode
*reduced
= reduce_index(n
);
3016 err(n
->loc
, "unknown symbol `%s'", id
->ident
);
3017 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
3018 astnode_finalize(n
);
3025 * Checks that A::B is valid.
3026 * If it's not valid it is replaced by integer 0.
3027 * @param n Node of type SCOPE_NODE
3029 static int validate_scoperef(astnode
*n
, void *arg
, astnode
**next
)
3032 astnode
*namespace = LHS(n
);
3033 symtab_entry
* e
= symtab_lookup(namespace->ident
);
3035 err(n
->loc
, "unknown namespace `%s'", namespace->ident
);
3036 /* Replace by integer 0 */
3037 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
3038 astnode_finalize(n
);
3041 /* Get symbol on right of :: operator */
3043 /* Namespace was found, check its type */
3049 /* OK, check the symbol */
3050 symtab_push(e
->symtab
);
3051 e
= symtab_lookup(symbol
->ident
);
3053 err(n
->loc
, "unknown symbol `%s' in namespace `%s'", symbol
->ident
, namespace->ident
);
3054 /* Replace by integer 0 */
3055 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
3056 astnode_finalize(n
);
3062 err(n
->loc
, "`%s' is not a namespace", namespace->ident
);
3063 /* Replace by integer 0 */
3064 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
3065 astnode_finalize(n
);
3073 * Validates right part of dotted reference recursively.
3074 * Assumes that left part's symbol table is on stack.
3075 * @param n Node of type DOT_NODE
3077 static void validate_dotref_recursive(astnode
*n
, astnode
*top
)
3082 symtab_entry
*field
;
3085 if (astnode_is_type(left
, INDEX_NODE
)) {
3086 left
= LHS(left
); /* Need identifier */
3089 if (astnode_is_type(right
, DOT_NODE
)) {
3090 right
= LHS(right
); /* Need identifier */
3092 if (astnode_is_type(right
, INDEX_NODE
)) {
3093 right
= LHS(right
); /* Need identifier */
3095 /* Lookup 'right' in 'left's symbol table */
3096 assert(astnode_get_type(right
) == IDENTIFIER_NODE
);
3097 field
= symtab_lookup(right
->ident
);
3098 if (field
== NULL
) {
3099 err(n
->loc
, "`%s' is not a member of `%s'", right
->ident
, left
->ident
);
3100 /* Replace by integer 0 */
3101 astnode_replace(top
, astnode_create_integer(0, top
->loc
) );
3102 astnode_finalize(top
);
3104 /* See if more subfields to process */
3106 if (astnode_is_type(n
, DOT_NODE
)) {
3107 /* Verify the variable's type -- should be user-defined */
3108 type
= LHS(field
->def
);
3109 if ((type
== NULL
) || (type
->datatype
!= USER_DATATYPE
)) {
3110 err(n
->loc
, "member `%s' of `%s' is not a structure", right
->ident
, left
->ident
);
3111 /* Replace by integer 0 */
3112 astnode_replace(top
, astnode_create_integer(0, top
->loc
) );
3113 astnode_finalize(top
);
3115 /* Look up variable's type definition and verify it's a structure */
3116 def
= symtab_global_lookup(LHS(type
)->ident
);
3118 err(n
->loc
, "member '%s' of '%s' is of unknown type (`%s')", right
->ident
, left
->ident
, LHS(type
)->ident
);
3119 /* Replace by integer 0 */
3120 astnode_replace(top
, astnode_create_integer(0, top
->loc
) );
3121 astnode_finalize(top
);
3122 } else if ( !((def
->type
== STRUC_SYMBOL
) || (def
->type
== UNION_SYMBOL
)) ) {
3123 err(n
->loc
, "member `%s' of `%s' is not a structure", right
->ident
, left
->ident
);
3124 /* Replace by integer 0 */
3125 astnode_replace(top
, astnode_create_integer(0, top
->loc
) );
3126 astnode_finalize(top
);
3129 symtab_push(def
->symtab
);
3130 validate_dotref_recursive(n
, top
);
3139 * Validates A.B.C.D. . ...
3140 * Replaces the whole thing with integer 0 if not.
3141 * @param n Node of type DOT_NODE
3143 static int validate_dotref(astnode
*n
, void *arg
, astnode
**next
)
3145 symtab_entry
*father
;
3149 if (astnode_has_ancestor_of_type(n
, DOT_NODE
)) {
3150 return 1; /* Already validated, since this function is recursive */
3152 /* Look up parent in global symbol table */
3153 left
= LHS(n
); /* n := left . right */
3154 if (astnode_is_type(left
, INDEX_NODE
)) {
3155 left
= LHS(left
); /* Need identifier */
3157 father
= symtab_lookup(left
->ident
);
3158 if (father
== NULL
) {
3159 err(n
->loc
, "unknown symbol `%s'", left
->ident
);
3160 /* Replace by integer 0 */
3161 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
3162 astnode_finalize(n
);
3165 father
->ref_count
++;
3166 /* Verify the variable's type -- should be user-defined */
3167 type
= LHS(father
->def
);
3168 if ((type
== NULL
) || (type
->datatype
!= USER_DATATYPE
)) {
3169 err(n
->loc
, "`%s' is not a structure", left
->ident
);
3170 /* Replace by integer 0 */
3171 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
3172 astnode_finalize(n
);
3175 def
= symtab_lookup(LHS(type
)->ident
);
3177 err(n
->loc
, "'%s' is of unknown type (`%s')", left
->ident
, LHS(type
)->ident
);
3178 /* Replace by integer 0 */
3179 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
3180 astnode_finalize(n
);
3182 } else if ( !((def
->type
== STRUC_SYMBOL
) || (def
->type
== UNION_SYMBOL
)) ) {
3183 err(n
->loc
, "`%s' is not a structure", left
->ident
);
3184 /* Replace by integer 0 */
3185 astnode_replace(n
, astnode_create_integer(0, n
->loc
) );
3186 astnode_finalize(n
);
3189 /* Verify fields recursively */
3190 symtab_push(def
->symtab
);
3191 validate_dotref_recursive(n
, n
);
3199 /*---------------------------------------------------------------------------*/
3202 * Evaluates expressions involved in conditional assembly, and removes the
3203 * appropriate branches from the AST.
3204 * Does some other stuff too, such as substitute equates and fold constants.
3206 void astproc_first_pass(astnode
*root
)
3208 /* Table of callback functions for our purpose. */
3209 static astnodeprocmap map
[] = {
3210 { LABEL_NODE
, enter_label
},
3211 { VAR_DECL_NODE
, enter_var
},
3212 { PROC_NODE
, enter_proc
},
3213 { STRUC_DECL_NODE
, enter_struc
},
3214 { UNION_DECL_NODE
, enter_union
},
3215 { ENUM_DECL_NODE
, enter_enum
},
3216 { RECORD_DECL_NODE
, enter_record
},
3217 { LOCAL_LABEL_NODE
, globalize_local
},
3218 { LOCAL_ID_NODE
, globalize_local
},
3219 { MACRO_DECL_NODE
, enter_macro
},
3220 { MACRO_NODE
, expand_macro
},
3221 { REPT_NODE
, process_rept
},
3222 { WHILE_NODE
, process_while
},
3223 { DATASEG_NODE
, process_dataseg
},
3224 { CODESEG_NODE
, process_codeseg
},
3225 { ORG_NODE
, process_org
},
3226 { CHARMAP_NODE
, load_charmap
},
3227 { INSTRUCTION_NODE
, process_instruction
},
3228 { DATA_NODE
, process_data
},
3229 { STORAGE_NODE
, process_storage
},
3230 { EQU_NODE
, process_equ
},
3231 { ASSIGN_NODE
, process_assign
},
3232 { IFDEF_NODE
, process_ifdef
},
3233 { IFNDEF_NODE
, process_ifndef
},
3234 { IF_NODE
, process_if
},
3235 { EXTRN_NODE
, tag_extrn_symbols
},
3236 { MESSAGE_NODE
, process_message
},
3237 { WARNING_NODE
, process_warning
},
3238 { ERROR_NODE
, process_error
},
3239 { FORWARD_BRANCH_DECL_NODE
, process_forward_branch_decl
},
3240 { BACKWARD_BRANCH_DECL_NODE
, process_backward_branch_decl
},
3241 { FORWARD_BRANCH_NODE
, process_forward_branch
},
3242 { BACKWARD_BRANCH_NODE
, process_backward_branch
},
3247 in_dataseg
= 0; /* codeseg is default */
3249 astproc_walk(root
, NULL
, map
);
3250 /* Remove all the volatile constants from the symbol table */
3251 /* These are the ones defined with the '=' operator, whose identifiers should
3252 all have been replaced by their value in the syntax tree now. Since
3253 they're not referenced anywhere we can safely dispose of them.
3254 The EQUates on the other hand should be kept, since they will
3255 possibly be exported. */
3256 #ifdef ENABLE_BUGGY_THING // ### FIXME
3259 symbol_ident_list list
;
3261 symtab_list_type(CONSTANT_SYMBOL
, &list
);
3262 for (i
= 0; i
< list
.size
; ++i
) {
3263 e
= symtab_lookup(list
.idents
[i
]);
3264 if (e
->flags
& VOLATILE_FLAG
) {
3265 symtab_remove(list
.idents
[i
]);
3268 symtab_list_finalize(&list
);
3273 /*---------------------------------------------------------------------------*/
3276 * Tags labels as public.
3277 * @param public A node of type PUBLIC_NODE
3279 static int tag_public_symbols(astnode
*public, void *arg
, astnode
**next
)
3283 /* Go through the list of identifiers */
3284 for (id
=astnode_get_first_child(public); id
!= NULL
; id
= astnode_get_next_sibling(id
) ) {
3285 e
= symtab_lookup(id
->ident
);
3287 if (e
->flags
& EXTRN_FLAG
) {
3288 err(public->loc
, "`%s' already declared extrn", id
->ident
);
3292 case CONSTANT_SYMBOL
:
3296 e
->flags
|= PUBLIC_FLAG
;
3300 err(public->loc
, "`%s' is of non-exportable type", id
->ident
);
3305 warn(public->loc
, "`%s' declared as public but is not defined", id
->ident
);
3308 astnode_remove(public);
3309 astnode_finalize(public);
3314 * Sets alignment for a set of (data) labels.
3315 * @param align A node of type ALIGN_NODE
3317 static int tag_align_symbols(astnode
*align
, void *arg
, astnode
**next
)
3324 /* Go through the list of identifiers */
3325 idents
= LHS(align
);
3326 for (id
=astnode_get_first_child(idents
); id
!= NULL
; id
= astnode_get_next_sibling(id
) ) {
3327 e
= symtab_lookup(id
->ident
);
3329 if (!(e
->flags
& DATA_FLAG
)) {
3330 err(align
->loc
, "cannot align a code symbol (`%s')", id
->ident
);
3335 expr
= reduce_expression(RHS(align
));
3336 if (!astnode_is_type(expr
, INTEGER_NODE
)) {
3337 err(align
->loc
, "alignment expression must be an integer literal");
3338 } else if ((expr
->integer
< 0) || (expr
->integer
>= 0x10000)) {
3339 err(align
->loc
, "alignment expression out of range");
3340 } else if (expr
->integer
> 1) {
3342 switch (expr
->integer
) {
3359 e
->flags
|= ALIGN_FLAG
;
3364 err(align
->loc
, "alignment expression must be a power of 2");
3371 err(align
->loc
, "`%s' cannot be aligned", id
->ident
);
3377 warn(align
->loc
, "alignment ignored for undefined symbol `%s'", id
->ident
);
3380 astnode_remove(align
);
3381 astnode_finalize(align
);
3385 /*---------------------------------------------------------------------------*/
3388 * Removes unused labels from a syntax tree (and symbol table).
3389 * Unused labels are labels that are defined but not referenced anywhere.
3390 * This function assumes that the reference counts have already been calculated.
3392 void remove_unused_labels()
3397 symbol_ident_list list
;
3398 symtab_list_type(LABEL_SYMBOL
, &list
);
3399 for (i
=0; i
<list
.size
; i
++) {
3400 id
= list
.idents
[i
];
3401 symtab_entry
* e
= symtab_lookup(id
);
3402 if ((e
->ref_count
== 0) && ((e
->flags
& (PUBLIC_FLAG
| EXTRN_FLAG
)) == 0)) {
3404 strtok(n
->label
, "#"); /* Remove globalize junk */
3405 warn(n
->loc
, "`%s' defined but not used", n
->label
);
3407 astnode_finalize(n
);
3408 //symtab_remove(n->label); ### FIXME leads to crash sometimes...
3411 symtab_list_finalize(&list
);
3415 * If the storage is of user-defined type, replaces it with
3416 * .DSB sizeof(type) * count
3418 static int reduce_user_storage(astnode
*n
, void *arg
, astnode
**next
)
3422 astnode
*byte_storage
;
3425 if (type
->datatype
== USER_DATATYPE
) {
3426 e
= symtab_lookup(LHS(type
)->ident
);
3428 /* Replace by DSB */
3430 byte_storage
= astnode_create_storage(
3431 astnode_create_datatype(BYTE_DATATYPE
, NULL
, type
->loc
),
3432 astnode_create_arithmetic(
3434 astnode_create_sizeof(
3435 astnode_create_identifier(LHS(type
)->ident
, n
->loc
),
3438 astnode_clone(count
, n
->loc
),
3443 astnode_replace(n
, byte_storage
);
3444 astnode_finalize(n
);
3445 *next
= byte_storage
;
3448 err(n
->loc
, "unknown symbol `%s'", LHS(type
)->ident
);
3450 astnode_finalize(n
);
3458 * Second major pass over AST.
3460 void astproc_second_pass(astnode
*root
)
3462 /* Table of callback functions for our purpose. */
3463 static astnodeprocmap map
[] = {
3464 { IDENTIFIER_NODE
, validate_ref
},
3465 { SCOPE_NODE
, validate_scoperef
},
3466 { DOT_NODE
, validate_dotref
},
3467 { INDEX_NODE
, validate_index
},
3468 { PUBLIC_NODE
, tag_public_symbols
},
3469 { STORAGE_NODE
, reduce_user_storage
},
3470 { ALIGN_NODE
, tag_align_symbols
},
3471 { STRUC_DECL_NODE
, noop
},
3472 { UNION_DECL_NODE
, noop
},
3473 { ENUM_DECL_NODE
, noop
},
3474 { RECORD_DECL_NODE
, noop
},
3477 in_dataseg
= 0; /* codeseg is default */
3479 astproc_walk(root
, NULL
, map
);
3481 remove_unused_labels();
3484 /*---------------------------------------------------------------------------*/
3487 * Translates a single instruction.
3488 * @param instr A node of type INSTRUCTION_NODE
3490 static int translate_instruction(astnode
*instr
, void *arg
, astnode
**next
)
3493 /* Put the operand in final form */
3494 astnode
*o
= reduce_expression_complete( LHS(instr
) );
3495 assert(o
== LHS(instr
));
3496 /* Convert (mnemonic, addressing mode) pair to opcode */
3497 instr
->instr
.opcode
= opcode_get(instr
->instr
.mnemonic
, instr
->instr
.mode
);
3498 if (instr
->instr
.opcode
== 0xFF) {
3499 /* Check for the special cases */
3500 if ((instr
->instr
.mnemonic
== STX_MNEMONIC
) && (instr
->instr
.mode
== ABSOLUTE_Y_MODE
)) {
3501 /* Doesn't have absolute version, "scale down" to zeropage */
3502 instr
->instr
.mode
= ZEROPAGE_Y_MODE
;
3503 instr
->instr
.opcode
= opcode_get(instr
->instr
.mnemonic
, instr
->instr
.mode
);
3504 } else if ((instr
->instr
.mnemonic
== STY_MNEMONIC
) && (instr
->instr
.mode
== ABSOLUTE_X_MODE
)) {
3505 /* Doesn't have absolute version, "scale down" to zeropage */
3506 instr
->instr
.mode
= ZEROPAGE_X_MODE
;
3507 instr
->instr
.opcode
= opcode_get(instr
->instr
.mnemonic
, instr
->instr
.mode
);
3508 } else if (instr
->instr
.mode
== ABSOLUTE_MODE
) {
3509 /* Check for relative addressing (these are parsed as absolute mode) */
3510 switch (instr
->instr
.mnemonic
) {
3519 /* Fix addressing mode and opcode */
3520 instr
->instr
.mode
= RELATIVE_MODE
;
3521 instr
->instr
.opcode
= opcode_get(instr
->instr
.mnemonic
, instr
->instr
.mode
);
3526 if (instr
->instr
.opcode
!= 0xFF) {
3527 /* If the operand is a constant, see if we can "reduce" from
3528 absolute mode to zeropage mode */
3529 if ((astnode_is_type(o
, INTEGER_NODE
)) &&
3530 ((unsigned long)o
->integer
< 256) &&
3531 ((c
= opcode_zp_equiv(instr
->instr
.opcode
)) != 0xFF)) {
3532 /* Switch to the zeromode version */
3533 instr
->instr
.opcode
= c
;
3534 switch (instr
->instr
.mode
) {
3535 case ABSOLUTE_MODE
: instr
->instr
.mode
= ZEROPAGE_MODE
; break;
3536 case ABSOLUTE_X_MODE
: instr
->instr
.mode
= ZEROPAGE_X_MODE
; break;
3537 case ABSOLUTE_Y_MODE
: instr
->instr
.mode
= ZEROPAGE_Y_MODE
; break;
3538 default: /* Impossible to get here, right? */ break;
3541 /* If the operand is a constant, make sure it fits */
3542 if (astnode_is_type(o
, INTEGER_NODE
)) {
3543 switch (instr
->instr
.mode
) {
3544 case IMMEDIATE_MODE
:
3546 case ZEROPAGE_X_MODE
:
3547 case ZEROPAGE_Y_MODE
:
3548 case PREINDEXED_INDIRECT_MODE
:
3549 case POSTINDEXED_INDIRECT_MODE
:
3550 /* Operand must fit in 8 bits */
3551 if (!IS_BYTE_VALUE(o
->integer
)) {
3552 warn(o
->loc
, "operand out of range; truncated");
3558 case ABSOLUTE_X_MODE
:
3559 case ABSOLUTE_Y_MODE
:
3561 /* Operand must fit in 16 bits */
3562 if ((unsigned long)o
->integer
>= 0x10000) {
3563 warn(o
->loc
, "operand out of range; truncated");
3564 o
->integer
&= 0xFFFF;
3569 /* Constant isn't allowed here is it? */
3576 else if (astnode_is_type(o
, STRING_NODE
)) {
3577 /* String operand doesn't make sense here */
3578 err(instr
->loc
, "invalid operand");
3581 err(instr
->loc
, "invalid addressing mode");
3587 * ### Is this really such a good idea?
3589 static int maybe_merge_data(astnode
*n
, void *arg
, astnode
**next
)
3594 /* Only merge if no debugging, otherwise line information is lost. */
3595 if (!xasm_args
.debug
&& astnode_is_type(*next
, DATA_NODE
)
3596 && astnode_equal(type
, LHS(*next
)) ) {
3599 astnode_finalize( astnode_remove_child_at(temp
, 0) ); /* Remove datatype node */
3600 astnode_add_child(n
, astnode_remove_children(temp
) );
3601 astnode_finalize(temp
);
3604 /* Reduce expressions to final form */
3605 for (n
= n
->first_child
; n
!= NULL
; n
= temp
->next_sibling
) {
3606 temp
= reduce_expression_complete(n
);
3607 if (astnode_is_type(temp
, INTEGER_NODE
)) {
3608 /* Check that value fits according to datatype */
3609 switch (type
->datatype
) {
3611 if (!IS_BYTE_VALUE(temp
->integer
)) {
3612 warn(temp
->loc
, "operand out of range; truncated");
3613 temp
->integer
&= 0xFF;
3618 if (!IS_WORD_VALUE(temp
->integer
)) {
3619 warn(temp
->loc
, "operand out of range; truncated");
3620 temp
->integer
&= 0xFFFF;
3624 case DWORD_DATATYPE
:
3639 static int maybe_merge_storage(astnode
*storage
, void *arg
, astnode
**next
)
3644 if (astnode_is_type(*next
, STORAGE_NODE
)
3645 && astnode_equal(LHS(storage
), LHS(*next
)) ) {
3648 astnode_finalize( astnode_remove_child_at(temp
, 0) ); /* Remove datatype node */
3649 old_count
= RHS(storage
);
3650 /* Calculate new count */
3651 new_count
= astnode_create_arithmetic(
3653 astnode_remove_child_at(temp
, 0),
3654 astnode_clone(old_count
, storage
->loc
),
3657 new_count
= reduce_expression_complete(new_count
);
3658 astnode_replace(old_count
, new_count
);
3659 astnode_finalize(old_count
);
3660 astnode_finalize(temp
);
3663 reduce_expression_complete(RHS(storage
));
3669 * Replaces .proc by its label followed by statements.
3671 static int flatten_proc(astnode
*proc
, void *arg
, astnode
**next
)
3673 astnode
*id
= LHS(proc
);
3674 astnode
*list
= RHS(proc
);
3676 id
->type
= LABEL_NODE
;
3677 astnode_insert_child(list
, id
, 0);
3678 astnode
*stmts
= astnode_remove_children(list
);
3679 astnode_replace(proc
, stmts
);
3680 astnode_finalize(proc
);
3688 static int flatten_var_decl(astnode
*var
, void *arg
, astnode
**next
)
3690 astnode
*stmts
= LHS(var
);
3691 astnode_remove_children(var
);
3692 stmts
->type
= LABEL_NODE
;
3693 astnode_replace(var
, stmts
);
3694 astnode_finalize(var
);
3700 * Third and final pass (if the output isn't pure 6502).
3701 * Translates instructions, merges data and storage nodes,
3702 * and reduces their operands to final form on the way.
3704 void astproc_third_pass(astnode
*root
)
3706 /* Table of callback functions for our purpose. */
3707 static astnodeprocmap map
[] = {
3708 { INSTRUCTION_NODE
, translate_instruction
},
3709 { DATA_NODE
, maybe_merge_data
},
3710 { STORAGE_NODE
, maybe_merge_storage
},
3711 { VAR_DECL_NODE
, flatten_var_decl
},
3712 { PROC_NODE
, flatten_proc
},
3713 { STRUC_DECL_NODE
, noop
},
3714 { UNION_DECL_NODE
, noop
},
3715 { ENUM_DECL_NODE
, noop
},
3716 { RECORD_DECL_NODE
, noop
},
3719 in_dataseg
= 0; /* codeseg is default */
3721 astproc_walk(root
, NULL
, map
);
3724 /*---------------------------------------------------------------------------*/
3727 * Evaluates the given expression, _without_ replacing it in the AST
3728 * (unlike astproc_reduce_expression() and friends).
3730 static astnode
*eval_expression(astnode
*expr
)
3732 switch (astnode_get_type(expr
)) {
3734 case ARITHMETIC_NODE
: {
3735 astnode
*lhs
= eval_expression(LHS(expr
));
3736 astnode
*rhs
= eval_expression(RHS(expr
));
3737 switch (expr
->oper
) {
3740 case MINUS_OPERATOR
:
3755 if (astnode_is_type(lhs
, INTEGER_NODE
)
3756 && astnode_is_type(rhs
, INTEGER_NODE
)) {
3757 /* Both sides are integer literals. */
3758 switch (expr
->oper
) {
3759 case PLUS_OPERATOR
: return astnode_create_integer(lhs
->integer
+ rhs
->integer
, expr
->loc
);
3760 case MINUS_OPERATOR
: return astnode_create_integer(lhs
->integer
- rhs
->integer
, expr
->loc
);
3761 case MUL_OPERATOR
: return astnode_create_integer(lhs
->integer
* rhs
->integer
, expr
->loc
);
3762 case DIV_OPERATOR
: return astnode_create_integer(lhs
->integer
/ rhs
->integer
, expr
->loc
);
3763 case MOD_OPERATOR
: return astnode_create_integer(lhs
->integer
% rhs
->integer
, expr
->loc
);
3764 case AND_OPERATOR
: return astnode_create_integer(lhs
->integer
& rhs
->integer
, expr
->loc
);
3765 case OR_OPERATOR
: return astnode_create_integer(lhs
->integer
| rhs
->integer
, expr
->loc
);
3766 case XOR_OPERATOR
: return astnode_create_integer(lhs
->integer
^ rhs
->integer
, expr
->loc
);
3767 case SHL_OPERATOR
: return astnode_create_integer(lhs
->integer
<< rhs
->integer
, expr
->loc
);
3768 case SHR_OPERATOR
: return astnode_create_integer(lhs
->integer
>> rhs
->integer
, expr
->loc
);
3769 case LT_OPERATOR
: return astnode_create_integer(lhs
->integer
< rhs
->integer
, expr
->loc
);
3770 case GT_OPERATOR
: return astnode_create_integer(lhs
->integer
> rhs
->integer
, expr
->loc
);
3771 case EQ_OPERATOR
: return astnode_create_integer(lhs
->integer
== rhs
->integer
, expr
->loc
);
3772 case NE_OPERATOR
: return astnode_create_integer(lhs
->integer
!= rhs
->integer
, expr
->loc
);
3773 case LE_OPERATOR
: return astnode_create_integer(lhs
->integer
<= rhs
->integer
, expr
->loc
);
3774 case GE_OPERATOR
: return astnode_create_integer(lhs
->integer
>= rhs
->integer
, expr
->loc
);
3776 default: /* ### Error, actually */
3780 /* Use some mathematical identities... */
3781 else if ((astnode_is_type(lhs
, INTEGER_NODE
) && (lhs
->integer
== 0))
3782 && (expr
->oper
== PLUS_OPERATOR
)) {
3783 /* 0+expr == expr */
3784 return astnode_clone(rhs
, rhs
->loc
);
3785 } else if ((astnode_is_type(rhs
, INTEGER_NODE
) && (rhs
->integer
== 0))
3786 && (expr
->oper
== PLUS_OPERATOR
)) {
3787 /* expr+0 == expr */
3788 return astnode_clone(lhs
, lhs
->loc
);
3789 } else if ((astnode_is_type(lhs
, INTEGER_NODE
) && (lhs
->integer
== 1))
3790 && (expr
->oper
== MUL_OPERATOR
)) {
3791 /* 1*expr == expr */
3792 return astnode_clone(rhs
, rhs
->loc
);
3793 } else if ((astnode_is_type(rhs
, INTEGER_NODE
) && (rhs
->integer
== 1))
3794 && ((expr
->oper
== MUL_OPERATOR
) || (expr
->oper
== DIV_OPERATOR
)) ) {
3795 /* expr*1 == expr */
3796 /* expr/1 == expr */
3797 return astnode_clone(lhs
, lhs
->loc
);
3806 case UMINUS_OPERATOR
:
3808 if (astnode_is_type(lhs
, INTEGER_NODE
)) {
3809 switch (expr
->oper
) {
3810 case NEG_OPERATOR
: return astnode_create_integer(~lhs
->integer
, expr
->loc
);
3811 case NOT_OPERATOR
: return astnode_create_integer(!lhs
->integer
, expr
->loc
);
3812 case LO_OPERATOR
: return astnode_create_integer(lhs
->integer
& 0xFF, expr
->loc
);
3813 case HI_OPERATOR
: return astnode_create_integer((lhs
->integer
>> 8) & 0xFF, expr
->loc
);
3814 case UMINUS_OPERATOR
: return astnode_create_integer(-lhs
->integer
, expr
->loc
);
3823 return astnode_clone(expr
, expr
->loc
);
3825 case IDENTIFIER_NODE
: {
3826 symtab_entry
*e
= symtab_lookup(expr
->ident
);
3827 // ### assert(e->type == LABEL_SYMBOL);
3828 if (e
->flags
& ADDR_FLAG
)
3829 return astnode_create_integer(e
->address
, expr
->loc
);
3832 case CURRENT_PC_NODE
:
3833 return astnode_create_integer(in_dataseg
? dataseg_pc
: codeseg_pc
, expr
->loc
);
3842 * Sets the address of the label to be the currently calculated PC.
3844 static int set_label_address(astnode
*label
, void *arg
, astnode
**next
)
3846 symtab_entry
*e
= symtab_lookup(label
->ident
);
3847 // ### assert(e && (e->type == LABEL_SYMBOL));
3848 e
->address
= in_dataseg
? dataseg_pc
: codeseg_pc
;
3849 e
->flags
|= ADDR_FLAG
;
3854 * Sets the current PC to the address specified by the ORG node.
3856 static int set_pc_from_org(astnode
*org
, void *arg
, astnode
**next
)
3858 astnode
*addr
= LHS(org
);
3859 assert(astnode_is_type(addr
, INTEGER_NODE
));
3861 dataseg_pc
= addr
->integer
;
3863 codeseg_pc
= addr
->integer
;
3868 * Ensures that the given symbol is defined.
3870 static int ensure_symbol_is_defined(astnode
*id
, void *arg
, astnode
**next
)
3872 symtab_entry
*e
= symtab_lookup(id
->ident
);
3874 if ((e
->flags
& EXTRN_FLAG
) && !(e
->flags
& ERROR_UNDEFINED_FLAG
)) {
3875 err(id
->loc
, "cannot generate pure binary because `%s' is not defined", id
->ident
);
3876 e
->flags
|= ERROR_UNDEFINED_FLAG
;
3882 * Increments PC according to the size of the instruction.
3884 static int inc_pc_by_instruction(astnode
*instr
, void *arg
, astnode
**next
)
3886 assert(!in_dataseg
);
3889 unsigned char zp_op
= opcode_zp_equiv(instr
->instr
.opcode
);
3890 if (zp_op
!= 0xFF) {
3891 /* See if we can optimize this to a ZP-instruction */
3892 astnode
*operand
= eval_expression(LHS(instr
));
3893 if (operand
&& astnode_is_type(operand
, INTEGER_NODE
)) {
3894 if ((operand
->integer
>= 0) && (operand
->integer
< 256)) {
3895 instr
->instr
.opcode
= zp_op
;
3897 astnode_finalize(operand
);
3901 codeseg_pc
+= opcode_length(instr
->instr
.opcode
);
3906 * Increments PC according to the size of the defined data.
3908 static int inc_pc_by_data(astnode
*data
, void *arg
, astnode
**next
)
3910 astnode
*type
= LHS(data
);
3911 int count
= astnode_get_child_count(data
) - 1;
3913 assert(!in_dataseg
);
3914 switch (type
->datatype
) {
3915 case BYTE_DATATYPE
: nbytes
= count
; break;
3916 case WORD_DATATYPE
: nbytes
= count
* 2; break;
3917 case DWORD_DATATYPE
: nbytes
= count
* 4; break;
3922 codeseg_pc
+= nbytes
;
3927 * Increments PC according to the size of the included binary.
3929 static int inc_pc_by_binary(astnode
*node
, void *arg
, astnode
**next
)
3931 assert(!in_dataseg
);
3932 codeseg_pc
+= node
->binary
.size
;
3937 * Increments PC according to the size of the storage.
3939 static int inc_pc_by_storage(astnode
*storage
, void *arg
, astnode
**next
)
3941 astnode
*type
= LHS(storage
);
3942 assert(type
->datatype
== BYTE_DATATYPE
);
3943 astnode
*count
= eval_expression(RHS(storage
));
3945 if (astnode_get_type(count
) == INTEGER_NODE
) {
3947 dataseg_pc
+= count
->integer
;
3949 codeseg_pc
+= count
->integer
;
3951 astnode_finalize(count
);
3957 * This pass is only performed if the output format is pure 6502.
3958 * It ensures that it is actually possible to generate pure 6502
3959 * for this syntax tree (i.e. no external symbols).
3960 * Furthermore, it calculates the address of all labels, so that
3961 * everything is ready for the final output phase.
3963 void astproc_fourth_pass(astnode
*root
)
3966 /* ### Should loop while there's a change in the address of
3967 one or more labels */
3968 for (x
= 0; x
< 2; ++x
) {
3969 in_dataseg
= 0; /* codeseg is default */
3972 /* Table of callback functions for our purpose. */
3973 static astnodeprocmap map
[] = {
3974 { DATASEG_NODE
, process_dataseg
},
3975 { CODESEG_NODE
, process_codeseg
},
3976 { ORG_NODE
, set_pc_from_org
},
3977 { LABEL_NODE
, set_label_address
},
3978 { IDENTIFIER_NODE
, ensure_symbol_is_defined
},
3979 { INSTRUCTION_NODE
, inc_pc_by_instruction
},
3980 { DATA_NODE
, inc_pc_by_data
},
3981 { STORAGE_NODE
, inc_pc_by_storage
},
3982 { BINARY_NODE
, inc_pc_by_binary
},
3983 { STRUC_DECL_NODE
, noop
},
3984 { UNION_DECL_NODE
, noop
},
3985 { ENUM_DECL_NODE
, noop
},
3986 { RECORD_DECL_NODE
, noop
},
3990 astproc_walk(root
, NULL
, map
);
3994 /*---------------------------------------------------------------------------*/
3997 * Writes an instruction.
3999 static int write_instruction(astnode
*instr
, void *arg
, astnode
**next
)
4001 FILE *fp
= (FILE *)arg
;
4002 unsigned char op
= instr
->instr
.opcode
;
4003 int len
= opcode_length(op
);
4007 astnode
*operand
= eval_expression(LHS(instr
));
4008 if(!astnode_is_type(operand
, INTEGER_NODE
)) {
4009 /* ### This is rather fatal, it should be a literal by this point */
4010 err(instr
->loc
, "operand does not evaluate to literal");
4012 int value
= operand
->integer
;
4014 /* Check if it's a relative jump */
4024 /* Calculate difference between target and address of next instruction */
4025 value
= value
- (codeseg_pc
+ 2);
4026 if (!IS_BYTE_VALUE(value
)) {
4027 err(operand
->loc
, "branch out of range");
4033 if (!IS_BYTE_VALUE(value
)) {
4034 warn(operand
->loc
, "operand out of range; truncated");
4039 fputc((unsigned char)value
, fp
);
4042 if (!IS_WORD_VALUE(value
)) {
4043 warn(operand
->loc
, "operand out of range; truncated");
4046 fputc((unsigned char)value
, fp
);
4047 fputc((unsigned char)(value
>> 8), fp
);
4050 astnode_finalize(operand
);
4052 codeseg_pc
+= opcode_length(instr
->instr
.opcode
);
4059 static int write_data(astnode
*data
, void *arg
, astnode
**next
)
4061 FILE *fp
= (FILE *)arg
;
4062 astnode
*type
= LHS(data
);
4064 assert(!in_dataseg
);
4065 for (expr
= RHS(data
); expr
!= NULL
; expr
= astnode_get_next_sibling(expr
) ) {
4067 astnode
*e
= eval_expression(expr
);
4068 assert(e
->type
== INTEGER_NODE
);
4070 switch (type
->datatype
) {
4072 if (!IS_BYTE_VALUE(value
)) {
4073 warn(expr
->loc
, "operand out of range; truncated");
4076 fputc((unsigned char)value
, fp
);
4081 if (!IS_WORD_VALUE(value
)) {
4082 warn(expr
->loc
, "operand out of range; truncated");
4085 fputc((unsigned char)value
, fp
);
4086 fputc((unsigned char)(value
>> 8), fp
);
4090 case DWORD_DATATYPE
:
4091 fputc((unsigned char)value
, fp
);
4092 fputc((unsigned char)(value
>> 8), fp
);
4093 fputc((unsigned char)(value
>> 16), fp
);
4094 fputc((unsigned char)(value
>> 24), fp
);
4102 astnode_finalize(e
);
4108 * Writes storage (padding).
4110 static int write_storage(astnode
*storage
, void *arg
, astnode
**next
)
4112 FILE *fp
= (FILE *)arg
;
4113 astnode
*type
= LHS(storage
);
4114 astnode
*count
= eval_expression(RHS(storage
));
4115 assert(type
->datatype
== BYTE_DATATYPE
);
4116 assert(!in_dataseg
);
4119 assert(astnode_get_type(count
) == INTEGER_NODE
);
4120 for (i
= 0; i
< count
->integer
; ++i
)
4122 codeseg_pc
+= count
->integer
;
4123 astnode_finalize(count
);
4131 static int write_binary(astnode
*node
, void *arg
, astnode
**next
)
4133 FILE *fp
= (FILE *)arg
;
4134 assert(!in_dataseg
);
4135 fwrite(node
->binary
.data
, 1, node
->binary
.size
, fp
);
4136 codeseg_pc
+= node
->binary
.size
;
4141 * This pass is only performed if the output format is pure 6502.
4142 * It writes the binary code.
4144 void astproc_fifth_pass(astnode
*root
, FILE *fp
)
4146 /* Table of callback functions for our purpose. */
4147 static astnodeprocmap map
[] = {
4148 { DATASEG_NODE
, process_dataseg
},
4149 { CODESEG_NODE
, process_codeseg
},
4150 { ORG_NODE
, set_pc_from_org
},
4151 { INSTRUCTION_NODE
, write_instruction
},
4152 { DATA_NODE
, write_data
},
4153 { STORAGE_NODE
, write_storage
},
4154 { BINARY_NODE
, write_binary
},
4155 { STRUC_DECL_NODE
, noop
},
4156 { UNION_DECL_NODE
, noop
},
4157 { ENUM_DECL_NODE
, noop
},
4158 { RECORD_DECL_NODE
, noop
},
4161 in_dataseg
= 0; /* codeseg is default */
4165 astproc_walk(root
, fp
, map
);