diff --git a/mk/arm.mk b/mk/arm.mk index a768dc7d..abd1439a 100644 --- a/mk/arm.mk +++ b/mk/arm.mk @@ -14,6 +14,7 @@ export ARM_EXEC arm-specific-defs = \ $(Q)$(PRINTF) \ "/* target: ARM */\n$\ + \#pragma once\n$\ \#define ARCH_PREDEFINED \"__arm__\" /* defined by GNU C and RealView */\n$\ \#define ELF_MACHINE 0x28 /* up to ARMv7/Aarch32 */\n$\ \#define ELF_FLAGS 0x5000200\n$\ diff --git a/mk/riscv.mk b/mk/riscv.mk index f3ae87bd..ee8f25fd 100644 --- a/mk/riscv.mk +++ b/mk/riscv.mk @@ -10,6 +10,7 @@ export RISCV_EXEC riscv-specific-defs = \ $(Q)$(PRINTF) \ "/* target: RISCV */\n$\ + \#pragma once\n$\ \#define ARCH_PREDEFINED \"__riscv\" /* Older versions of the GCC toolchain defined __riscv__ */\n$\ \#define ELF_MACHINE 0xf3\n$\ \#define ELF_FLAGS 0\n$\ diff --git a/src/arm-codegen.c b/src/arm-codegen.c index c6c020ee..357311dd 100644 --- a/src/arm-codegen.c +++ b/src/arm-codegen.c @@ -8,6 +8,8 @@ /* Translate IR to target machine code */ #include "arm.c" +#include "defs.h" +#include "globals.c" void update_elf_offset(ph2_ir_t *ph2_ir) { diff --git a/src/arm.c b/src/arm.c index 0562eae1..405d2792 100644 --- a/src/arm.c +++ b/src/arm.c @@ -26,6 +26,8 @@ * the current instruction. */ +#include "defs.h" + /* opcode */ typedef enum { arm_and = 0, diff --git a/src/defs.h b/src/defs.h index 189a10c7..7c2ec9ca 100644 --- a/src/defs.h +++ b/src/defs.h @@ -5,8 +5,8 @@ * file "LICENSE" for information on usage and redistribution of this file. */ -#ifndef SHECC_DEFS_H -#define SHECC_DEFS_H +#pragma once +#include /* definitions */ @@ -40,6 +40,7 @@ #define MAX_NESTING 128 #define MAX_OPERAND_STACK_SIZE 32 #define MAX_ANALYSIS_STACK_SIZE 800 +#define MAX_INCLUSIONS 16 /* Default capacities for common data structures */ /* Default arena size is initialized with 256 KiB */ @@ -92,6 +93,89 @@ typedef struct { hashmap_node_t **buckets; } hashmap_t; +/* lexer tokens */ +typedef enum { + T_start, /* FIXME: it was intended to start the state machine. */ + T_numeric, + T_identifier, + T_comma, /* , */ + T_string, /* null-terminated string */ + T_char, + T_open_bracket, /* ( */ + T_close_bracket, /* ) */ + T_open_curly, /* { */ + T_close_curly, /* } */ + T_open_square, /* [ */ + T_close_square, /* ] */ + T_asterisk, /* '*' */ + T_divide, /* / */ + T_mod, /* % */ + T_bit_or, /* | */ + T_bit_xor, /* ^ */ + T_bit_not, /* ~ */ + T_log_and, /* && */ + T_log_or, /* || */ + T_log_not, /* ! */ + T_lt, /* < */ + T_gt, /* > */ + T_le, /* <= */ + T_ge, /* >= */ + T_lshift, /* << */ + T_rshift, /* >> */ + T_dot, /* . */ + T_arrow, /* -> */ + T_plus, /* + */ + T_minus, /* - */ + T_minuseq, /* -= */ + T_pluseq, /* += */ + T_asteriskeq, /* *= */ + T_divideeq, /* /= */ + T_modeq, /* %= */ + T_lshifteq, /* <<= */ + T_rshifteq, /* >>= */ + T_xoreq, /* ^= */ + T_oreq, /* |= */ + T_andeq, /* &= */ + T_eq, /* == */ + T_noteq, /* != */ + T_assign, /* = */ + T_increment, /* ++ */ + T_decrement, /* -- */ + T_question, /* ? */ + T_colon, /* : */ + T_semicolon, /* ; */ + T_eof, /* end-of-file (EOF) */ + T_ampersand, /* & */ + T_return, + T_if, + T_else, + T_while, + T_for, + T_do, + T_typedef, + T_enum, + T_struct, + T_sizeof, + T_elipsis, /* ... */ + T_switch, + T_case, + T_break, + T_default, + T_continue, + /* C pre-processor directives */ + T_cppd_include, + T_cppd_define, + T_cppd_undef, + T_cppd_error, + T_cppd_if, + T_cppd_elif, + T_cppd_else, + T_cppd_endif, + T_cppd_ifdef, + T_cppd_ifndef, + T_cppd_pragma +} token_t; + /* builtin types */ typedef enum { TYPE_void = 0, @@ -467,5 +551,3 @@ typedef struct { var_t *var; int polluted; } regfile_t; - -#endif diff --git a/src/globals.c b/src/globals.c index b8e8d166..a0c09933 100644 --- a/src/globals.c +++ b/src/globals.c @@ -5,9 +5,25 @@ * file "LICENSE" for information on usage and redistribution of this file. */ +#pragma once #include #include +#include "defs.h" + +/* Lexer */ +char token_str[MAX_TOKEN_LEN]; +token_t next_token; +char next_char; +bool skip_newline = true; + +bool preproc_match; + +/* Point to the first character after where the macro has been called. It is + * needed when returning from the macro body. + */ +int macro_return_idx; + /* Global objects */ block_list_t BLOCKS; @@ -58,6 +74,8 @@ int constants_idx = 0; source_t *SOURCE; +hashmap_t *INCLUSION_MAP; + /* ELF sections */ char *elf_code; @@ -968,6 +986,7 @@ void global_init() PH2_IR_FLATTEN = malloc(MAX_IR_INSTR * sizeof(ph2_ir_t *)); LABEL_LUT = malloc(MAX_LABEL * sizeof(label_lut_t)); SOURCE = create_source(MAX_SOURCE); + INCLUSION_MAP = hashmap_create(MAX_INCLUSIONS); ALIASES = malloc(MAX_ALIASES * sizeof(alias_t)); CONSTANTS = malloc(MAX_CONSTANTS * sizeof(constant_t)); @@ -1000,6 +1019,7 @@ void global_release() free(PH2_IR_FLATTEN); free(LABEL_LUT); source_release(SOURCE); + hashmap_free(INCLUSION_MAP); free(ALIASES); free(CONSTANTS); diff --git a/src/lexer.c b/src/lexer.c index 7b3cadba..8064d1e8 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -7,99 +7,8 @@ #include -/* lexer tokens */ -typedef enum { - T_start, /* FIXME: it was intended to start the state machine. */ - T_numeric, - T_identifier, - T_comma, /* , */ - T_string, /* null-terminated string */ - T_char, - T_open_bracket, /* ( */ - T_close_bracket, /* ) */ - T_open_curly, /* { */ - T_close_curly, /* } */ - T_open_square, /* [ */ - T_close_square, /* ] */ - T_asterisk, /* '*' */ - T_divide, /* / */ - T_mod, /* % */ - T_bit_or, /* | */ - T_bit_xor, /* ^ */ - T_bit_not, /* ~ */ - T_log_and, /* && */ - T_log_or, /* || */ - T_log_not, /* ! */ - T_lt, /* < */ - T_gt, /* > */ - T_le, /* <= */ - T_ge, /* >= */ - T_lshift, /* << */ - T_rshift, /* >> */ - T_dot, /* . */ - T_arrow, /* -> */ - T_plus, /* + */ - T_minus, /* - */ - T_minuseq, /* -= */ - T_pluseq, /* += */ - T_asteriskeq, /* *= */ - T_divideeq, /* /= */ - T_modeq, /* %= */ - T_lshifteq, /* <<= */ - T_rshifteq, /* >>= */ - T_xoreq, /* ^= */ - T_oreq, /* |= */ - T_andeq, /* &= */ - T_eq, /* == */ - T_noteq, /* != */ - T_assign, /* = */ - T_increment, /* ++ */ - T_decrement, /* -- */ - T_question, /* ? */ - T_colon, /* : */ - T_semicolon, /* ; */ - T_eof, /* end-of-file (EOF) */ - T_ampersand, /* & */ - T_return, - T_if, - T_else, - T_while, - T_for, - T_do, - T_typedef, - T_enum, - T_struct, - T_sizeof, - T_elipsis, /* ... */ - T_switch, - T_case, - T_break, - T_default, - T_continue, - /* C pre-processor directives */ - T_cppd_include, - T_cppd_define, - T_cppd_undef, - T_cppd_error, - T_cppd_if, - T_cppd_elif, - T_cppd_else, - T_cppd_endif, - T_cppd_ifdef, - T_cppd_ifndef -} token_t; - -char token_str[MAX_TOKEN_LEN]; -token_t next_token; -char next_char; -bool skip_newline = true; - -bool preproc_match; - -/* Point to the first character after where the macro has been called. It is - * needed when returning from the macro body. - */ -int macro_return_idx; +#include "defs.h" +#include "globals.c" bool is_whitespace(char c) { @@ -223,6 +132,8 @@ token_t lex_token_internal(bool aliasing) return T_cppd_else; if (!strcmp(token_str, "#endif")) return T_cppd_endif; + if (!strcmp(token_str, "#pragma")) + return T_cppd_pragma; error("Unknown directive"); } diff --git a/src/parser.c b/src/parser.c index cfa0100c..d70913e7 100644 --- a/src/parser.c +++ b/src/parser.c @@ -6,8 +6,13 @@ */ #include +#include #include +#include "../config" +#include "defs.h" +#include "globals.c" + /* C language syntactic analyzer */ int global_var_idx = 0; int global_label_idx = 0; @@ -513,6 +518,10 @@ bool read_preproc_directive() cppd_control_flow_skip_lines(); return true; } + if (lex_accept_internal(T_cppd_pragma, false)) { + lex_expect(T_identifier); + return true; + } return false; } @@ -3399,6 +3408,10 @@ void load_source_file(char *file) for (;;) { if (!fgets(buffer, MAX_LINE_LEN, f)) { + break; + } + if (!strncmp(buffer, "#pragma once", 12) && + hashmap_contains(INCLUSION_MAP, file)) { fclose(f); return; } @@ -3419,6 +3432,8 @@ void load_source_file(char *file) SOURCE->size += strlen(buffer); } } + + hashmap_put(INCLUSION_MAP, file, NULL); fclose(f); } diff --git a/src/peephole.c b/src/peephole.c index f6e10de6..4e2426ce 100644 --- a/src/peephole.c +++ b/src/peephole.c @@ -5,6 +5,11 @@ * file "LICENSE" for information on usage and redistribution of this file. */ +#include + +#include "defs.h" +#include "globals.c" + bool is_fusible_insn(ph2_ir_t *ph2_ir) { switch (ph2_ir->op) { diff --git a/src/reg-alloc.c b/src/reg-alloc.c index 5c7d80de..ebef1152 100644 --- a/src/reg-alloc.c +++ b/src/reg-alloc.c @@ -12,6 +12,11 @@ * dead variable and does NOT wrtie it back to the stack. */ +#include + +#include "defs.h" +#include "globals.c" + /* Aligns size to nearest multiple of 4, this meets * ARMv7's alignment requirement. * diff --git a/src/riscv-codegen.c b/src/riscv-codegen.c index 25752e89..fbb2c226 100644 --- a/src/riscv-codegen.c +++ b/src/riscv-codegen.c @@ -7,6 +7,8 @@ /* Translate IR to target machine code */ +#include "defs.h" +#include "globals.c" #include "riscv.c" void update_elf_offset(ph2_ir_t *ph2_ir) diff --git a/src/ssa.c b/src/ssa.c index 0eccec40..25792c53 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -5,6 +5,12 @@ * file "LICENSE" for information on usage and redistribution of this file. */ +#include +#include + +#include "defs.h" +#include "globals.c" + /* cfront does not accept structure as an argument, pass pointer */ void bb_forward_traversal(bb_traversal_args_t *args) {