extern
This commit is contained in:
		
							parent
							
								
									d1d1c88934
								
							
						
					
					
						commit
						95871ff6bf
					
				
					 8 changed files with 117 additions and 118 deletions
				
			
		
							
								
								
									
										124
									
								
								boot.c
									
										
									
									
									
								
							
							
						
						
									
										124
									
								
								boot.c
									
										
									
									
									
								
							|  | @ -1,4 +1,18 @@ | |||
| #include "boot-lib.h" | ||||
| // libc dependency
 | ||||
| 
 | ||||
| extern void* stdin; | ||||
| extern void* stdout; | ||||
| extern void* stderr; | ||||
| 
 | ||||
| int printf(const char* format, ...); | ||||
| int getchar(); | ||||
| void exit(int status); | ||||
| int fprintf(void* file, const char* format, ...); | ||||
| int ungetc(int ch, void* file); | ||||
| 
 | ||||
| void ungetchar(int ch) { | ||||
|     ungetc(ch, stdin); | ||||
| } | ||||
| 
 | ||||
| // lexer
 | ||||
| 
 | ||||
|  | @ -79,6 +93,7 @@ const int TOKEN_BREAK = 107; | |||
| const int TOKEN_CONTINUE = 108; | ||||
| const int TOKEN_RETURN = 109; | ||||
| 
 | ||||
| const int TOKEN_EXTERN = 126; | ||||
| const int TOKEN_CONST = 127; | ||||
| const int TOKEN_VOID = 128; | ||||
| const int TOKEN_INT = 129; | ||||
|  | @ -121,7 +136,7 @@ int get_escaped_char() { | |||
|     } else if (ch == '\"') { | ||||
|         ch = '\"'; | ||||
|     } else { | ||||
|         eprintf("unexpected escaped character: %c\n", ch); | ||||
|         fprintf(stderr, "unexpected escaped character: %c\n", ch); | ||||
|         exit(1); | ||||
|     } | ||||
|     return ch; | ||||
|  | @ -144,7 +159,7 @@ int parse_string() { | |||
|     int ch; | ||||
|     while ((ch = getchar()) != '"') { | ||||
|         if (ch == -1 || ch == '\n') { | ||||
|             eprintf("expecting '\"'\n"); | ||||
|             fprintf(stderr, "expecting '\"'\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         if (ch == '\\') { | ||||
|  | @ -237,6 +252,8 @@ void parse_id_like(int ch) { | |||
|         token_type = TOKEN_FOR; | ||||
|     } else if (streq(id, "do")) { | ||||
|         token_type = TOKEN_DO; | ||||
|     } else if (streq(id, "extern")) { | ||||
|         token_type = TOKEN_EXTERN; | ||||
|     } | ||||
|     if (token_type != TOKEN_ID) { | ||||
|         rewind_id(0); | ||||
|  | @ -312,7 +329,7 @@ void next_token() { | |||
|             while (1) { | ||||
|                 ch = getchar(); | ||||
|                 if (ch == -1) { | ||||
|                     eprintf("expecting '*/'\n"); | ||||
|                     fprintf(stderr, "expecting '*/'\n"); | ||||
|                     exit(1); | ||||
|                 } | ||||
|                 if (ch == '*') { | ||||
|  | @ -429,7 +446,7 @@ void next_token() { | |||
|             token_data = get_escaped_char(); | ||||
|         } | ||||
|         if (getchar() != '\'') { | ||||
|             eprintf("expecting '\n"); | ||||
|             fprintf(stderr, "expecting '\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|     } else if (ch == '"') { | ||||
|  | @ -444,7 +461,7 @@ void next_token() { | |||
|             } | ||||
|         } | ||||
|         if (token_type != TOKEN_ELLIPSIS) { | ||||
|             eprintf("expecting '...'\n"); | ||||
|             fprintf(stderr, "expecting '...'\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|     } else if (is_digit(ch)) { | ||||
|  | @ -453,22 +470,22 @@ void next_token() { | |||
|     } else if (is_id_start(ch)) { | ||||
|         parse_id_like(ch); | ||||
|     } else { | ||||
|         eprintf("unexpected character: %c(%d)\n", ch, ch); | ||||
|         fprintf(stderr, "unexpected character: %c(%d)\n", ch, ch); | ||||
|         exit(1); | ||||
|     } | ||||
|     eprintf("token: %d\n", token_type); | ||||
|     fprintf(stderr, "token: %d\n", token_type); | ||||
|     if (token_type == TOKEN_ID) { | ||||
|         const char* name = id_table + id_lut[token_data]; | ||||
|         eprintf("  id: %s\n", name); | ||||
|         fprintf(stderr, "  id: %s\n", name); | ||||
|     } else if (token_type == TOKEN_NUMBER) { | ||||
|         eprintf("  number: %d\n", token_data); | ||||
|         fprintf(stderr, "  number: %d\n", token_data); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void expect_token(int expected_type) { | ||||
|     next_token(); | ||||
|     if (token_type != expected_type) { | ||||
|         eprintf("unexpected token: %d, should be %d\n", token_type, expected_type); | ||||
|         fprintf(stderr, "unexpected token: %d, should be %d\n", token_type, expected_type); | ||||
|         exit(1); | ||||
|     } | ||||
| } | ||||
|  | @ -890,20 +907,20 @@ int lookup(int id) { | |||
|     const char* name = id_table + id_lut[id]; | ||||
|     if (global_marker[id]) { | ||||
|         if (global_marker[id] == MARKER_FUNCTION) { | ||||
|             eprintf("function name must not appear outside function call: %s\n", name); | ||||
|             fprintf(stderr, "function name must not appear outside function call: %s\n", name); | ||||
|             exit(1); | ||||
|         } | ||||
|         int rd = next_reg(TYPE_VOID_PTR); | ||||
|         _asm_i("la", rd, name, " # id: ", id); | ||||
|         return materialize_address(rd, global_type[id], global_marker[id]); | ||||
|     } | ||||
|     eprintf("unresolved identifier: %s\n", name); | ||||
|     fprintf(stderr, "unresolved identifier: %s\n", name); | ||||
|     exit(1); | ||||
| } | ||||
| 
 | ||||
| int asm_r_arith(const char* op, int rs1) { | ||||
|     if (reg_type[rs1] & TYPE_PTR_MASK) { | ||||
|         eprintf("pointer cannot be arithmetically operated by %s\n", op); | ||||
|         fprintf(stderr, "pointer cannot be arithmetically operated by %s\n", op); | ||||
|         exit(1); | ||||
|     } | ||||
|     return asm_r(TYPE_INT, op, rs1); | ||||
|  | @ -911,7 +928,7 @@ int asm_r_arith(const char* op, int rs1) { | |||
| 
 | ||||
| int asm_rr_arith(const char* op, int rs1, int rs2) { | ||||
|     if (reg_type[rs1] & TYPE_PTR_MASK || reg_type[rs2] & TYPE_PTR_MASK) { | ||||
|         eprintf("pointer cannot be arithmetically operated by %s\n", op); | ||||
|         fprintf(stderr, "pointer cannot be arithmetically operated by %s\n", op); | ||||
|         exit(1); | ||||
|     } | ||||
|     return asm_rr(TYPE_INT, op, rs1, rs2); | ||||
|  | @ -951,7 +968,7 @@ int cont_label_stack_size; | |||
| 
 | ||||
| void asm_break() { | ||||
|     if (break_label_stack_size == 0) { | ||||
|         eprintf("break without loop\n"); | ||||
|         fprintf(stderr, "break without loop\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|     asm_j(break_label_stack[break_label_stack_size - 1]); | ||||
|  | @ -959,7 +976,7 @@ void asm_break() { | |||
| 
 | ||||
| void asm_continue() { | ||||
|     if (cont_label_stack_size == 0) { | ||||
|         eprintf("continue without loop\n"); | ||||
|         fprintf(stderr, "continue without loop\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|     asm_j(cont_label_stack[cont_label_stack_size - 1]); | ||||
|  | @ -1004,7 +1021,7 @@ int asm_add(int lhs, int rhs) { | |||
|         } | ||||
|         int ptr_type = reg_type[ptr]; | ||||
|         if (ptr_type == TYPE_VOID_PTR) { | ||||
|             eprintf("void pointer cannot be arithmetically operated\n"); | ||||
|             fprintf(stderr, "void pointer cannot be arithmetically operated\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         int offset = next_reg(TYPE_INT); | ||||
|  | @ -1012,7 +1029,7 @@ int asm_add(int lhs, int rhs) { | |||
|         return asm_rr(ptr_type, "add", ptr, offset); | ||||
|     } | ||||
|     if (type1 && type2) { | ||||
|         eprintf("operands of addition cannot be both pointers\n"); | ||||
|         fprintf(stderr, "operands of addition cannot be both pointers\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|     return asm_rr(TYPE_INT, "add", lhs, rhs); | ||||
|  | @ -1025,11 +1042,11 @@ int asm_sub(int lhs, int rhs) { | |||
|     int type2 = rhs_type & TYPE_PTR_MASK; | ||||
|     if (type1 && type2) { | ||||
|         if (lhs_type != rhs_type) { | ||||
|             eprintf("pointer type mismatch\n"); | ||||
|             fprintf(stderr, "pointer type mismatch\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         if (lhs_type == TYPE_VOID_PTR) { | ||||
|             eprintf("void pointer cannot be arithmetically operated\n"); | ||||
|             fprintf(stderr, "void pointer cannot be arithmetically operated\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         int diff = asm_rr(TYPE_INT, "sub", lhs, rhs); | ||||
|  | @ -1072,7 +1089,7 @@ int parse_assign_expr(); | |||
| int parse_function_call(int id) { | ||||
|     const char* name = id_table + id_lut[id]; | ||||
|     if (global_marker[id] != MARKER_FUNCTION) { | ||||
|         eprintf("not a function name: %s\n", name); | ||||
|         fprintf(stderr, "not a function name: %s\n", name); | ||||
|         exit(1); | ||||
|     } | ||||
|     int arg = 0; | ||||
|  | @ -1084,7 +1101,7 @@ int parse_function_call(int id) { | |||
|         } | ||||
|         unget_token(); | ||||
|         if (arg >= 8) { | ||||
|             eprintf("too many arguments\n"); | ||||
|             fprintf(stderr, "too many arguments\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         args[arg++] = parse_assign_expr(); | ||||
|  | @ -1094,7 +1111,7 @@ int parse_function_call(int id) { | |||
|         } else if (token_type == TOKEN_PAREN_RIGHT) { | ||||
|             break; | ||||
|         } else { | ||||
|             eprintf("expecting ',' or ')'\n"); | ||||
|             fprintf(stderr, "expecting ',' or ')'\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|     } | ||||
|  | @ -1143,7 +1160,7 @@ int parse_primary_expr() { | |||
|         expect_token(TOKEN_PAREN_RIGHT); | ||||
|         return reg; | ||||
|     } else { | ||||
|         eprintf("unexpected token in primary expression: %d\n", token_type); | ||||
|         fprintf(stderr, "unexpected token in primary expression: %d\n", token_type); | ||||
|         exit(1); | ||||
|     } | ||||
| } | ||||
|  | @ -1182,7 +1199,7 @@ int parse_prefix_expr() { | |||
|         int reg = parse_postfix_expr(); | ||||
|         int type = reg_type[reg]; | ||||
|         if (type & TYPE_PTR_MASK) { | ||||
|             eprintf("cannot take address of a pointer\n"); | ||||
|             fprintf(stderr, "cannot take address of a pointer\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         return addressof(reg); | ||||
|  | @ -1190,11 +1207,11 @@ int parse_prefix_expr() { | |||
|         int reg = parse_postfix_expr(); | ||||
|         int type = reg_type[reg]; | ||||
|         if (!(type & TYPE_PTR_MASK)) { | ||||
|             eprintf("cannot dereference a non-pointer\n"); | ||||
|             fprintf(stderr, "cannot dereference a non-pointer\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         if (type == TYPE_VOID_PTR) { | ||||
|             eprintf("cannot dereference void pointer\n"); | ||||
|             fprintf(stderr, "cannot dereference void pointer\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         return dereference(reg); | ||||
|  | @ -1443,7 +1460,7 @@ int parse_conditional_expr() { | |||
|         asm_label(label1); | ||||
|         int rhs = parse_conditional_expr(); | ||||
|         if (reg_type[lhs] != reg_type[rhs]) { | ||||
|             eprintf("type mismatch in conditional expression\n"); | ||||
|             fprintf(stderr, "type mismatch in conditional expression\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         asm_mv(result, rhs); | ||||
|  | @ -1535,7 +1552,7 @@ int parse_expr() { | |||
| 
 | ||||
| void parse_local_variable(int type) { | ||||
|     if (type == TYPE_VOID) { | ||||
|         eprintf("variable cannot be of void type\n"); | ||||
|         fprintf(stderr, "variable cannot be of void type\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|     expect_token(TOKEN_ID); | ||||
|  | @ -1543,7 +1560,7 @@ void parse_local_variable(int type) { | |||
|     next_token(); | ||||
|     if (token_type == TOKEN_BRACKET_LEFT) { | ||||
|         if (type & TYPE_PTR_MASK) { | ||||
|             eprintf("array of pointers is not supported\n"); | ||||
|             fprintf(stderr, "array of pointers is not supported\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         expect_token(TOKEN_NUMBER); | ||||
|  | @ -1561,7 +1578,7 @@ void parse_local_variable(int type) { | |||
|     expect_token(TOKEN_ASSIGN); | ||||
|     int reg = parse_expr(); | ||||
|     if (type != reg_type[reg]) { | ||||
|         eprintf("type mismatch in assignment\n"); | ||||
|         fprintf(stderr, "type mismatch in assignment\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|     store_into_local(reg, slot); | ||||
|  | @ -1709,17 +1726,9 @@ void parse_function(const char* name) { | |||
|             expect_token(TOKEN_PAREN_RIGHT); | ||||
|             break; | ||||
|         } | ||||
|         if (token_type == TOKEN_VOID) { | ||||
|             if (arg != 0) { | ||||
|                 eprintf("void should be the only argument\n"); | ||||
|                 exit(1); | ||||
|             } | ||||
|             expect_token(TOKEN_PAREN_RIGHT); | ||||
|             break; | ||||
|         } | ||||
|         int arg_type = parse_type(); | ||||
|         if (arg_type < 0 || arg_type == TYPE_VOID) { | ||||
|             eprintf("expecting a non-void argument type: %d\n", arg_type); | ||||
|             fprintf(stderr, "expecting a non-void argument type: %d\n", arg_type); | ||||
|             exit(1); | ||||
|         } | ||||
|         expect_token(TOKEN_ID); | ||||
|  | @ -1729,13 +1738,13 @@ void parse_function(const char* name) { | |||
|             expect_token(TOKEN_BRACKET_RIGHT); | ||||
|             next_token(); | ||||
|             if (arg_type & TYPE_PTR_MASK) { | ||||
|                 eprintf("array of pointers is not supported\n"); | ||||
|                 fprintf(stderr, "array of pointers is not supported\n"); | ||||
|                 exit(1); | ||||
|             } | ||||
|             arg_type |= TYPE_PTR_MASK; | ||||
|         } | ||||
|         if (arg >= 8) { | ||||
|             eprintf("too many arguments\n"); | ||||
|             fprintf(stderr, "too many arguments\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         args[arg++] = declare_local(token_data, arg_type); | ||||
|  | @ -1744,7 +1753,7 @@ void parse_function(const char* name) { | |||
|         } else if (token_type == TOKEN_PAREN_RIGHT) { | ||||
|             break; | ||||
|         } else { | ||||
|             eprintf("expecting ',' or ')'\n"); | ||||
|             fprintf(stderr, "expecting ',' or ')'\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|     } | ||||
|  | @ -1808,10 +1817,6 @@ void parse_function(const char* name) { | |||
| } | ||||
| 
 | ||||
| void parse_global_variable(int id, const char* name, int type) { | ||||
|     if (type == TYPE_VOID) { | ||||
|         eprintf("variable cannot be of void type\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|     printf(".data\n"); | ||||
|     printf(".globl %s\n", name); | ||||
|     printf(".align 5\n"); | ||||
|  | @ -1821,7 +1826,7 @@ void parse_global_variable(int id, const char* name, int type) { | |||
|         printf("  .dword %d\n", token_data); | ||||
|     } else if (token_type == TOKEN_BRACKET_LEFT) { | ||||
|         if (type & TYPE_PTR_MASK) { | ||||
|             eprintf("array of pointers is not supported\n"); | ||||
|             fprintf(stderr, "array of pointers is not supported\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         expect_token(TOKEN_NUMBER); | ||||
|  | @ -1834,17 +1839,21 @@ void parse_global_variable(int id, const char* name, int type) { | |||
|         printf("  .zero %d\n", 8); | ||||
|         unget_token(); | ||||
|     } | ||||
|     expect_token(TOKEN_SEMICOLON); | ||||
| } | ||||
| 
 | ||||
| void parse_global_declaration() { | ||||
|     int external = 0; | ||||
|     if (token_type == TOKEN_EXTERN) { | ||||
|         external = 1; | ||||
|         next_token(); | ||||
|     } | ||||
|     int is_const_int = 1; | ||||
|     if (token_type != TOKEN_CONST) { | ||||
|         is_const_int = 0; | ||||
|     } | ||||
|     int type = parse_type(); | ||||
|     if (type < 0) { | ||||
|         eprintf("expecting type for global declaration\n"); | ||||
|         fprintf(stderr, "expecting type for global declaration\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|     if (type != TYPE_INT) { | ||||
|  | @ -1854,7 +1863,7 @@ void parse_global_declaration() { | |||
|     int id = token_data; | ||||
|     char* name = id_table + id_lut[id]; | ||||
|     next_token(); | ||||
|     if (is_const_int && token_type == TOKEN_ASSIGN) { | ||||
|     if (!external && is_const_int && token_type == TOKEN_ASSIGN) { | ||||
|         expect_token(TOKEN_NUMBER); | ||||
|         const_table[id] = token_data; | ||||
|         is_const[id] = 1; | ||||
|  | @ -1863,8 +1872,17 @@ void parse_global_declaration() { | |||
|         declare_global(id, MARKER_FUNCTION, type); | ||||
|         parse_function(name); | ||||
|     } else { | ||||
|         if (type == TYPE_VOID) { | ||||
|             fprintf(stderr, "variable cannot be of void type\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|         declare_global(id, MARKER_SCALAR, type); | ||||
|         parse_global_variable(id, name, type); | ||||
|         if (external) { | ||||
|             unget_token(); | ||||
|         } else { | ||||
|             parse_global_variable(id, name, type); | ||||
|         } | ||||
|         expect_token(TOKEN_SEMICOLON); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue