fix dangling pointer issue. If the node being processed is replaced,
[xorcyst.git] / RCS / codegen.c,v
blobcfeee12cac392d6853a6ba625a3a9e616a8a98ad
1 head    1.10;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
8 1.10
9 date    2007.08.12.18.58.12;    author khansen; state Exp;
10 branches;
11 next    1.9;
13 1.9
14 date    2007.08.09.20.33.48;    author khansen; state Exp;
15 branches;
16 next    1.8;
18 1.8
19 date    2007.08.07.22.42.17;    author khansen; state Exp;
20 branches;
21 next    1.7;
23 1.7
24 date    2007.08.07.21.23.24;    author khansen; state Exp;
25 branches;
26 next    1.6;
28 1.6
29 date    2007.07.22.13.33.26;    author khansen; state Exp;
30 branches;
31 next    1.5;
33 1.5
34 date    2004.12.19.19.58.37;    author kenth;   state Exp;
35 branches;
36 next    1.4;
38 1.4
39 date    2004.12.18.16.58.52;    author kenth;   state Exp;
40 branches;
41 next    1.3;
43 1.3
44 date    2004.12.14.01.49.14;    author kenth;   state Exp;
45 branches;
46 next    1.2;
48 1.2
49 date    2004.12.06.04.52.36;    author kenth;   state Exp;
50 branches;
51 next    1.1;
53 1.1
54 date    2004.06.30.07.55.38;    author kenth;   state Exp;
55 branches;
56 next    ;
59 desc
63 1.10
64 log
65 @ability to generate pure 6502 binary (--pure-binary switch)
67 text
68 @/*
69  * $Id: codegen.c,v 1.9 2007/08/09 20:33:48 khansen Exp khansen $
70  * $Log: codegen.c,v $
71  * Revision 1.9  2007/08/09 20:33:48  khansen
72  * progress
73  *
74  * Revision 1.8  2007/08/07 22:42:17  khansen
75  * make sure a CMD_FILE command is output at the start of each segment
76  *
77  * Revision 1.7  2007/08/07 21:23:24  khansen
78  * const
79  *
80  * Revision 1.6  2007/07/22 13:33:26  khansen
81  * convert tabs to whitespaces
82  *
83  * Revision 1.5  2004/12/19 19:58:37  kenth
84  * xorcyst 1.4.0
85  *
86  * Revision 1.4  2004/12/18 16:58:52  kenth
87  * outputs file and line info if --debug
88  * CMD_DSW, CMD_DSD gone
89  *
90  * Revision 1.3  2004/12/14 01:49:14  kenth
91  * xorcyst 1.3.0
92  *
93  * Revision 1.2  2004/12/06 04:52:36  kenth
94  * xorcyst 1.1.0
95  *
96  * Revision 1.1  2004/06/30 07:55:38  kenth
97  * Initial revision
98  *
99  */
102  *    (C) 2004 Kent Hansen
104  *    The XORcyst is free software; you can redistribute it and/or modify
105  *    it under the terms of the GNU General Public License as published by
106  *    the Free Software Foundation; either version 2 of the License, or
107  *    (at your option) any later version.
109  *    The XORcyst is distributed in the hope that it will be useful,
110  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
111  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
112  *    GNU General Public License for more details.
114  *    You should have received a copy of the GNU General Public License
115  *    along with The XORcyst; if not, write to the Free Software
116  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
117  */
120  * This file contains functions for generating object code from an abstract
121  * syntax tree (AST).
122  * The output of the assembler is not pure 6502 binary code. It is a file in
123  * a custom object format meant to be fed to the XORcyst linker. The object
124  * file contains information about the symbols it exports (that others may
125  * access), the symbols it imports (the linker will look for these in other
126  * units and resolve their values), and of course the 6502 instructions.
127  * Labels, data and instructions are encoded in a special bytecode language.
128  * All operands to instructions and directives which aren't constants are
129  * stored as expressions. (It is the linker's job to parse the expressions,
130  * compute their values and produce the actual 6502 binary.)
132  * The format of resulting file is:
133  * 1 word: magic number
134  * 1 byte: version
135  * 1 word: number of exported constants
136  * ? bytes: exported constants descriptors
137  * 1 byte: number of units explicitly imported from
138  * ? bytes: names of units explicitly imported from
139  * 1 word: number of imported symbols (externals)
140  * ? bytes: imported symbols descriptors
141  * 24-bit word: size of data segment
142  * ? bytes: data segment bytecodes
143  * 24-bit word: size of code segment
144  * ? bytes: code segment bytecodes
145  * 1 word: number of expressions
146  * ? bytes: expression descriptors
147  */
149 #include <stdio.h>
150 #include <stdlib.h>
151 #include <string.h>
152 #include "codegen.h"
153 #include "symtab.h"
154 #include "objdef.h"
155 #include "opcode.h"
156 #include "xasm.h"
157 #include "assert.h"
159 /*---------------------------------------------------------------------------*/
161 /* Convenient macros to write integers in big-endian form. */
162 #define put_1(f, b) { fputc((unsigned char)(b), f); }
163 #define put_2(f, w) { put_1(f, (w) >> 8); put_1(f, w); }
164 #define put_3(f, t) { put_2(f, (t) >> 8); put_1(f, t); }
165 #define put_4(f, q) { put_2(f, (q) >> 16); put_2(f, q); }
167 /* Convenient macros to write length-prepended strings. */
168 #define put_str_8(f, s) { put_1(f, strlen(s)-1); fprintf(f, "%s", s); }
169 #define put_str_16(f, s) { put_2(f, strlen(s)-1); fprintf(f, "%s", s); }
170 #define put_str(f, s) { if (strlen(s) <= 0x100) { put_str_8(f, s); } else { put_str_16(f, s); } }
173  * Writes a sequence of bytes to file.
174  * @@param f File handle
175  * @@param bytes Array of bytes
176  * @@param count Number of bytes
177  */
178 static void put_bytes(FILE *f, const unsigned char *bytes, int count)
180     int i;
181     /* Write the bytes */
182     for (i=0; i<count; i++) {
183         put_1(f, bytes[i]);
184     }
187 /*---------------------------------------------------------------------------*/
189 #define BUF_MAX_SIZE 0x10000
190 /** Buffer used to collect binary data generated from processing consecutive code statements. */
191 static unsigned char buf[BUF_MAX_SIZE];
192 /** Current position in buffer */
193 static int buf_pos = 0;
194 /** Buffer file */
195 static FILE *buf_file = NULL;
197 #define buf_reset() { buf_pos = 0; }
200  * Flushes contents of <code>buf</code> to file.
201  * @@param f File handle
202  */
203 static void buf_flush(FILE *f)
205     if (buf_pos > 0) {
206         if (buf_pos <= 0x100) {
207             /* Use 8-bit form. */
208             put_1(f, CMD_BIN8);
209             put_1(f, buf_pos - 1);
210             put_bytes(f, buf, buf_pos);
211         }
212         else if (buf_pos <= 0x10000) {
213             /* Use 16-bit form. */
214             put_1(f, CMD_BIN16);
215             put_2(f, buf_pos - 1);
216             put_bytes(f, buf, buf_pos);
217         }
218         else {
219             /* Error, buffer overflow. */
220             fprintf(stderr, "buf_flush: buffer overflow\n");
221         }
222         buf_reset();
223     }
226 /** Appends single byte to buffer. */
227 #define buf_append(b) { if (buf_pos >= BUF_MAX_SIZE) buf_flush(buf_file); buf[buf_pos++] = (unsigned char)(b); }
229 /** Appends n bytes to buffer. */
230 static void buf_append_n(unsigned char *data, int size)
232     int i;
233     for (i=0; i<size; i++) {
234         buf_append(data[i]);
235     }
238 /*---------------------------------------------------------------------------*/
241  * Converts an arithmetic operator (from ARITHMETIC_NODE) into a byte value.
242  * The bytecode language uses a different operator encoding which is why
243  * we need this function.
244  * @@param op Operator to convert
245  * @@return Bytecode-equivalent operator
246  */
247 static unsigned char operator_to_bytecode(arithmetic_operator op)
249     switch (op) {
250         case PLUS_OPERATOR: return OP_PLUS;
251         case MINUS_OPERATOR:    return OP_MINUS;
252         case MUL_OPERATOR:  return OP_MUL;
253         case DIV_OPERATOR:  return OP_DIV;
254         case MOD_OPERATOR:  return OP_MOD;
255         case AND_OPERATOR:  return OP_AND;
256         case OR_OPERATOR:   return OP_OR;
257         case XOR_OPERATOR:  return OP_XOR;
258         case SHL_OPERATOR:  return OP_SHL;
259         case SHR_OPERATOR:  return OP_SHR;
260         case LT_OPERATOR:   return OP_LT;
261         case GT_OPERATOR:   return OP_GT;
262         case EQ_OPERATOR:   return OP_EQ;
263         case NE_OPERATOR:   return OP_NE;
264         case LE_OPERATOR:   return OP_LE;
265         case GE_OPERATOR:   return OP_GE;
266         case NEG_OPERATOR:  return OP_NEG;
267         case NOT_OPERATOR:  return OP_NOT;
268         case LO_OPERATOR:   return OP_LO;
269         case HI_OPERATOR:   return OP_HI;
270         case UMINUS_OPERATOR:   return OP_UMINUS;
271         case BANK_OPERATOR: return OP_BANK;
273         default:
274         fprintf(stderr, "operator_to_bytecode(): bad operator\n");
275     }
276     return 0xFF;
279 /*---------------------------------------------------------------------------*/
281 /* Maximum number of expressions that the code generator can handle. */
282 #define MAX_EXPRS 16384
284 /* List of expressions involved in code statements. */
285 static astnode *expr_list[MAX_EXPRS];
286 /* Number of expressions generated so far. */
287 static int expr_count = 0;
290  * Registers an expression with the code generator.
291  * Unique 16-bit ID of the expression is returned, which may then be used to refer
292  * to the expression in bytecodes.
293  * @@param expr Expression to register
294  * @@return Unique ID of expression
295  */
296 static int register_expression(astnode *expr)
298     int i;
299     /* See if an equivalent expression already is registered */
300     for (i=0; i<expr_count; i++) {
301         if (astnode_equal(expr, expr_list[i])) {
302             /* Return ID of equivalent expression. */
303             return i;
304         }
305     }
306     /* This is a new expression, add it to end of list if possible. */
307     if (expr_count == MAX_EXPRS) {
308         fprintf(stderr, "register_expression(): buffer overflow\n");
309         return -1;
310     }
311     else {
312         expr_list[expr_count++] = expr;
313         return expr_count-1;
314     }
318  * Serializes an expression recursively.
319  * The result of serializing a leaf node is always (type, value).
320  * The result of serializing an operator node is always (operator, lhs, rhs).
321  * @@param fp File handle
322  * @@param expr Expression to serialize
323  */
324 static void put_expr_recursive(FILE *fp, const astnode *expr)
326     unsigned long v;
327     char *s;
328     symtab_entry *e;
329     if (expr == NULL) { return; }
330 //  printf("put_expr_recursive(%s)\n", astnode_type_to_string(expr->type) );
331     switch (astnode_get_type(expr)) {
332         case INTEGER_NODE:
333         v = (unsigned long)expr->integer;
334         if (v < 0x100) {
335             /* Write type */    put_1(fp, INT_8);
336             /* Write value */   put_1(fp, v);
337         }
338         else if (v < 0x10000) {
339             /* Write type */    put_1(fp, INT_16);
340             /* Write value */   put_2(fp, v);
341         }
342         else if (v < 0x1000000) {
343             /* Write type */    put_1(fp, INT_24);
344             /* Write value */   put_3(fp, v);
345         }
346         else {
347             /* Write type */    put_1(fp, INT_32);
348             /* Write value */   put_4(fp, v);
349         }
350         break;
352         case STRING_NODE:
353         s = expr->string;
354         if (strlen(s) <= 0x100) {
355             /* Write type */    put_1(fp, STR_8);
356             /* Write string */  put_str_8(fp, s);
357         }
358         else {
359             /* Write type */    put_1(fp, STR_16);
360             /* Write string */  put_str_16(fp, s);
361         }
362         break;
364         case IDENTIFIER_NODE:
365         /* Look it up */
366         e = symtab_lookup(expr->ident);
367         /* Write type */
368         put_1(fp, (e->flags & EXTRN_FLAG) ? EXTRN : LOCAL);
369         /* Write ID */
370         put_2(fp, e->tag);
371         break;
373         case ARITHMETIC_NODE:
374         /* The operator goes first */
375         put_1(fp, operator_to_bytecode(expr->oper) );
376         /* Then left-hand side */
377         put_expr_recursive(fp, LHS(expr));
378         /* Then right-hand side */
379         put_expr_recursive(fp, RHS(expr));
380         break;
382         case CURRENT_PC_NODE:
383         put_1(fp, PC);
384         break;
386         default:
387         /* Error */
388         fprintf(
389             stderr,
390             "put_expr_recursive(): unknown expression type (%s)\n",
391             astnode_type_to_string(astnode_get_type(expr))
392         );
393         break;
394     }
398  * Serializes an expression.
399  * The expression is written in postfix form so that it can be easily evaluated
400  * even as pure binary.
401  * @@param fp File handle
402  * @@param expr Expression to serialize
403  */
404 static void put_expr(FILE *fp, const astnode *expr)
406     put_expr_recursive(fp, expr);
410  * Writes all expressions registered during code generation to file.
411  * @@param fp File handle
412  */
413 static void put_expressions(FILE *fp)
415     int i;
416     /* Write expression count */
417     put_2(fp, expr_count);
418     /* Write serialized expressions */
419     for (i=0; i<expr_count; i++) {
420         put_expr(fp, expr_list[i]);
421     }
424 /*---------------------------------------------------------------------------*/
427  * Tests if two file location descriptors are equal.
428  */
429 static int locations_are_equal(const location *l1, const location *l2)
431     return ((l1->first_line == l2->first_line) && (strcmp(l1->file, l2->file) == 0));
434 /*---------------------------------------------------------------------------*/
437  * Writes a statement to file.
438  * @@param fp File handle
439  * @@param n Statement
440  */
441 static void put_statement(FILE *fp, const astnode *n, location *loc)
443     symtab_entry *e;
444     astnode *expr;
445     astnode *type;
446     int len;
447     int i;
448     int line;
449     unsigned char flags;
450     static int tag = 0; /* Used to give labels unique IDs */
452     /* See if we should embed file+line information */
453     if (xasm_args.debug && !locations_are_equal(loc, &n->loc) ) {
454         buf_flush(fp);
455         if (strcmp(loc->file, n->loc.file) != 0) {
456             put_1(fp, CMD_FILE);
457             put_str_8(fp, n->loc.file);
458         }
459         if (loc->first_line != n->loc.first_line) {
460             line = n->loc.first_line;
461             if (line == loc->first_line + 1) {
462                 put_1(fp, CMD_LINE_INC);
463             } else {
464                 if (line < 256) {
465                     put_1(fp, CMD_LINE8);
466                     put_1(fp, line);
467                 }
468                 else if (line < 65536) {
469                     put_1(fp, CMD_LINE16);
470                     put_2(fp, line);
471                 }
472                 else {
473                     put_1(fp, CMD_LINE24);
474                     put_3(fp, line);
475                 }
476             }
477         }
478     }
479     *loc = n->loc;
481     switch (astnode_get_type(n)) {
483         case LABEL_NODE:
484         buf_flush(fp);
485         /* Write command */
486         put_1(fp, CMD_LABEL);
487         /* Look it up in symbol table */
488         e = symtab_lookup(n->label);
489         /* IMPORTANT: Tag label uniquely so we can refer to it in expressions */
490         e->tag = tag++;
491         /* Write flag byte */
492         flags = 0;
493         flags |= (e->flags & PUBLIC_FLAG) ? LABEL_FLAG_EXPORT : 0;
494         flags |= (e->flags & ZEROPAGE_FLAG) ? LABEL_FLAG_ZEROPAGE : 0;
495         flags |= (e->flags & ALIGN_FLAG) ? LABEL_FLAG_ALIGN : 0;
496         flags |= (e->flags & ADDR_FLAG) ? LABEL_FLAG_ADDR : 0;
497         put_1(fp, flags);
498         /* If exported, write name also */
499         if (e->flags & PUBLIC_FLAG) {
500             put_str_8(fp, e->id);
501         }
502         /* if alignment, write that too */
503         if (e->flags & ALIGN_FLAG) {
504             put_1(fp, e->align);
505         }
506         /* if address, write that too */
507         if (e->flags & ADDR_FLAG) {
508             put_2(fp, e->address);
509         }
510         break;
512         case INSTRUCTION_NODE:
513         /* Get # of bytes such a 6502 instruction occupies */
514         len = opcode_length(n->instr.opcode);
515         if (len == 1) {
516             /* Instruction has no operand, so append it to binary buffer. */
517             buf_append(n->instr.opcode);
518         }
519         else {
520             /* Instruction has an operand.
521             It may be a constant or something unresolved. */
522             expr = astnode_get_child(n, 0);
523             if (astnode_get_type(expr) == INTEGER_NODE) {
524                 /* Instruction has constant operand, so append it to binary buffer. */
525                 buf_append(n->instr.opcode);
526                 /* Lo byte */
527                 buf_append(expr->integer);
528                 if (len == 3) {
529                     /* Hi byte */
530                     buf_append(expr->integer >> 8);
531                 }
532             }
533             else {
534                 /* Instruction has unresolved operand. */
535                 /* Flush binary buffer to file */
536                 buf_flush(fp);
537                 /* Output 4-byte sequence: CMD_INSTR [opcode] [expr-id] */
538                 put_1(fp, CMD_INSTR);
539                 put_1(fp, n->instr.opcode);
540                 put_2(fp, register_expression(expr));
541             }
542         }
543         break;
545         case BINARY_NODE:
546         /* Append the binary to the buffer */
547         buf_append_n(n->binary.data, n->binary.size);
548         break;
550         case DATA_NODE:
551         i = 0;
552         type = LHS(n);
553         /* Go through all the elements of the data array */
554         for (expr = RHS(n); expr != NULL; expr = astnode_get_next_sibling(expr) ) {
555             if (astnode_get_type(expr) == INTEGER_NODE) {
556                 /* Constant, output as binary */
557                 switch (type->datatype) {
558                     case BYTE_DATATYPE:
559                     buf_append(expr->integer);
560                     break;
562                     case WORD_DATATYPE:
563                     /* Note: little-endian here (6502) */
564                     buf_append(expr->integer);
565                     buf_append(expr->integer >> 8);
566                     break;
568                     case DWORD_DATATYPE:
569                     /* Note: little-endian here (6502) */
570                     buf_append(expr->integer);
571                     buf_append(expr->integer >> 8);
572                     buf_append(expr->integer >> 16);
573                     buf_append(expr->integer >> 24);
574                     break;
576                     default:
577                     /* Nada */
578                     break;
579                 }
580             }
581             else {
582                 /* Unresolved. Linker will handle it. */
583                 /* Flush binary buffer to file */
584                 buf_flush(fp);
585                 /* Output 3-byte sequence: [type-cmd] [expr-id] */
586                 switch (type->datatype) {
587                     case BYTE_DATATYPE: put_1(fp, CMD_DB);  break;
588                     case WORD_DATATYPE: put_1(fp, CMD_DW);  break;
589                     case DWORD_DATATYPE:    put_1(fp, CMD_DD);  break;
590                     default:
591                     /* Nada */
592                     break;
593                 }
594                 put_2(fp, register_expression(expr));
595             }
596         }
597         break;
599         case STORAGE_NODE:
600         buf_flush(fp);
601         type = LHS(n);
602         assert(type->datatype == BYTE_DATATYPE);
603         /* Get expression which is the count */
604         expr = RHS(n);
605         /* Write command */
606         if (astnode_get_type(expr) == INTEGER_NODE) {
607             /* Use the immediate form. */
608             /* Calculate the # of bytes. */
609             len = expr->integer;
610             /* Select bytecode depending on whether count fits in 8 bits or not */
611             if (len <= 0x100) {
612                 /* Write command */
613                 put_1(fp, CMD_DSI8);
614                 /* Write count */
615                 put_1(fp, len-1);
616             }
617             else {
618                 /* Write command */
619                 put_1(fp, CMD_DSI16);
620                 /* Write count */
621                 put_2(fp, len-1);
622             }
623         }
624         else {
625             /* Use the unresolved form. */
626             put_1(fp, CMD_DSB);
627             /* Write expression ID */
628             put_2(fp, register_expression(expr));
629         }
630         break;
632         case INCSRC_NODE:
633         case INCBIN_NODE:
634         case CHARMAP_NODE:
635         case STRUC_DECL_NODE:
636         case UNION_DECL_NODE:
637         case ENUM_DECL_NODE:
638         case RECORD_DECL_NODE:
639         /* Ignore */
640         break;
642         default:
643         /* Nada */
644         fprintf(stderr, "put_statement(%s): unsupported type\n", astnode_type_to_string(astnode_get_type(n)));
645         break;
646     }
649 /*---------------------------------------------------------------------------*/
652  * Writes the public constants to file.
653  * @@param fp File handle
654  */
655 static void put_public_constants(FILE *fp)
657     symbol_ident_list list;
658     unsigned long v;
659     char *s;
660     symtab_entry *e;
661     int i;
662     astnode *expr;
663     int count;
665     /* 16-bit count followed by (name, type, value) triplets */
667     symtab_list_type(CONSTANT_SYMBOL, &list);
668     /* Make one iteration to look them up and count them */
669     count = 0;
670     for (i=0; i<list.size; i++) {
671         e = symtab_lookup(list.idents[i]);
672         if (e->flags & PUBLIC_FLAG) {
673             count++;
674         }
675     }
676     /* Write count */
677     put_2(fp, count);
678     /* Write triplets */
679     for (i=0; i<list.size; i++) {
680         e = symtab_lookup(list.idents[i]);
681         if (e->flags & PUBLIC_FLAG) {
682             /* Write the name */
683             put_str_8(fp, e->id);
684             /* Get the expression which represents the value */
685             expr = (astnode *)e->def;
686             /* Write the type and value */
687             switch (astnode_get_type(expr)) {
688                 case INTEGER_NODE:
689                 v = (unsigned long)expr->integer;
690                 if (v < 0x100) {
691                     /* Write type */    put_1(fp, INT_8);
692                     /* Write value */   put_1(fp, v);
693                 }
694                 else if (v < 0x10000) {
695                     /* Write type */    put_1(fp, INT_16);
696                     /* Write value */   put_2(fp, v);
697                 }
698                 else if (v < 0x1000000) {
699                     /* Write type */    put_1(fp, INT_24);
700                     /* Write value */   put_3(fp, v);
701                 }
702                 else {
703                     /* Write type */    put_1(fp, INT_32);
704                     /* Write value */   put_4(fp, v);
705                 }
706                 break;
708                 case STRING_NODE:
709                 s = expr->string;
710                 if (strlen(s) <= 0x100) {
711                     /* Write type */    put_1(fp, STR_8);
712                     /* Write value */   put_str_8(fp, s);
713                 }
714                 else if (strlen(s) <= 0x10000) {
715                     /* Write type */    put_1(fp, STR_16);
716                     /* Write value */   put_str_16(fp, s);
717                 }
718                 else {
719                     fprintf(stderr, "put_public_constants(): string constant too long\n");
720                 }
721                 break;
723                 default:
724                 fprintf(stderr, "put_public_constants(): expression isn't a constant after all\n");
725                 break;
726             }
727         }
728     }
729     symtab_list_finalize(&list);
733  * Writes the external symbol specifiers to file.
734  * @@param fp File handle
735  */
736 static void put_externals(FILE *fp)
738     symbol_ident_list list;
739     symtab_entry *e;
740     int i;
741     int tag;
742     int count;
743     /* number of units explicitly imported from */
744     put_1(fp, 0x00);    /* TODO */
745     /* List of unit names (TODO) */
747     /* 16-bit count followed by name list */
749     symtab_list_type(ANY_SYMBOL, &list);
750     /* One iteration to count them */
751     count = 0;
752     for (i=0; i<list.size; i++) {
753         e = symtab_lookup(list.idents[i]);
754         if (e->flags & EXTRN_FLAG) {
755             count++;
756         }
757     }
758     put_2(fp, count);
759     /* Another iteration to output them */
760     tag = 0;
761     for (i=0; i<list.size; i++) {
762         /* Look it up */
763         e = symtab_lookup(list.idents[i]);
764         if (e->flags & EXTRN_FLAG) {
765             /* IMPORTANT: Set unique tag so we can refer to it in expressions */
766             /* (This probably shouldn't be done here though...???) */
767             e->tag = tag++;
768             /* Write unit (TODO) */
769             put_1(fp, 0x00);    /* 0 = Any unit */
770             /* Write name */
771             put_str_8(fp, list.idents[i]);
772         }
773     }
774     symtab_list_finalize(&list);
778  * Writes a segment to file.
779  * @@param fp File handle
780  * @@param root AST node which has the list of assembly statements as its children
781  * @@param targetseg Specifies the type of segment (data or code)
782  */
783 static void put_segment(FILE *fp, const astnode *root, int targetseg)
785     astnode *n;
786     int seg;    /* The type of segment we're in */
787     fpos_t size_pos, end_pos;
788     long start, end;
789     location loc = { -1, -1, -1, -1, "" };
791     /* Write the size of the segment (backpatched later) */
792     fgetpos(fp, &size_pos);
793     put_3(fp, 0xDECADE);    /* 24-bit integer */
795     seg = 2;    /* Codeseg is default */
796     buf_reset();
797     start = ftell(fp);
798     /* Step through all the nodes in the list */
799     for (n = astnode_get_first_child(root); n != NULL; n = astnode_get_next_sibling(n) ) {
800         switch (astnode_get_type(n)) {
801             case DATASEG_NODE:
802             seg = 1;    /* Now we're in a DATA segment */
803             break;
805             case CODESEG_NODE:
806             seg = 2;    /* Now we're in a CODE segment */
807             break;
809             default:
810             /* Only output the statement if we're in the proper segment. */
811             if (seg == targetseg) {
812                 put_statement(fp, n, &loc);
813             }
814             break;
815         }
816     }
817     buf_flush(fp);
818     put_1(fp, CMD_END);
819     end = ftell(fp);
820     /* Backpatch size */
821     fgetpos(fp, &end_pos);  /* First save the current (end) position */
822     fsetpos(fp, &size_pos); /* Set position to where the size should be written */
823     put_3(fp, end - start); /* Size is difference between end and start offset */
824     fsetpos(fp, &end_pos);  /* Restore end position */
828  * Writes a sequence of parsed assembly statements to file.
829  * @@param fp File handle
830  * @@param root AST node which has the assembly statements as its children
831  */
832 static void put_bytecodes(FILE *fp, const astnode *root)
834     /* Write data segment first */
835     put_segment(fp, root, 1);
836     /* Write code segment next */
837     put_segment(fp, root, 2);
840 /*---------------------------------------------------------------------------*/
843  * Writes an object file which captures all the information in a syntax tree.
844  * @@param root Root of the syntax tree
845  * @@param filename Name of the file to write to (object file)
846  */
847 void codegen_write(const astnode *root, const char *filename)
849     /* Attempt to open file for writing */
850     FILE *fp = fopen(filename, "wb");
851     if (fp == NULL) {
852         fprintf(stderr, "codegen_write: could not open '%s' for writing\n", filename);
853         /* ### increase error count */
854         return;
855     }
857     expr_count = 0;
858     buf_file = fp;
860     /* Write magic number */
861     put_2(fp, A_MAGIC);
862     /* Write version (upper nibble=major, lower nibble=minor) */
863     put_1(fp, A_VERSION);
865     /* Write exported constants. */
866     put_public_constants(fp);
868     /* Write imported symbols. */
869     put_externals(fp);
871     /* Write bytecodes. */
872     put_bytecodes(fp, root);
874     /* Write expressions */
875     put_expressions(fp);
877     /* Close the file */
878     fclose(fp);
885 @progress
887 text
888 @d2 1
889 a2 1
890  * $Id: codegen.c,v 1.8 2007/08/07 22:42:17 khansen Exp khansen $
891 d4 3
892 d90 1
893 d534 2
894 a535 1
895         type = LHS(n);  /* NB! This is assumed to be BYTE_DATATYPE by now! */
896 d786 1
902 @make sure a CMD_FILE command is output at the start of each segment
904 text
905 @d2 1
906 a2 1
907  * $Id: codegen.c,v 1.7 2007/08/07 21:23:24 khansen Exp khansen $
908 d4 3
909 d563 4
915 @const
917 text
918 @d2 1
919 a2 1
920  * $Id: codegen.c,v 1.6 2007/07/22 13:33:26 khansen Exp khansen $
921 d4 3
922 d367 1
923 a367 1
924 static void put_statement(FILE *fp, const astnode *n)
925 a376 1
926     static location loc = { -1, -1, -1, -1, "" };
927 d379 1
928 a379 1
929     if (xasm_args.debug && !locations_are_equal(&loc, &n->loc) ) {
930 d381 1
931 a381 1
932         if (strcmp(loc.file, n->loc.file) != 0) {
933 d385 1
934 a385 1
935         if (loc.first_line != n->loc.first_line) {
936 d387 1
937 a387 1
938             if (line == loc.first_line + 1) {
939 d389 1
940 a389 2
941             }
942             else {
943 a403 1
944         loc = n->loc;
945 d405 1
946 a567 1
947     loc = n->loc;
948 d710 1
949 d733 1
950 a733 1
951                 put_statement(fp, n);
957 @convert tabs to whitespaces
959 text
960 @d2 1
961 a2 1
962  * $Id: codegen.c,v 1.5 2004/12/19 19:58:37 kenth Exp $
963 d4 3
964 d101 1
965 a101 1
966 static void put_bytes(FILE *f, unsigned char *bytes, int count)
967 d247 1
968 a247 1
969 static void put_expr_recursive(FILE *fp, astnode *expr)
970 d327 1
971 a327 1
972 static void put_expr(FILE *fp, astnode *expr)
973 d352 1
974 a352 1
975 static int locations_are_equal(location *l1, location *l2)
976 d364 1
977 a364 1
978 static void put_statement(FILE *fp, astnode *n)
979 d375 1
980 a375 1
981     
982 d405 1
983 a405 1
984     
985 d704 1
986 a704 1
987 static void put_segment(FILE *fp, astnode *root, int targetseg)
988 d752 1
989 a752 1
990 static void put_bytecodes(FILE *fp, astnode *root)
991 d767 1
992 a767 1
993 void codegen_write(astnode *root, char *filename)
999 @xorcyst 1.4.0
1001 text
1002 @d2 1
1003 a2 1
1004  * $Id: codegen.c,v 1.4 2004/12/18 16:58:52 kenth Exp kenth $
1005 d4 3
1006 d100 5
1007 a104 5
1008         int i;
1009         /* Write the bytes */
1010         for (i=0; i<count; i++) {
1011                 put_1(f, bytes[i]);
1012         }
1013 d125 19
1014 a143 19
1015         if (buf_pos > 0) {
1016                 if (buf_pos <= 0x100) {
1017                         /* Use 8-bit form. */
1018                         put_1(f, CMD_BIN8);
1019                         put_1(f, buf_pos - 1);
1020                         put_bytes(f, buf, buf_pos);
1021                 }
1022                 else if (buf_pos <= 0x10000) {
1023                         /* Use 16-bit form. */
1024                         put_1(f, CMD_BIN16);
1025                         put_2(f, buf_pos - 1);
1026                         put_bytes(f, buf, buf_pos);
1027                 }
1028                 else {
1029                         /* Error, buffer overflow. */
1030                         fprintf(stderr, "buf_flush: buffer overflow\n");
1031                 }
1032                 buf_reset();
1033         }
1034 d152 4
1035 a155 4
1036         int i;
1037         for (i=0; i<size; i++) {
1038                 buf_append(data[i]);
1039         }
1040 d169 28
1041 a196 28
1042         switch (op) {
1043                 case PLUS_OPERATOR:     return OP_PLUS;
1044                 case MINUS_OPERATOR:    return OP_MINUS;
1045                 case MUL_OPERATOR:      return OP_MUL;
1046                 case DIV_OPERATOR:      return OP_DIV;
1047                 case MOD_OPERATOR:      return OP_MOD;
1048                 case AND_OPERATOR:      return OP_AND;
1049                 case OR_OPERATOR:       return OP_OR;
1050                 case XOR_OPERATOR:      return OP_XOR;
1051                 case SHL_OPERATOR:      return OP_SHL;
1052                 case SHR_OPERATOR:      return OP_SHR;
1053                 case LT_OPERATOR:       return OP_LT;
1054                 case GT_OPERATOR:       return OP_GT;
1055                 case EQ_OPERATOR:       return OP_EQ;
1056                 case NE_OPERATOR:       return OP_NE;
1057                 case LE_OPERATOR:       return OP_LE;
1058                 case GE_OPERATOR:       return OP_GE;
1059                 case NEG_OPERATOR:      return OP_NEG;
1060                 case NOT_OPERATOR:      return OP_NOT;
1061                 case LO_OPERATOR:       return OP_LO;
1062                 case HI_OPERATOR:       return OP_HI;
1063                 case UMINUS_OPERATOR:   return OP_UMINUS;
1064                 case BANK_OPERATOR:     return OP_BANK;
1066                 default:
1067                 fprintf(stderr, "operator_to_bytecode(): bad operator\n");
1068         }
1069         return 0xFF;
1070 d218 17
1071 a234 17
1072         int i;
1073         /* See if an equivalent expression already is registered */
1074         for (i=0; i<expr_count; i++) {
1075                 if (astnode_equal(expr, expr_list[i])) {
1076                         /* Return ID of equivalent expression. */
1077                         return i;
1078                 }
1079         }
1080         /* This is a new expression, add it to end of list if possible. */
1081         if (expr_count == MAX_EXPRS) {
1082                 fprintf(stderr, "register_expression(): buffer overflow\n");
1083                 return -1;
1084         }
1085         else {
1086                 expr_list[expr_count++] = expr;
1087                 return expr_count-1;
1088         }
1089 d246 69
1090 a314 69
1091         unsigned long v;
1092         char *s;
1093         symtab_entry *e;
1094         if (expr == NULL) { return; }
1095 //      printf("put_expr_recursive(%s)\n", astnode_type_to_string(expr->type) );
1096         switch (astnode_get_type(expr)) {
1097                 case INTEGER_NODE:
1098                 v = (unsigned long)expr->integer;
1099                 if (v < 0x100) {
1100                         /* Write type */        put_1(fp, INT_8);
1101                         /* Write value */       put_1(fp, v);
1102                 }
1103                 else if (v < 0x10000) {
1104                         /* Write type */        put_1(fp, INT_16);
1105                         /* Write value */       put_2(fp, v);
1106                 }
1107                 else if (v < 0x1000000) {
1108                         /* Write type */        put_1(fp, INT_24);
1109                         /* Write value */       put_3(fp, v);
1110                 }
1111                 else {
1112                         /* Write type */        put_1(fp, INT_32);
1113                         /* Write value */       put_4(fp, v);
1114                 }
1115                 break;
1117                 case STRING_NODE:
1118                 s = expr->string;
1119                 if (strlen(s) <= 0x100) {
1120                         /* Write type */        put_1(fp, STR_8);
1121                         /* Write string */      put_str_8(fp, s);
1122                 }
1123                 else {
1124                         /* Write type */        put_1(fp, STR_16);
1125                         /* Write string */      put_str_16(fp, s);
1126                 }
1127                 break;
1129                 case IDENTIFIER_NODE:
1130                 /* Look it up */
1131                 e = symtab_lookup(expr->ident);
1132                 /* Write type */
1133                 put_1(fp, (e->flags & EXTRN_FLAG) ? EXTRN : LOCAL);
1134                 /* Write ID */
1135                 put_2(fp, e->tag);
1136                 break;
1138                 case ARITHMETIC_NODE:
1139                 /* The operator goes first */
1140                 put_1(fp, operator_to_bytecode(expr->oper) );
1141                 /* Then left-hand side */
1142                 put_expr_recursive(fp, LHS(expr));
1143                 /* Then right-hand side */
1144                 put_expr_recursive(fp, RHS(expr));
1145                 break;
1147                 case CURRENT_PC_NODE:
1148                 put_1(fp, PC);
1149                 break;
1151                 default:
1152                 /* Error */
1153                 fprintf(
1154                         stderr,
1155                         "put_expr_recursive(): unknown expression type (%s)\n",
1156                         astnode_type_to_string(astnode_get_type(expr))
1157                 );
1158                 break;
1159         }
1160 d326 1
1161 a326 1
1162         put_expr_recursive(fp, expr);
1163 d335 7
1164 a341 7
1165         int i;
1166         /* Write expression count */
1167         put_2(fp, expr_count);
1168         /* Write serialized expressions */
1169         for (i=0; i<expr_count; i++) {
1170                 put_expr(fp, expr_list[i]);
1171         }
1172 d351 1
1173 a351 1
1174         return ((l1->first_line == l2->first_line) && (strcmp(l1->file, l2->file) == 0));
1175 d363 202
1176 a564 202
1177         symtab_entry *e;
1178         astnode *expr;
1179         astnode *type;
1180         int len;
1181         int i;
1182         int line;
1183         unsigned char flags;
1184         static int tag = 0;     /* Used to give labels unique IDs */
1185         static location loc = { -1, -1, -1, -1, "" };
1186         
1187         /* See if we should embed file+line information */
1188         if (xasm_args.debug && !locations_are_equal(&loc, &n->loc) ) {
1189                 buf_flush(fp);
1190                 if (strcmp(loc.file, n->loc.file) != 0) {
1191                         put_1(fp, CMD_FILE);
1192                         put_str_8(fp, n->loc.file);
1193                 }
1194                 if (loc.first_line != n->loc.first_line) {
1195                         line = n->loc.first_line;
1196                         if (line == loc.first_line + 1) {
1197                                 put_1(fp, CMD_LINE_INC);
1198                         }
1199                         else {
1200                                 if (line < 256) {
1201                                         put_1(fp, CMD_LINE8);
1202                                         put_1(fp, line);
1203                                 }
1204                                 else if (line < 65536) {
1205                                         put_1(fp, CMD_LINE16);
1206                                         put_2(fp, line);
1207                                 }
1208                                 else {
1209                                         put_1(fp, CMD_LINE24);
1210                                         put_3(fp, line);
1211                                 }
1212                         }
1213                 }
1214                 loc = n->loc;
1215         }
1216         
1217         switch (astnode_get_type(n)) {
1219                 case LABEL_NODE:
1220                 buf_flush(fp);
1221                 /* Write command */
1222                 put_1(fp, CMD_LABEL);
1223                 /* Look it up in symbol table */
1224                 e = symtab_lookup(n->label);
1225                 /* IMPORTANT: Tag label uniquely so we can refer to it in expressions */
1226                 e->tag = tag++;
1227                 /* Write flag byte */
1228                 flags = 0;
1229                 flags |= (e->flags & PUBLIC_FLAG) ? LABEL_FLAG_EXPORT : 0;
1230                 flags |= (e->flags & ZEROPAGE_FLAG) ? LABEL_FLAG_ZEROPAGE : 0;
1231                 flags |= (e->flags & ALIGN_FLAG) ? LABEL_FLAG_ALIGN : 0;
1232                 flags |= (e->flags & ADDR_FLAG) ? LABEL_FLAG_ADDR : 0;
1233                 put_1(fp, flags);
1234                 /* If exported, write name also */
1235                 if (e->flags & PUBLIC_FLAG) {
1236                         put_str_8(fp, e->id);
1237                 }
1238                 /* if alignment, write that too */
1239                 if (e->flags & ALIGN_FLAG) {
1240                         put_1(fp, e->align);
1241                 }
1242                 /* if address, write that too */
1243                 if (e->flags & ADDR_FLAG) {
1244                         put_2(fp, e->address);
1245                 }
1246                 break;
1248                 case INSTRUCTION_NODE:
1249                 /* Get # of bytes such a 6502 instruction occupies */
1250                 len = opcode_length(n->instr.opcode);
1251                 if (len == 1) {
1252                         /* Instruction has no operand, so append it to binary buffer. */
1253                         buf_append(n->instr.opcode);
1254                 }
1255                 else {
1256                         /* Instruction has an operand.
1257                         It may be a constant or something unresolved. */
1258                         expr = astnode_get_child(n, 0);
1259                         if (astnode_get_type(expr) == INTEGER_NODE) {
1260                                 /* Instruction has constant operand, so append it to binary buffer. */
1261                                 buf_append(n->instr.opcode);
1262                                 /* Lo byte */
1263                                 buf_append(expr->integer);
1264                                 if (len == 3) {
1265                                         /* Hi byte */
1266                                         buf_append(expr->integer >> 8);
1267                                 }
1268                         }
1269                         else {
1270                                 /* Instruction has unresolved operand. */
1271                                 /* Flush binary buffer to file */
1272                                 buf_flush(fp);
1273                                 /* Output 4-byte sequence: CMD_INSTR [opcode] [expr-id] */
1274                                 put_1(fp, CMD_INSTR);
1275                                 put_1(fp, n->instr.opcode);
1276                                 put_2(fp, register_expression(expr));
1277                         }
1278                 }
1279                 break;
1281                 case BINARY_NODE:
1282                 /* Append the binary to the buffer */
1283                 buf_append_n(n->binary.data, n->binary.size);
1284                 break;
1286                 case DATA_NODE:
1287                 i = 0;
1288                 type = LHS(n);
1289                 /* Go through all the elements of the data array */
1290                 for (expr = RHS(n); expr != NULL; expr = astnode_get_next_sibling(expr) ) {
1291                         if (astnode_get_type(expr) == INTEGER_NODE) {
1292                                 /* Constant, output as binary */
1293                                 switch (type->datatype) {
1294                                         case BYTE_DATATYPE:
1295                                         buf_append(expr->integer);
1296                                         break;
1298                                         case WORD_DATATYPE:
1299                                         /* Note: little-endian here (6502) */
1300                                         buf_append(expr->integer);
1301                                         buf_append(expr->integer >> 8);
1302                                         break;
1304                                         case DWORD_DATATYPE:
1305                                         /* Note: little-endian here (6502) */
1306                                         buf_append(expr->integer);
1307                                         buf_append(expr->integer >> 8);
1308                                         buf_append(expr->integer >> 16);
1309                                         buf_append(expr->integer >> 24);
1310                                         break;
1312                                         default:
1313                                         /* Nada */
1314                                         break;
1315                                 }
1316                         }
1317                         else {
1318                                 /* Unresolved. Linker will handle it. */
1319                                 /* Flush binary buffer to file */
1320                                 buf_flush(fp);
1321                                 /* Output 3-byte sequence: [type-cmd] [expr-id] */
1322                                 switch (type->datatype) {
1323                                         case BYTE_DATATYPE:     put_1(fp, CMD_DB);      break;
1324                                         case WORD_DATATYPE:     put_1(fp, CMD_DW);      break;
1325                                         case DWORD_DATATYPE:    put_1(fp, CMD_DD);      break;
1326                                         default:
1327                                         /* Nada */
1328                                         break;
1329                                 }
1330                                 put_2(fp, register_expression(expr));
1331                         }
1332                 }
1333                 break;
1335                 case STORAGE_NODE:
1336                 buf_flush(fp);
1337                 type = LHS(n);  /* NB! This is assumed to be BYTE_DATATYPE by now! */
1338                 /* Get expression which is the count */
1339                 expr = RHS(n);
1340                 /* Write command */
1341                 if (astnode_get_type(expr) == INTEGER_NODE) {
1342                         /* Use the immediate form. */
1343                         /* Calculate the # of bytes. */
1344                         len = expr->integer;
1345                         /* Select bytecode depending on whether count fits in 8 bits or not */
1346                         if (len <= 0x100) {
1347                                 /* Write command */
1348                                 put_1(fp, CMD_DSI8);
1349                                 /* Write count */
1350                                 put_1(fp, len-1);
1351                         }
1352                         else {
1353                                 /* Write command */
1354                                 put_1(fp, CMD_DSI16);
1355                                 /* Write count */
1356                                 put_2(fp, len-1);
1357                         }
1358                 }
1359                 else {
1360                         /* Use the unresolved form. */
1361                         put_1(fp, CMD_DSB);
1362                         /* Write expression ID */
1363                         put_2(fp, register_expression(expr));
1364                 }
1365                 break;
1367                 case INCSRC_NODE:
1368                 case INCBIN_NODE:
1369                 case CHARMAP_NODE:
1370                 /* Ignore */
1371                 break;
1373                 default:
1374                 /* Nada */
1375                 fprintf(stderr, "put_statement(%s): unsupported type\n", astnode_type_to_string(astnode_get_type(n)));
1376                 break;
1377         }
1378         loc = n->loc;
1379 d575 73
1380 a647 73
1381         symbol_ident_list list;
1382         unsigned long v;
1383         char *s;
1384         symtab_entry *e;
1385         int i;
1386         astnode *expr;
1387         int count;
1389         /* 16-bit count followed by (name, type, value) triplets */
1391         symtab_list_type(CONSTANT_SYMBOL, &list);
1392         /* Make one iteration to look them up and count them */
1393         count = 0;
1394         for (i=0; i<list.size; i++) {
1395                 e = symtab_lookup(list.idents[i]);
1396                 if (e->flags & PUBLIC_FLAG) {
1397                         count++;
1398                 }
1399         }
1400         /* Write count */
1401         put_2(fp, count);
1402         /* Write triplets */
1403         for (i=0; i<list.size; i++) {
1404                 e = symtab_lookup(list.idents[i]);
1405                 if (e->flags & PUBLIC_FLAG) {
1406                         /* Write the name */
1407                         put_str_8(fp, e->id);
1408                         /* Get the expression which represents the value */
1409                         expr = (astnode *)e->def;
1410                         /* Write the type and value */
1411                         switch (astnode_get_type(expr)) {
1412                                 case INTEGER_NODE:
1413                                 v = (unsigned long)expr->integer;
1414                                 if (v < 0x100) {
1415                                         /* Write type */        put_1(fp, INT_8);
1416                                         /* Write value */       put_1(fp, v);
1417                                 }
1418                                 else if (v < 0x10000) {
1419                                         /* Write type */        put_1(fp, INT_16);
1420                                         /* Write value */       put_2(fp, v);
1421                                 }
1422                                 else if (v < 0x1000000) {
1423                                         /* Write type */        put_1(fp, INT_24);
1424                                         /* Write value */       put_3(fp, v);
1425                                 }
1426                                 else {
1427                                         /* Write type */        put_1(fp, INT_32);
1428                                         /* Write value */       put_4(fp, v);
1429                                 }
1430                                 break;
1432                                 case STRING_NODE:
1433                                 s = expr->string;
1434                                 if (strlen(s) <= 0x100) {
1435                                         /* Write type */        put_1(fp, STR_8);
1436                                         /* Write value */       put_str_8(fp, s);
1437                                 }
1438                                 else if (strlen(s) <= 0x10000) {
1439                                         /* Write type */        put_1(fp, STR_16);
1440                                         /* Write value */       put_str_16(fp, s);
1441                                 }
1442                                 else {
1443                                         fprintf(stderr, "put_public_constants(): string constant too long\n");
1444                                 }
1445                                 break;
1447                                 default:
1448                                 fprintf(stderr, "put_public_constants(): expression isn't a constant after all\n");
1449                                 break;
1450                         }
1451                 }
1452         }
1453         symtab_list_finalize(&list);
1454 d656 37
1455 a692 37
1456         symbol_ident_list list;
1457         symtab_entry *e;
1458         int i;
1459         int tag;
1460         int count;
1461         /* number of units explicitly imported from */
1462         put_1(fp, 0x00);        /* TODO */
1463         /* List of unit names (TODO) */
1465         /* 16-bit count followed by name list */
1467         symtab_list_type(ANY_SYMBOL, &list);
1468         /* One iteration to count them */
1469         count = 0;
1470         for (i=0; i<list.size; i++) {
1471                 e = symtab_lookup(list.idents[i]);
1472                 if (e->flags & EXTRN_FLAG) {
1473                         count++;
1474                 }
1475         }
1476         put_2(fp, count);
1477         /* Another iteration to output them */
1478         tag = 0;
1479         for (i=0; i<list.size; i++) {
1480                 /* Look it up */
1481                 e = symtab_lookup(list.idents[i]);
1482                 if (e->flags & EXTRN_FLAG) {
1483                         /* IMPORTANT: Set unique tag so we can refer to it in expressions */
1484                         /* (This probably shouldn't be done here though...???) */
1485                         e->tag = tag++;
1486                         /* Write unit (TODO) */
1487                         put_1(fp, 0x00);        /* 0 = Any unit */
1488                         /* Write name */
1489                         put_str_8(fp, list.idents[i]);
1490                 }
1491         }
1492         symtab_list_finalize(&list);
1493 d703 39
1494 a741 39
1495         astnode *n;
1496         int seg;        /* The type of segment we're in */
1497         fpos_t size_pos, end_pos;
1498         long start, end;
1500         /* Write the size of the segment (backpatched later) */
1501         fgetpos(fp, &size_pos);
1502         put_3(fp, 0xDECADE);    /* 24-bit integer */
1504         seg = 2;        /* Codeseg is default */
1505         buf_reset();
1506         start = ftell(fp);
1507         /* Step through all the nodes in the list */
1508         for (n = astnode_get_first_child(root); n != NULL; n = astnode_get_next_sibling(n) ) {
1509                 switch (astnode_get_type(n)) {
1510                         case DATASEG_NODE:
1511                         seg = 1;        /* Now we're in a DATA segment */
1512                         break;
1514                         case CODESEG_NODE:
1515                         seg = 2;        /* Now we're in a CODE segment */
1516                         break;
1518                         default:
1519                         /* Only output the statement if we're in the proper segment. */
1520                         if (seg == targetseg) {
1521                                 put_statement(fp, n);
1522                         }
1523                         break;
1524                 }
1525         }
1526         buf_flush(fp);
1527         put_1(fp, CMD_END);
1528         end = ftell(fp);
1529         /* Backpatch size */
1530         fgetpos(fp, &end_pos);  /* First save the current (end) position */
1531         fsetpos(fp, &size_pos); /* Set position to where the size should be written */
1532         put_3(fp, end - start); /* Size is difference between end and start offset */
1533         fsetpos(fp, &end_pos);  /* Restore end position */
1534 d751 4
1535 a754 4
1536         /* Write data segment first */
1537         put_segment(fp, root, 1);
1538         /* Write code segment next */
1539         put_segment(fp, root, 2);
1540 d766 20
1541 a785 20
1542         /* Attempt to open file for writing */
1543         FILE *fp = fopen(filename, "wb");
1544         if (fp == NULL) {
1545                 fprintf(stderr, "codegen_write: could not open '%s' for writing\n", filename);
1546                 return;
1547         }
1549         expr_count = 0;
1550         buf_file = fp;
1552         /* Write magic number */
1553         put_2(fp, A_MAGIC);
1554         /* Write version (upper nibble=major, lower nibble=minor) */
1555         put_1(fp, A_VERSION);
1557         /* Write exported constants. */
1558         put_public_constants(fp);
1560         /* Write imported symbols. */
1561         put_externals(fp);
1562 d787 2
1563 a788 2
1564         /* Write bytecodes. */
1565         put_bytecodes(fp, root);
1566 d790 2
1567 a791 2
1568         /* Write expressions */
1569         put_expressions(fp);
1570 d793 2
1571 a794 2
1572         /* Close the file */
1573         fclose(fp);
1579 @outputs file and line info if --debug
1580 CMD_DSW, CMD_DSD gone
1582 text
1583 @d2 1
1584 a2 1
1585  * $Id: codegen.c,v 1.3 2004/12/14 01:49:14 kenth Exp kenth $
1586 d4 4
1587 d366 1
1588 d410 7
1589 a416 2
1590                 /* Write export flag byte */
1591                 put_1(fp, (e->flags & PUBLIC_FLAG) ? 1 : 0);
1592 d421 8
1598 @xorcyst 1.3.0
1600 text
1601 @d2 1
1602 a2 1
1603  * $Id: codegen.c,v 1.2 2004/12/06 04:52:36 kenth Exp kenth $
1604 d4 3
1605 d361 1
1606 d363 1
1607 a363 1
1608         static location loc = { -1, -1, -1, -1, NULL };
1609 d365 29
1610 a393 3
1611 //      if (!locations_are_equal(&loc, &n->loc)) {
1612                 // TODO: output file/line info
1613 //      }
1614 d502 1
1615 a502 1
1616                 type = LHS(n);
1617 a509 8
1618                         switch (type->datatype) {
1619                                 case BYTE_DATATYPE:     len = len*1;    break;
1620                                 case WORD_DATATYPE:     len = len*2;    break;
1621                                 case DWORD_DATATYPE:    len = len*4;    break;
1622                                 default:
1623                                 /* Nada */
1624                                 break;
1625                         }
1626 d526 1
1627 a526 8
1628                         switch (type->datatype) {
1629                                 case BYTE_DATATYPE:     put_1(fp, CMD_DSB);     break;
1630                                 case WORD_DATATYPE:     put_1(fp, CMD_DSW);     break;
1631                                 case DWORD_DATATYPE:    put_1(fp, CMD_DSD);     break;
1632                                 default:
1633                                 /* Nada */
1634                                 break;
1635                         }
1636 d609 5
1637 a613 1
1638                                         /* Write length */      put_1(fp, strlen(s) - 1);
1639 d616 1
1640 a616 2
1641                                         /* Write type */        put_1(fp, STR_16);
1642                                         /* Write length */      put_2(fp, strlen(s) - 1);
1643 a617 2
1644                                 /* Write value */
1645                                 put_str(fp, s);
1651 @xorcyst 1.1.0
1653 text
1654 @d2 1
1655 a2 1
1656  * $Id: codegen.c,v 1.1 2004/06/30 07:55:38 kenth Exp kenth $
1657 d4 3
1658 d67 1
1659 d337 10
1660 d359 6
1661 a364 1
1663 d528 1
1669 @Initial revision
1671 text
1672 @d2 5
1673 a6 2
1674  * $Id$
1675  * $Log$
1676 d95 1
1677 d97 1
1678 a97 1
1679 static char buf[0x10000];
1680 d100 2
1681 a103 8
1682 #define buf_append(b) { buf[buf_pos++] = b; }
1683 static void buf_append_n(unsigned char *data, int size)
1685         int i;
1686         for (i=0; i<size; i++) {
1687                 buf_append(data[i]);
1688         }
1690 d132 12
1691 d180 1
1692 a180 1
1693                 fprintf(stderr, "operator_to_bytecode: bad operator\n");
1694 d187 1
1695 d192 1
1696 d214 1
1697 a214 1
1698                 fprintf(stderr, "register_expression: buffer overflow\n");
1699 a222 3
1700 #define LHS(e) astnode_get_child(e, 0)
1701 #define RHS(e) astnode_get_child(e, 1)
1703 d236 1
1704 d274 1
1705 a274 1
1706                 put_1(fp, (e->type == EXTERNAL_SYMBOL) ? EXTRN : LOCAL);
1707 d294 5
1708 a298 1
1709                 fprintf(stderr, "put_expr_recursive: unknown expression type\n");
1710 d341 1
1711 d404 1
1712 d406 1
1713 a406 1
1714                 for (expr = astnode_get_first_child(n); expr != NULL; expr = astnode_get_next_sibling(expr) ) {
1715 d409 1
1716 a409 1
1717                                 switch (n->datatype) {
1718 d413 1
1719 d419 1
1720 d427 4
1721 d434 1
1722 a434 1
1723                                 /* Unresolved. */
1724 d438 1
1725 a438 1
1726                                 switch (n->datatype) {
1727 d442 3
1728 d453 1
1729 d455 1
1730 a455 1
1731                 expr = astnode_get_child(n, 0);
1732 d461 1
1733 a461 1
1734                         switch (n->datatype) {
1735 d465 3
1736 d485 1
1737 a485 1
1738                         switch (n->datatype) {
1739 d489 3
1740 d498 6
1741 d506 1
1742 d585 1
1743 a585 1
1744                                 fprintf(stderr, "put_public_constants: expression isn't a constant after all\n");
1745 d602 2
1746 a603 1
1748 d609 13
1749 a621 2
1750         symtab_list_type(EXTERNAL_SYMBOL, &list);
1751         put_2(fp, list.size);
1752 d625 9
1753 a633 7
1754                 /* IMPORTANT: Set unique tag so we can refer to it in expressions */
1755                 /* (This probably shouldn't be done here though...) */
1756                 e->tag = i;
1757                 /* Write unit (TODO) */
1758                 put_1(fp, 0x00);        /* 0 = Any unit */
1759                 /* Write name */
1760                 put_str_8(fp, list.idents[i]);
1761 d655 1
1762 a655 1
1763         seg = 0;        /* Invalid */
1764 d717 1