#undef RELEASE_DATE
#undef VERSION
#define VERSION_MAJOR "0"
-#define VERSION_MINOR "65"
-#define RELEASE_DATE "8 November 2004"
+#define VERSION_MINOR "70"
+#define RELEASE_DATE "23 October 2007"
#define VERSION VERSION_MAJOR "." VERSION_MINOR
#include <stdarg.h>
#define MAX_CWD_SIZE 4096
#define MAX_ALLOCATION_PASSES 100
+/* NOTE: Before you even start thinking to touch anything
+ * in this code, set DEBUG_ROMCC_WARNINGS to 1 to get an
+ * insight on the original author's thoughts. We introduced
+ * this switch as romcc was about the only thing producing
+ * massive warnings in our code..
+ */
+#define DEBUG_ROMCC_WARNINGS 0
+
#define DEBUG_CONSISTENCY 1
#define DEBUG_SDP_BLOCKS 0
#define DEBUG_TRIPLE_COLOR 0
#define DEBUG_EXPLICIT_CLOSURES 0
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME give clear error messages about unused variables"
#warning "FIXME properly handle multi dimensional arrays"
#warning "FIXME handle multiple register sizes"
+#endif
/* Control flow graph of a loop without goto.
*
}
/* Types on the destination platform */
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME this assumes 32bit x86 is the destination"
+#endif
typedef int8_t schar_t;
typedef uint8_t uchar_t;
typedef int8_t char_t;
struct file_state *prev;
const char *basename;
char *dirname;
- char *buf;
+ const char *buf;
off_t size;
const char *pos;
int line;
int report_line;
const char *report_name;
const char *report_dir;
+ int macro : 1;
+ int trigraphs : 1;
+ int join_lines : 1;
};
struct hash_entry;
struct token {
int tok;
struct hash_entry *ident;
+ const char *pos;
int str_len;
union {
ulong_t integer;
[OP_ADDRCONST ] = OP( 0, 0, 1, 0, PURE | DEF, "addrconst"),
[OP_UNKNOWNVAL ] = OP( 0, 0, 0, 0, PURE | DEF, "unknown"),
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME is it correct for OP_WRITE to be a def? I currently use it as one..."
+#endif
[OP_WRITE ] = OP( 0, 1, 1, 0, PURE | DEF | BLOCK, "write"),
[OP_READ ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "read"),
[OP_COPY ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "copy"),
};
struct macro {
struct hash_entry *ident;
- char *buf;
+ const char *buf;
int buf_len;
- int buf_off;
struct macro_arg *args;
int argc;
};
struct block *first_block, *last_block;
int last_vertex;
};
-#define MAX_CPP_IF_DEPTH 63
+#define MAX_PP_IF_DEPTH 63
struct compile_state {
struct compiler_state *compiler;
struct arch_state *arch;
struct hash_entry *i_noinline;
struct hash_entry *i_always_inline;
int scope_depth;
- unsigned char if_bytes[(MAX_CPP_IF_DEPTH + CHAR_BIT -1)/CHAR_BIT];
+ unsigned char if_bytes[(MAX_PP_IF_DEPTH + CHAR_BIT -1)/CHAR_BIT];
int if_depth;
int eat_depth, eat_targ;
- int macro_line;
struct file_state *macro_file;
struct triple *functions;
struct triple *main_function;
struct compile_state *state, struct triple *ins);
static struct triple *flatten(
struct compile_state *state, struct triple *first, struct triple *ptr);
-
+static void print_dominators(struct compile_state *state,
+ FILE *fp, struct basic_blocks *bb);
+static void print_dominance_frontiers(struct compile_state *state,
+ FILE *fp, struct basic_blocks *bb);
#define COMPILER_SIMPLIFY_LOGICAL 0x00004000
#define COMPILER_SIMPLIFY_BITFIELD 0x00008000
-#define COMPILER_CPP_ONLY 0x80000000
+#define COMPILER_TRIGRAPHS 0x40000000
+#define COMPILER_PP_ONLY 0x80000000
#define COMPILER_DEFAULT_FLAGS ( \
+ COMPILER_TRIGRAPHS | \
COMPILER_ELIMINATE_INEFECTUAL_CODE | \
COMPILER_INLINE_DEFAULTON | \
COMPILER_SIMPLIFY_OP | \
}
static const struct compiler_flag romcc_flags[] = {
- { "cpp-only", COMPILER_CPP_ONLY },
+ { "trigraphs", COMPILER_TRIGRAPHS },
+ { "pp-only", COMPILER_PP_ONLY },
{ "eliminate-inefectual-code", COMPILER_ELIMINATE_INEFECTUAL_CODE },
{ "simplify", COMPILER_SIMPLIFY },
{ "scc-transform", COMPILER_SCC_TRANSFORM },
static const struct compiler_flag romcc_opt_flags[] = {
{ "-O", COMPILER_SIMPLIFY },
{ "-O2", COMPILER_SIMPLIFY | COMPILER_SCC_TRANSFORM },
- { "-E", COMPILER_CPP_ONLY },
+ { "-E", COMPILER_PP_ONLY },
{ 0, 0, },
};
static const struct compiler_flag romcc_debug_flags[] = {
valid_op(state, ptr->op);
}
+#if DEBUG_ROMCC_WARNING
static void valid_param_count(struct compile_state *state, struct triple *ins)
{
int lhs, rhs, misc, targ;
internal_error(state, ins, "Bad targ count");
}
}
-
-static void process_trigraphs(struct compile_state *state)
-{
- char *src, *dest, *end;
- struct file_state *file;
- file = state->file;
- src = dest = file->buf;
- end = file->buf + file->size;
- while((end - src) >= 3) {
- if ((src[0] == '?') && (src[1] == '?')) {
- int c = -1;
- switch(src[2]) {
- case '=': c = '#'; break;
- case '/': c = '\\'; break;
- case '\'': c = '^'; break;
- case '(': c = '['; break;
- case ')': c = ']'; break;
- case '!': c = '!'; break;
- case '<': c = '{'; break;
- case '>': c = '}'; break;
- case '-': c = '~'; break;
- }
- if (c != -1) {
- *dest++ = c;
- src += 3;
- }
- else {
- *dest++ = *src++;
- }
- }
- else {
- *dest++ = *src++;
- }
- }
- while(src != end) {
- *dest++ = *src++;
- }
- file->size = dest - file->buf;
-}
-
-static void splice_lines(struct compile_state *state)
-{
- char *src, *dest, *end;
- struct file_state *file;
- file = state->file;
- src = dest = file->buf;
- end = file->buf + file->size;
- while((end - src) >= 2) {
- if ((src[0] == '\\') && (src[1] == '\n')) {
- src += 2;
- }
- else {
- *dest++ = *src++;
- }
- }
- while(src != end) {
- *dest++ = *src++;
- }
- file->size = dest - file->buf;
-}
+#endif
static struct type void_type;
static struct type unknown_type;
/* Is this triple a return instruction? */
return triple_is_branch_type(state, ins, RETBRANCH);
}
-
+
+#if DEBUG_ROMCC_WARNING
static int triple_is_simple_ubranch(struct compile_state *state, struct triple *ins)
{
/* Is this triple an unconditional branch and not a call or a
* return? */
return triple_is_branch_type(state, ins, UBRANCH);
}
+#endif
static int triple_is_end(struct compile_state *state, struct triple *ins)
{
struct triple **param;
int size, i;
verify_use(state, user, used);
+
+#if DEBUG_ROMCC_WARNINGS
#warning "AUDIT ME ->rhs"
+#endif
size = user->rhs;
param = &RHS(user, 0);
for(i = 0; i < size; i++) {
static void print_triples(struct compile_state *state);
static void print_blocks(struct compile_state *state, const char *func, FILE *fp);
-#define TOK_UNKNOWN 0
-#define TOK_SPACE 1
-#define TOK_SEMI 2
-#define TOK_LBRACE 3
-#define TOK_RBRACE 4
-#define TOK_COMMA 5
-#define TOK_EQ 6
-#define TOK_COLON 7
-#define TOK_LBRACKET 8
-#define TOK_RBRACKET 9
-#define TOK_LPAREN 10
-#define TOK_RPAREN 11
-#define TOK_STAR 12
-#define TOK_DOTS 13
-#define TOK_MORE 14
-#define TOK_LESS 15
-#define TOK_TIMESEQ 16
-#define TOK_DIVEQ 17
-#define TOK_MODEQ 18
-#define TOK_PLUSEQ 19
-#define TOK_MINUSEQ 20
-#define TOK_SLEQ 21
-#define TOK_SREQ 22
-#define TOK_ANDEQ 23
-#define TOK_XOREQ 24
-#define TOK_OREQ 25
-#define TOK_EQEQ 26
-#define TOK_NOTEQ 27
-#define TOK_QUEST 28
-#define TOK_LOGOR 29
-#define TOK_LOGAND 30
-#define TOK_OR 31
-#define TOK_AND 32
-#define TOK_XOR 33
-#define TOK_LESSEQ 34
-#define TOK_MOREEQ 35
-#define TOK_SL 36
-#define TOK_SR 37
-#define TOK_PLUS 38
-#define TOK_MINUS 39
-#define TOK_DIV 40
-#define TOK_MOD 41
-#define TOK_PLUSPLUS 42
-#define TOK_MINUSMINUS 43
-#define TOK_BANG 44
-#define TOK_ARROW 45
-#define TOK_DOT 46
-#define TOK_TILDE 47
-#define TOK_LIT_STRING 48
-#define TOK_LIT_CHAR 49
-#define TOK_LIT_INT 50
-#define TOK_LIT_FLOAT 51
-#define TOK_MACRO 52
-#define TOK_CONCATENATE 53
-
-#define TOK_IDENT 54
-#define TOK_STRUCT_NAME 55
-#define TOK_ENUM_CONST 56
-#define TOK_TYPE_NAME 57
-
-#define TOK_AUTO 58
-#define TOK_BREAK 59
-#define TOK_CASE 60
-#define TOK_CHAR 61
-#define TOK_CONST 62
-#define TOK_CONTINUE 63
-#define TOK_DEFAULT 64
-#define TOK_DO 65
-#define TOK_DOUBLE 66
-#define TOK_ELSE 67
-#define TOK_ENUM 68
-#define TOK_EXTERN 69
-#define TOK_FLOAT 70
-#define TOK_FOR 71
-#define TOK_GOTO 72
-#define TOK_IF 73
-#define TOK_INLINE 74
-#define TOK_INT 75
-#define TOK_LONG 76
-#define TOK_REGISTER 77
-#define TOK_RESTRICT 78
-#define TOK_RETURN 79
-#define TOK_SHORT 80
-#define TOK_SIGNED 81
-#define TOK_SIZEOF 82
-#define TOK_STATIC 83
-#define TOK_STRUCT 84
-#define TOK_SWITCH 85
-#define TOK_TYPEDEF 86
-#define TOK_UNION 87
-#define TOK_UNSIGNED 88
-#define TOK_VOID 89
-#define TOK_VOLATILE 90
-#define TOK_WHILE 91
-#define TOK_ASM 92
-#define TOK_ATTRIBUTE 93
-#define TOK_ALIGNOF 94
+#define TOK_UNKNOWN 0
+#define TOK_SPACE 1
+#define TOK_SEMI 2
+#define TOK_LBRACE 3
+#define TOK_RBRACE 4
+#define TOK_COMMA 5
+#define TOK_EQ 6
+#define TOK_COLON 7
+#define TOK_LBRACKET 8
+#define TOK_RBRACKET 9
+#define TOK_LPAREN 10
+#define TOK_RPAREN 11
+#define TOK_STAR 12
+#define TOK_DOTS 13
+#define TOK_MORE 14
+#define TOK_LESS 15
+#define TOK_TIMESEQ 16
+#define TOK_DIVEQ 17
+#define TOK_MODEQ 18
+#define TOK_PLUSEQ 19
+#define TOK_MINUSEQ 20
+#define TOK_SLEQ 21
+#define TOK_SREQ 22
+#define TOK_ANDEQ 23
+#define TOK_XOREQ 24
+#define TOK_OREQ 25
+#define TOK_EQEQ 26
+#define TOK_NOTEQ 27
+#define TOK_QUEST 28
+#define TOK_LOGOR 29
+#define TOK_LOGAND 30
+#define TOK_OR 31
+#define TOK_AND 32
+#define TOK_XOR 33
+#define TOK_LESSEQ 34
+#define TOK_MOREEQ 35
+#define TOK_SL 36
+#define TOK_SR 37
+#define TOK_PLUS 38
+#define TOK_MINUS 39
+#define TOK_DIV 40
+#define TOK_MOD 41
+#define TOK_PLUSPLUS 42
+#define TOK_MINUSMINUS 43
+#define TOK_BANG 44
+#define TOK_ARROW 45
+#define TOK_DOT 46
+#define TOK_TILDE 47
+#define TOK_LIT_STRING 48
+#define TOK_LIT_CHAR 49
+#define TOK_LIT_INT 50
+#define TOK_LIT_FLOAT 51
+#define TOK_MACRO 52
+#define TOK_CONCATENATE 53
+
+#define TOK_IDENT 54
+#define TOK_STRUCT_NAME 55
+#define TOK_ENUM_CONST 56
+#define TOK_TYPE_NAME 57
+
+#define TOK_AUTO 58
+#define TOK_BREAK 59
+#define TOK_CASE 60
+#define TOK_CHAR 61
+#define TOK_CONST 62
+#define TOK_CONTINUE 63
+#define TOK_DEFAULT 64
+#define TOK_DO 65
+#define TOK_DOUBLE 66
+#define TOK_ELSE 67
+#define TOK_ENUM 68
+#define TOK_EXTERN 69
+#define TOK_FLOAT 70
+#define TOK_FOR 71
+#define TOK_GOTO 72
+#define TOK_IF 73
+#define TOK_INLINE 74
+#define TOK_INT 75
+#define TOK_LONG 76
+#define TOK_REGISTER 77
+#define TOK_RESTRICT 78
+#define TOK_RETURN 79
+#define TOK_SHORT 80
+#define TOK_SIGNED 81
+#define TOK_SIZEOF 82
+#define TOK_STATIC 83
+#define TOK_STRUCT 84
+#define TOK_SWITCH 85
+#define TOK_TYPEDEF 86
+#define TOK_UNION 87
+#define TOK_UNSIGNED 88
+#define TOK_VOID 89
+#define TOK_VOLATILE 90
+#define TOK_WHILE 91
+#define TOK_ASM 92
+#define TOK_ATTRIBUTE 93
+#define TOK_ALIGNOF 94
#define TOK_FIRST_KEYWORD TOK_AUTO
#define TOK_LAST_KEYWORD TOK_ALIGNOF
-#define TOK_MDEFINE 100
-#define TOK_MDEFINED 101
-#define TOK_MUNDEF 102
-#define TOK_MINCLUDE 103
-#define TOK_MLINE 104
-#define TOK_MERROR 105
-#define TOK_MWARNING 106
-#define TOK_MPRAGMA 107
-#define TOK_MIFDEF 108
-#define TOK_MIFNDEF 109
-#define TOK_MELIF 110
-#define TOK_MENDIF 111
-
-#define TOK_FIRST_MACRO TOK_MDEFINE
-#define TOK_LAST_MACRO TOK_MENDIF
+#define TOK_MDEFINE 100
+#define TOK_MDEFINED 101
+#define TOK_MUNDEF 102
+#define TOK_MINCLUDE 103
+#define TOK_MLINE 104
+#define TOK_MERROR 105
+#define TOK_MWARNING 106
+#define TOK_MPRAGMA 107
+#define TOK_MIFDEF 108
+#define TOK_MIFNDEF 109
+#define TOK_MELIF 110
+#define TOK_MENDIF 111
+
+#define TOK_FIRST_MACRO TOK_MDEFINE
+#define TOK_LAST_MACRO TOK_MENDIF
-#define TOK_MIF 112
-#define TOK_MELSE 113
-#define TOK_MIDENT 114
+#define TOK_MIF 112
+#define TOK_MELSE 113
+#define TOK_MIDENT 114
-#define TOK_EOL 115
-#define TOK_EOF 116
+#define TOK_EOL 115
+#define TOK_EOF 116
static const char *tokens[] = {
[TOK_UNKNOWN ] = ":unknown:",
}
}
-static void define_macro(
- struct compile_state *state,
- struct hash_entry *ident,
- const char *value, int value_len, int value_off,
- struct macro_arg *args)
+static void do_define_macro(struct compile_state *state,
+ struct hash_entry *ident, const char *body,
+ int argc, struct macro_arg *args)
{
struct macro *macro;
struct macro_arg *arg;
+ size_t body_len;
+
+ /* Find the length of the body */
+ body_len = strlen(body);
macro = ident->sym_define;
if (macro != 0) {
- /* Explicitly allow identical redefinitions of the same macro */
- if ((macro->buf_len == value_len) &&
- (memcmp(macro->buf, value, value_len) == 0)) {
+ int identical_bodies, identical_args;
+ struct macro_arg *oarg;
+ /* Explicitly allow identical redfinitions of the same macro */
+ identical_bodies =
+ (macro->buf_len == body_len) &&
+ (memcmp(macro->buf, body, body_len) == 0);
+ identical_args = macro->argc == argc;
+ oarg = macro->args;
+ arg = args;
+ while(identical_args && arg) {
+ identical_args = oarg->ident == arg->ident;
+ arg = arg->next;
+ oarg = oarg->next;
+ }
+ if (identical_bodies && identical_args) {
+ xfree(body);
return;
}
error(state, 0, "macro %s already defined\n", ident->name);
}
#if 0
- fprintf(state->errout, "%s: `%*.*s'\n",
- ident->name,
- value_len - value_off,
- value_len - value_off,
- value + value_off);
+ fprintf(state->errout, "#define %s: `%*.*s'\n",
+ ident->name, body_len, body_len, body);
#endif
macro = xmalloc(sizeof(*macro), "macro");
- macro->ident = ident;
- macro->buf_len = value_len;
- macro->buf_off = value_off;
+ macro->ident = ident;
+ macro->buf = body;
+ macro->buf_len = body_len;
macro->args = args;
- macro->buf = xmalloc(macro->buf_len + 1, "macro buf");
-
- macro->argc = 0;
- for(arg = args; arg; arg = arg->next) {
- macro->argc += 1;
- }
-
- memcpy(macro->buf, value, macro->buf_len);
- macro->buf[macro->buf_len] = '\0';
+ macro->argc = argc;
ident->sym_define = macro;
}
+
+static void define_macro(
+ struct compile_state *state,
+ struct hash_entry *ident,
+ const char *body, int body_len,
+ int argc, struct macro_arg *args)
+{
+ char *buf;
+ buf = xmalloc(body_len + 1, "macro buf");
+ memcpy(buf, body, body_len);
+ buf[body_len] = '\0';
+ do_define_macro(state, ident, buf, argc, args);
+}
static void register_builtin_macro(struct compile_state *state,
const char *name, const char *value)
internal_error(state, 0, "Builtin macros with arguments not supported");
}
ident = lookup(state, name, strlen(name));
- define_macro(state, ident, value, strlen(value), 0, 0);
+ define_macro(state, ident, value, strlen(value), -1, 0);
}
static void register_builtin_macros(struct compile_state *state)
body++;
}
ident = lookup(state, name, name_len);
- define_macro(state, ident, body, strlen(body), 0, 0);
+ define_macro(state, ident, body, strlen(body), -1, 0);
}
for(macro = state->compiler->undefs; (name = *macro); macro++) {
ident = lookup(state, name, strlen(name));
return ret;
}
-static int eolp(int c)
-{
- int ret = 0;
- switch(c) {
- case '\n':
- ret = 1;
- break;
- }
- return ret;
-}
-
static int digitp(int c)
{
int ret = 0;
return c;
}
-static const char *after_digits(const char *ptr, const char *end)
+static const char *next_char(struct file_state *file, const char *pos, int index)
{
- while((ptr < end) && digitp(*ptr)) {
- ptr++;
+ const char *end = file->buf + file->size;
+ while(pos < end) {
+ /* Lookup the character */
+ int size = 1;
+ int c = *pos;
+ /* Is this a trigraph? */
+ if (file->trigraphs &&
+ (c == '?') && ((end - pos) >= 3) && (pos[1] == '?'))
+ {
+ switch(pos[2]) {
+ case '=': c = '#'; break;
+ case '/': c = '\\'; break;
+ case '\'': c = '^'; break;
+ case '(': c = '['; break;
+ case ')': c = ']'; break;
+ case '!': c = '!'; break;
+ case '<': c = '{'; break;
+ case '>': c = '}'; break;
+ case '-': c = '~'; break;
+ }
+ if (c != '?') {
+ size = 3;
+ }
+ }
+ /* Is this an escaped newline? */
+ if (file->join_lines &&
+ (c == '\\') && (pos + size < end) && (pos[1] == '\n'))
+ {
+ /* At the start of a line just eat it */
+ if (pos == file->pos) {
+ file->line++;
+ file->report_line++;
+ file->line_start = pos + size + 1;
+ }
+ pos += size + 1;
+ }
+ /* Do I need to ga any farther? */
+ else if (index == 0) {
+ break;
+ }
+ /* Process a normal character */
+ else {
+ pos += size;
+ index -= 1;
+ }
+ }
+ return pos;
+}
+
+static int get_char(struct file_state *file, const char *pos)
+{
+ const char *end = file->buf + file->size;
+ int c;
+ c = -1;
+ pos = next_char(file, pos, 0);
+ if (pos < end) {
+ /* Lookup the character */
+ c = *pos;
+ /* If it is a trigraph get the trigraph value */
+ if (file->trigraphs &&
+ (c == '?') && ((end - pos) >= 3) && (pos[1] == '?'))
+ {
+ switch(pos[2]) {
+ case '=': c = '#'; break;
+ case '/': c = '\\'; break;
+ case '\'': c = '^'; break;
+ case '(': c = '['; break;
+ case ')': c = ']'; break;
+ case '!': c = '!'; break;
+ case '<': c = '{'; break;
+ case '>': c = '}'; break;
+ case '-': c = '~'; break;
+ }
+ }
+ }
+ return c;
+}
+
+static void eat_chars(struct file_state *file, const char *targ)
+{
+ const char *pos = file->pos;
+ while(pos < targ) {
+ /* Do we have a newline? */
+ if (pos[0] == '\n') {
+ file->line++;
+ file->report_line++;
+ file->line_start = pos + 1;
+ }
+ pos++;
+ }
+ file->pos = pos;
+}
+
+
+static size_t char_strlen(struct file_state *file, const char *src, const char *end)
+{
+ size_t len;
+ len = 0;
+ while(src < end) {
+ src = next_char(file, src, 1);
+ len++;
+ }
+ return len;
+}
+
+static void char_strcpy(char *dest,
+ struct file_state *file, const char *src, const char *end)
+{
+ while(src < end) {
+ int c;
+ c = get_char(file, src);
+ src = next_char(file, src, 1);
+ *dest++ = c;
+ }
+}
+
+static char *char_strdup(struct file_state *file,
+ const char *start, const char *end, const char *id)
+{
+ char *str;
+ size_t str_len;
+ str_len = char_strlen(file, start, end);
+ str = xcmalloc(str_len + 1, id);
+ char_strcpy(str, file, start, end);
+ str[str_len] = '\0';
+ return str;
+}
+
+static const char *after_digits(struct file_state *file, const char *ptr)
+{
+ while(digitp(get_char(file, ptr))) {
+ ptr = next_char(file, ptr, 1);
}
return ptr;
}
-static const char *after_octdigits(const char *ptr, const char *end)
+static const char *after_octdigits(struct file_state *file, const char *ptr)
{
- while((ptr < end) && octdigitp(*ptr)) {
- ptr++;
+ while(octdigitp(get_char(file, ptr))) {
+ ptr = next_char(file, ptr, 1);
}
return ptr;
}
-static const char *after_hexdigits(const char *ptr, const char *end)
+static const char *after_hexdigits(struct file_state *file, const char *ptr)
{
- while((ptr < end) && hexdigitp(*ptr)) {
- ptr++;
+ while(hexdigitp(get_char(file, ptr))) {
+ ptr = next_char(file, ptr, 1);
}
return ptr;
}
-static void save_string(struct compile_state *state,
+static const char *after_alnums(struct file_state *file, const char *ptr)
+{
+ int c;
+ c = get_char(file, ptr);
+ while(letterp(c) || digitp(c)) {
+ ptr = next_char(file, ptr, 1);
+ c = get_char(file, ptr);
+ }
+ return ptr;
+}
+
+static void save_string(struct file_state *file,
struct token *tk, const char *start, const char *end, const char *id)
{
char *str;
- int str_len;
+
/* Create a private copy of the string */
- str_len = end - start + 1;
- str = xmalloc(str_len + 1, id);
- memcpy(str, start, str_len);
- str[str_len] = '\0';
+ str = char_strdup(file, start, end, id);
/* Store the copy in the token */
tk->val.str = str;
- tk->str_len = str_len;
-}
-
-static int lparen_peek(struct compile_state *state, struct file_state *file)
-{
- const char *tokp, *end;
- /* Is the next token going to be an lparen?
- * Whitespace tokens are significant for seeing if a macro
- * should be expanded.
- */
- tokp = file->pos;
- end = file->buf + file->size;
- return (tokp < end) && (*tokp == '(');
+ tk->str_len = strlen(str);
}
static void raw_next_token(struct compile_state *state,
{
const char *token;
int c, c1, c2, c3;
- const char *tokp, *end;
+ const char *tokp;
+ int eat;
int tok;
tk->str_len = 0;
tk->ident = 0;
- token = tokp = file->pos;
- end = file->buf + file->size;
+ token = tokp = next_char(file, file->pos, 0);
tok = TOK_UNKNOWN;
- c = -1;
- if (tokp < end) {
- c = *tokp;
- }
- c1 = -1;
- if ((tokp + 1) < end) {
- c1 = tokp[1];
- }
- c2 = -1;
- if ((tokp + 2) < end) {
- c2 = tokp[2];
- }
- c3 = -1;
- if ((tokp + 3) < end) {
- c3 = tokp[3];
- }
- if (tokp >= end) {
+ c = get_char(file, tokp);
+ tokp = next_char(file, tokp, 1);
+ eat = 0;
+ c1 = get_char(file, tokp);
+ c2 = get_char(file, next_char(file, tokp, 1));
+ c3 = get_char(file, next_char(file, tokp, 2));
+
+ /* The end of the file */
+ if (c == -1) {
tok = TOK_EOF;
- tokp = end;
- }
- /* End of Line */
- else if (eolp(c)) {
- tok = TOK_EOL;
- file->line++;
- file->report_line++;
- file->line_start = tokp + 1;
}
/* Whitespace */
else if (spacep(c)) {
tok = TOK_SPACE;
- while ((tokp < end) && spacep(c)) {
- c = *(++tokp);
- }
- if (!spacep(c)) {
- tokp--;
+ while (spacep(get_char(file, tokp))) {
+ tokp = next_char(file, tokp, 1);
}
}
/* EOL Comments */
else if ((c == '/') && (c1 == '/')) {
tok = TOK_SPACE;
- for(tokp += 2; tokp < end; tokp++) {
- c = *tokp;
+ tokp = next_char(file, tokp, 1);
+ while((c = get_char(file, tokp)) != -1) {
+ /* Advance to the next character only after we verify
+ * the current character is not a newline.
+ * EOL is special to the preprocessor so we don't
+ * want to loose any.
+ */
if (c == '\n') {
- tokp--;
break;
}
+ tokp = next_char(file, tokp, 1);
}
}
/* Comments */
else if ((c == '/') && (c1 == '*')) {
- int line;
- const char *line_start;
- line = file->line;
- line_start = file->line_start;
- for(tokp += 2; (end - tokp) >= 2; tokp++) {
- c = *tokp;
- if (c == '\n') {
- line++;
- line_start = tokp +1;
- }
- else if ((c == '*') && (tokp[1] == '/')) {
+ tokp = next_char(file, tokp, 2);
+ c = c2;
+ while((c1 = get_char(file, tokp)) != -1) {
+ tokp = next_char(file, tokp, 1);
+ if ((c == '*') && (c1 == '/')) {
tok = TOK_SPACE;
- tokp += 1;
break;
}
+ c = c1;
}
if (tok == TOK_UNKNOWN) {
error(state, 0, "unterminated comment");
}
- if (state->token_base && (line != file->line)) {
- error(state, 0,
- "multiline comment in preprocessor directive");
- }
- file->report_line += line - file->line;
- file->line = line;
- file->line_start = line_start;
}
/* string constants */
- else if ((c == '"') ||
- ((c == 'L') && (c1 == '"'))) {
- int line;
- const char *line_start;
- int wchar;
- line = file->line;
- line_start = file->line_start;
+ else if ((c == '"') || ((c == 'L') && (c1 == '"'))) {
+ int wchar, multiline;
+
wchar = 0;
+ multiline = 0;
if (c == 'L') {
wchar = 1;
- tokp++;
+ tokp = next_char(file, tokp, 1);
}
- for(tokp += 1; tokp < end; tokp++) {
- c = *tokp;
+ while((c = get_char(file, tokp)) != -1) {
+ tokp = next_char(file, tokp, 1);
if (c == '\n') {
- line++;
- line_start = tokp + 1;
+ multiline = 1;
}
- else if ((c == '\\') && (tokp +1 < end)) {
- tokp++;
+ else if (c == '\\') {
+ tokp = next_char(file, tokp, 1);
}
else if (c == '"') {
tok = TOK_LIT_STRING;
if (tok == TOK_UNKNOWN) {
error(state, 0, "unterminated string constant");
}
- if (line != file->line) {
- if (state->token_base) {
- /* Preprocessor directives cannot span lines */
- error(state, 0, "multiline string constant");
- } else {
- warning(state, 0, "multiline string constant");
- }
+ if (multiline) {
+ warning(state, 0, "multiline string constant");
}
- file->report_line += line - file->line;
- file->line = line;
- file->line_start = line_start;
/* Save the string value */
- save_string(state, tk, token, tokp, "literal string");
+ save_string(file, tk, token, tokp, "literal string");
}
/* character constants */
- else if ((c == '\'') ||
- ((c == 'L') && (c1 == '\''))) {
- int line;
- const char *line_start;
- int wchar;
- line = file->line;
- line_start = file->line_start;
+ else if ((c == '\'') || ((c == 'L') && (c1 == '\''))) {
+ int wchar, multiline;
+
wchar = 0;
+ multiline = 0;
if (c == 'L') {
wchar = 1;
- tokp++;
+ tokp = next_char(file, tokp, 1);
}
- for(tokp += 1; tokp < end; tokp++) {
- c = *tokp;
+ while((c = get_char(file, tokp)) != -1) {
+ tokp = next_char(file, tokp, 1);
if (c == '\n') {
- line++;
- line_start = tokp + 1;
+ multiline = 1;
}
- else if ((c == '\\') && (tokp +1 < end)) {
- tokp++;
+ else if (c == '\\') {
+ tokp = next_char(file, tokp, 1);
}
else if (c == '\'') {
tok = TOK_LIT_CHAR;
if (tok == TOK_UNKNOWN) {
error(state, 0, "unterminated character constant");
}
- if (line != file->line) {
- if (state->token_base) {
- /* Preprocessor directives cannot span lines */
- error(state, 0, "multiline character constant");
- } else {
- warning(state, 0, "multiline character constant");
- }
+ if (multiline) {
+ warning(state, 0, "multiline character constant");
}
- file->report_line += line - file->line;
- file->line = line;
- file->line_start = line_start;
/* Save the character value */
- save_string(state, tk, token, tokp, "literal character");
+ save_string(file, tk, token, tokp, "literal character");
}
/* integer and floating constants
* Integer Constants
* .{digits}[Ee][+-]?{digits}
* .{digits}
*/
-
else if (digitp(c) || ((c == '.') && (digitp(c1)))) {
- const char *next, *new;
+ const char *next;
int is_float;
+ int cn;
is_float = 0;
if (c != '.') {
- next = after_digits(tokp, end);
+ next = after_digits(file, tokp);
}
else {
- next = tokp;
- }
- if (next[0] == '.') {
- new = after_digits(next, end);
- is_float = (new != next);
- next = new;
- }
- if ((next[0] == 'e') || (next[0] == 'E')) {
- if (((next + 1) < end) &&
- ((next[1] == '+') || (next[1] == '-'))) {
- next++;
- }
- new = after_digits(next, end);
- is_float = (new != next);
+ next = token;
+ }
+ cn = get_char(file, next);
+ if (cn == '.') {
+ next = next_char(file, next, 1);
+ next = after_digits(file, next);
+ is_float = 1;
+ }
+ cn = get_char(file, next);
+ if ((cn == 'e') || (cn == 'E')) {
+ const char *new;
+ next = next_char(file, next, 1);
+ cn = get_char(file, next);
+ if ((cn == '+') || (cn == '-')) {
+ next = next_char(file, next, 1);
+ }
+ new = after_digits(file, next);
+ is_float |= (new != next);
next = new;
}
if (is_float) {
tok = TOK_LIT_FLOAT;
- if ((next < end) && (
- (next[0] == 'f') ||
- (next[0] == 'F') ||
- (next[0] == 'l') ||
- (next[0] == 'L'))
- ) {
- next++;
+ cn = get_char(file, next);
+ if ((cn == 'f') || (cn == 'F') || (cn == 'l') || (cn == 'L')) {
+ next = next_char(file, next, 1);
}
}
if (!is_float && digitp(c)) {
tok = TOK_LIT_INT;
if ((c == '0') && ((c1 == 'x') || (c1 == 'X'))) {
- next = after_hexdigits(tokp + 2, end);
+ next = next_char(file, tokp, 1);
+ next = after_hexdigits(file, next);
}
else if (c == '0') {
- next = after_octdigits(tokp, end);
+ next = after_octdigits(file, tokp);
}
else {
- next = after_digits(tokp, end);
+ next = after_digits(file, tokp);
}
/* crazy integer suffixes */
- if ((next < end) &&
- ((next[0] == 'u') || (next[0] == 'U'))) {
- next++;
- if ((next < end) &&
- ((next[0] == 'l') || (next[0] == 'L'))) {
- next++;
+ cn = get_char(file, next);
+ if ((cn == 'u') || (cn == 'U')) {
+ next = next_char(file, next, 1);
+ cn = get_char(file, next);
+ if ((cn == 'l') || (cn == 'L')) {
+ next = next_char(file, next, 1);
+ cn = get_char(file, next);
+ }
+ if ((cn == 'l') || (cn == 'L')) {
+ next = next_char(file, next, 1);
}
}
- else if ((next < end) &&
- ((next[0] == 'l') || (next[0] == 'L'))) {
- next++;
- if ((next < end) &&
- ((next[0] == 'u') || (next[0] == 'U'))) {
- next++;
+ else if ((cn == 'l') || (cn == 'L')) {
+ next = next_char(file, next, 1);
+ cn = get_char(file, next);
+ if ((cn == 'l') || (cn == 'L')) {
+ next = next_char(file, next, 1);
+ cn = get_char(file, next);
+ }
+ if ((cn == 'u') || (cn == 'U')) {
+ next = next_char(file, next, 1);
}
}
}
- tokp = next - 1;
+ tokp = next;
/* Save the integer/floating point value */
- save_string(state, tk, token, tokp, "literal number");
+ save_string(file, tk, token, tokp, "literal number");
}
/* identifiers */
else if (letterp(c)) {
tok = TOK_IDENT;
- tokp = identifier(tokp, end);
- tokp -= 1;
- tk->ident = lookup(state, token, tokp +1 - token);
+
+ /* Find and save the identifier string */
+ tokp = after_alnums(file, tokp);
+ save_string(file, tk, token, tokp, "identifier");
+
+ /* Look up to see which identifier it is */
+ tk->ident = lookup(state, tk->val.str, tk->str_len);
+
+ /* Free the identifier string */
+ tk->str_len = 0;
+ xfree(tk->val.str);
+
/* See if this identifier can be macro expanded */
tk->val.notmacro = 0;
- if ((tokp < end) && (tokp[1] == '$')) {
- tokp++;
+ c = get_char(file, tokp);
+ if (c == '$') {
+ tokp = next_char(file, tokp, 1);
tk->val.notmacro = 1;
}
}
/* C99 alternate macro characters */
else if ((c == '%') && (c1 == ':') && (c2 == '%') && (c3 == ':')) {
- tokp += 3;
+ eat += 3;
tok = TOK_CONCATENATE;
}
- else if ((c == '.') && (c1 == '.') && (c2 == '.')) { tokp += 2; tok = TOK_DOTS; }
- else if ((c == '<') && (c1 == '<') && (c2 == '=')) { tokp += 2; tok = TOK_SLEQ; }
- else if ((c == '>') && (c1 == '>') && (c2 == '=')) { tokp += 2; tok = TOK_SREQ; }
- else if ((c == '*') && (c1 == '=')) { tokp += 1; tok = TOK_TIMESEQ; }
- else if ((c == '/') && (c1 == '=')) { tokp += 1; tok = TOK_DIVEQ; }
- else if ((c == '%') && (c1 == '=')) { tokp += 1; tok = TOK_MODEQ; }
- else if ((c == '+') && (c1 == '=')) { tokp += 1; tok = TOK_PLUSEQ; }
- else if ((c == '-') && (c1 == '=')) { tokp += 1; tok = TOK_MINUSEQ; }
- else if ((c == '&') && (c1 == '=')) { tokp += 1; tok = TOK_ANDEQ; }
- else if ((c == '^') && (c1 == '=')) { tokp += 1; tok = TOK_XOREQ; }
- else if ((c == '|') && (c1 == '=')) { tokp += 1; tok = TOK_OREQ; }
- else if ((c == '=') && (c1 == '=')) { tokp += 1; tok = TOK_EQEQ; }
- else if ((c == '!') && (c1 == '=')) { tokp += 1; tok = TOK_NOTEQ; }
- else if ((c == '|') && (c1 == '|')) { tokp += 1; tok = TOK_LOGOR; }
- else if ((c == '&') && (c1 == '&')) { tokp += 1; tok = TOK_LOGAND; }
- else if ((c == '<') && (c1 == '=')) { tokp += 1; tok = TOK_LESSEQ; }
- else if ((c == '>') && (c1 == '=')) { tokp += 1; tok = TOK_MOREEQ; }
- else if ((c == '<') && (c1 == '<')) { tokp += 1; tok = TOK_SL; }
- else if ((c == '>') && (c1 == '>')) { tokp += 1; tok = TOK_SR; }
- else if ((c == '+') && (c1 == '+')) { tokp += 1; tok = TOK_PLUSPLUS; }
- else if ((c == '-') && (c1 == '-')) { tokp += 1; tok = TOK_MINUSMINUS; }
- else if ((c == '-') && (c1 == '>')) { tokp += 1; tok = TOK_ARROW; }
- else if ((c == '<') && (c1 == ':')) { tokp += 1; tok = TOK_LBRACKET; }
- else if ((c == ':') && (c1 == '>')) { tokp += 1; tok = TOK_RBRACKET; }
- else if ((c == '<') && (c1 == '%')) { tokp += 1; tok = TOK_LBRACE; }
- else if ((c == '%') && (c1 == '>')) { tokp += 1; tok = TOK_RBRACE; }
- else if ((c == '%') && (c1 == ':')) { tokp += 1; tok = TOK_MACRO; }
- else if ((c == '#') && (c1 == '#')) { tokp += 1; tok = TOK_CONCATENATE; }
+ else if ((c == '.') && (c1 == '.') && (c2 == '.')) { eat += 2; tok = TOK_DOTS; }
+ else if ((c == '<') && (c1 == '<') && (c2 == '=')) { eat += 2; tok = TOK_SLEQ; }
+ else if ((c == '>') && (c1 == '>') && (c2 == '=')) { eat += 2; tok = TOK_SREQ; }
+ else if ((c == '*') && (c1 == '=')) { eat += 1; tok = TOK_TIMESEQ; }
+ else if ((c == '/') && (c1 == '=')) { eat += 1; tok = TOK_DIVEQ; }
+ else if ((c == '%') && (c1 == '=')) { eat += 1; tok = TOK_MODEQ; }
+ else if ((c == '+') && (c1 == '=')) { eat += 1; tok = TOK_PLUSEQ; }
+ else if ((c == '-') && (c1 == '=')) { eat += 1; tok = TOK_MINUSEQ; }
+ else if ((c == '&') && (c1 == '=')) { eat += 1; tok = TOK_ANDEQ; }
+ else if ((c == '^') && (c1 == '=')) { eat += 1; tok = TOK_XOREQ; }
+ else if ((c == '|') && (c1 == '=')) { eat += 1; tok = TOK_OREQ; }
+ else if ((c == '=') && (c1 == '=')) { eat += 1; tok = TOK_EQEQ; }
+ else if ((c == '!') && (c1 == '=')) { eat += 1; tok = TOK_NOTEQ; }
+ else if ((c == '|') && (c1 == '|')) { eat += 1; tok = TOK_LOGOR; }
+ else if ((c == '&') && (c1 == '&')) { eat += 1; tok = TOK_LOGAND; }
+ else if ((c == '<') && (c1 == '=')) { eat += 1; tok = TOK_LESSEQ; }
+ else if ((c == '>') && (c1 == '=')) { eat += 1; tok = TOK_MOREEQ; }
+ else if ((c == '<') && (c1 == '<')) { eat += 1; tok = TOK_SL; }
+ else if ((c == '>') && (c1 == '>')) { eat += 1; tok = TOK_SR; }
+ else if ((c == '+') && (c1 == '+')) { eat += 1; tok = TOK_PLUSPLUS; }
+ else if ((c == '-') && (c1 == '-')) { eat += 1; tok = TOK_MINUSMINUS; }
+ else if ((c == '-') && (c1 == '>')) { eat += 1; tok = TOK_ARROW; }
+ else if ((c == '<') && (c1 == ':')) { eat += 1; tok = TOK_LBRACKET; }
+ else if ((c == ':') && (c1 == '>')) { eat += 1; tok = TOK_RBRACKET; }
+ else if ((c == '<') && (c1 == '%')) { eat += 1; tok = TOK_LBRACE; }
+ else if ((c == '%') && (c1 == '>')) { eat += 1; tok = TOK_RBRACE; }
+ else if ((c == '%') && (c1 == ':')) { eat += 1; tok = TOK_MACRO; }
+ else if ((c == '#') && (c1 == '#')) { eat += 1; tok = TOK_CONCATENATE; }
else if (c == ';') { tok = TOK_SEMI; }
else if (c == '{') { tok = TOK_LBRACE; }
else if (c == '}') { tok = TOK_RBRACE; }
else if (c == '.') { tok = TOK_DOT; }
else if (c == '~') { tok = TOK_TILDE; }
else if (c == '#') { tok = TOK_MACRO; }
+ else if (c == '\n') { tok = TOK_EOL; }
- file->pos = tokp + 1;
+ tokp = next_char(file, tokp, eat);
+ eat_chars(file, tokp);
tk->tok = tok;
- if (tok == TOK_IDENT) {
- if (state->token_base == 0) {
- ident_to_keyword(state, tk);
- } else {
- ident_to_macro(state, tk);
- }
- }
-}
-
-static void next_token(struct compile_state *state, struct token *tk)
-{
- struct file_state *file;
- file = state->file;
- /* Don't return space tokens. */
- do {
- raw_next_token(state, file, tk);
- if (tk->tok == TOK_MACRO) {
- /* Only match preprocessor directives at the start of a line */
- const char *ptr;
- for(ptr = file->line_start; spacep(*ptr); ptr++)
- ;
- if (ptr != file->pos - 1) {
- tk->tok = TOK_UNKNOWN;
- }
- }
- if (tk->tok == TOK_UNKNOWN) {
- error(state, 0, "unknown token");
- }
- } while(tk->tok == TOK_SPACE);
+ tk->pos = token;
}
static void check_tok(struct compile_state *state, struct token *tk, int tok)
struct macro_arg_value {
struct hash_entry *ident;
- unsigned char *value;
+ char *value;
size_t len;
};
static struct macro_arg_value *read_macro_args(
do {
raw_next_token(state, file, tk);
} while(tk->tok == TOK_SPACE);
- return 0;
+ return NULL;
}
argv = xcmalloc(sizeof(*argv) * macro->argc, "macro args");
for(i = 0, arg = macro->args; arg; arg = arg->next, i++) {
if (tk->tok == TOK_EOF) {
error(state, 0, "End of file encountered while parsing macro arguments");
}
-
- len = file->pos - start;
+
+ len = char_strlen(file, start, file->pos);
argv[i].value = xrealloc(
argv[i].value, argv[i].len + len, "macro args");
- memcpy(argv[i].value + argv[i].len, start, len);
+ char_strcpy((char *)argv[i].value + argv[i].len, file, start, file->pos);
argv[i].len += len;
}
if (i != macro->argc -1) {
size_t len, pos;
};
+static void grow_macro_buf(struct compile_state *state,
+ const char *id, struct macro_buf *buf,
+ size_t grow)
+{
+ if ((buf->pos + grow) >= buf->len) {
+ buf->str = xrealloc(buf->str, buf->len + grow, id);
+ buf->len += grow;
+ }
+}
+
static void append_macro_text(struct compile_state *state,
- struct macro *macro, struct macro_buf *buf,
+ const char *id, struct macro_buf *buf,
const char *fstart, size_t flen)
{
+ grow_macro_buf(state, id, buf, flen);
+ memcpy(buf->str + buf->pos, fstart, flen);
#if 0
fprintf(state->errout, "append: `%*.*s' `%*.*s'\n",
buf->pos, buf->pos, buf->str,
- flen, flen, fstart);
+ flen, flen, buf->str + buf->pos);
+#endif
+ buf->pos += flen;
+}
+
+
+static void append_macro_chars(struct compile_state *state,
+ const char *id, struct macro_buf *buf,
+ struct file_state *file, const char *start, const char *end)
+{
+ size_t flen;
+ flen = char_strlen(file, start, end);
+ grow_macro_buf(state, id, buf, flen);
+ char_strcpy(buf->str + buf->pos, file, start, end);
+#if 0
+ fprintf(state->errout, "append: `%*.*s' `%*.*s'\n",
+ buf->pos, buf->pos, buf->str,
+ flen, flen, buf->str + buf->pos);
#endif
- if ((buf->pos + flen) < buf->len) {
- memcpy(buf->str + buf->pos, fstart, flen);
- } else {
- buf->str = xrealloc(buf->str, buf->len + flen, macro->ident->name);
- memcpy(buf->str + buf->pos, fstart, flen);
- buf->len += flen;
- }
buf->pos += flen;
}
static void macro_expand_args(struct compile_state *state,
struct macro *macro, struct macro_arg_value *argv, struct token *tk)
{
- size_t i;
+ int i;
for(i = 0; i < macro->argc; i++) {
struct file_state fmacro, *file;
struct macro_buf buf;
- const char *fstart;
- size_t flen;
+ fmacro.prev = 0;
fmacro.basename = argv[i].ident->name;
fmacro.dirname = "";
+ fmacro.buf = (char *)argv[i].value;
fmacro.size = argv[i].len;
- fmacro.buf = argv[i].value;
fmacro.pos = fmacro.buf;
- fmacro.line_start = fmacro.buf;
fmacro.line = 1;
+ fmacro.line_start = fmacro.buf;
fmacro.report_line = 1;
fmacro.report_name = fmacro.basename;
fmacro.report_dir = fmacro.dirname;
- fmacro.prev = 0;
+ fmacro.macro = 1;
+ fmacro.trigraphs = 0;
+ fmacro.join_lines = 0;
buf.len = argv[i].len;
buf.str = xmalloc(buf.len, argv[i].ident->name);
file = &fmacro;
for(;;) {
- fstart = file->pos;
raw_next_token(state, file, tk);
- flen = file->pos - fstart;
+ /* If we have recursed into another macro body
+ * get out of it.
+ */
if (tk->tok == TOK_EOF) {
struct file_state *old;
old = file;
}
}
- append_macro_text(state, macro, &buf,
- fstart, flen);
+ append_macro_chars(state, macro->ident->name, &buf,
+ file, tk->pos, file->pos);
}
xfree(argv[i].value);
const char space[] = " ";
const char *fstart;
size_t flen;
- size_t i, j;
- fmacro.basename = macro->ident->name;
- fmacro.dirname = "";
- fmacro.size = macro->buf_len - macro->buf_off;;
- fmacro.buf = macro->buf + macro->buf_off;
- fmacro.pos = fmacro.buf;
- fmacro.line_start = fmacro.buf;
- fmacro.line = 1;
+ int i, j;
+
+ /* Place the macro body in a dummy file */
+ fmacro.prev = 0;
+ fmacro.basename = macro->ident->name;
+ fmacro.dirname = "";
+ fmacro.buf = macro->buf;
+ fmacro.size = macro->buf_len;
+ fmacro.pos = fmacro.buf;
+ fmacro.line = 1;
+ fmacro.line_start = fmacro.buf;
fmacro.report_line = 1;
fmacro.report_name = fmacro.basename;
fmacro.report_dir = fmacro.dirname;
- fmacro.prev = 0;
+ fmacro.macro = 1;
+ fmacro.trigraphs = 0;
+ fmacro.join_lines = 0;
+ /* Allocate a buffer to hold the macro expansion */
buf->len = macro->buf_len + 3;
buf->str = xmalloc(buf->len, macro->ident->name);
buf->pos = 0;
flen = argv[i].len;
break;
case TOK_MACRO:
- if (!macro->buf_off) {
+ if (macro->argc < 0) {
break;
}
do {
tk->ident->name);
}
/* Stringize token */
- append_macro_text(state, macro, buf, "\"", 1);
+ append_macro_text(state, macro->ident->name, buf, "\"", 1);
for(j = 0; j < argv[i].len; j++) {
char *str = argv[i].value + j;
size_t len = 1;
str = "\\\"";
len = 2;
}
- append_macro_text(state, macro, buf, str, len);
+ append_macro_text(state, macro->ident->name, buf, str, len);
}
- append_macro_text(state, macro, buf, "\"", 1);
+ append_macro_text(state, macro->ident->name, buf, "\"", 1);
fstart = 0;
flen = 0;
break;
break;
}
- append_macro_text(state, macro, buf, fstart, flen);
+ append_macro_text(state, macro->ident->name, buf, fstart, flen);
fstart = fmacro.pos;
raw_next_token(state, &fmacro, tk);
struct file_state fmacro;
const char *fstart;
size_t flen;
- fmacro.basename = macro->ident->name;
- fmacro.dirname = "";
- fmacro.size = buf->pos;
- fmacro.buf = buf->str;
- fmacro.pos = fmacro.buf;
- fmacro.line_start = fmacro.buf;
- fmacro.line = 1;
+
+ /* Put the old macro expansion buffer in a file */
+ fmacro.prev = 0;
+ fmacro.basename = macro->ident->name;
+ fmacro.dirname = "";
+ fmacro.buf = buf->str;
+ fmacro.size = buf->pos;
+ fmacro.pos = fmacro.buf;
+ fmacro.line = 1;
+ fmacro.line_start = fmacro.buf;
fmacro.report_line = 1;
fmacro.report_name = fmacro.basename;
fmacro.report_dir = fmacro.dirname;
- fmacro.prev = 0;
+ fmacro.macro = 1;
+ fmacro.trigraphs = 0;
+ fmacro.join_lines = 0;
+ /* Allocate a new macro expansion buffer */
buf->len = macro->buf_len + 3;
buf->str = xmalloc(buf->len, macro->ident->name);
buf->pos = 0;
flen = fmacro.pos - fstart;
if ((tk->tok == TOK_IDENT) &&
(tk->ident == macro->ident) &&
- (tk->val.notmacro == 0)) {
- append_macro_text(state, macro, buf, fstart, flen);
+ (tk->val.notmacro == 0))
+ {
+ append_macro_text(state, macro->ident->name, buf, fstart, flen);
fstart = "$";
flen = 1;
}
- append_macro_text(state, macro, buf, fstart, flen);
+ append_macro_text(state, macro->ident->name, buf, fstart, flen);
fstart = fmacro.pos;
raw_next_token(state, &fmacro, tk);
}
xfree(fmacro.buf);
}
-
+
static int compile_macro(struct compile_state *state,
struct file_state **filep, struct token *tk)
{
/* If I am a function like macro and the identifier is not followed
* by a left parenthesis, do nothing.
*/
- if ((macro->buf_off != 0) && !lparen_peek(state, *filep)) {
+ if ((macro->argc >= 0) && (get_char(*filep, (*filep)->pos) != '(')) {
return 0;
}
/* Read in the macro arguments */
argv = 0;
- if (macro->buf_off) {
+ if (macro->argc >= 0) {
raw_next_token(state, *filep, tk);
check_tok(state, tk, TOK_LPAREN);
* be regonized as a canidate for macro expansion.
*/
tag_macro_name(state, macro, &buf, tk);
- append_macro_text(state, macro, &buf, "\n\0", 2);
#if 0
fprintf(state->errout, "%s: %d -> `%*.*s'\n",
free_macro_args(macro, argv);
file = xmalloc(sizeof(*file), "file_state");
- file->basename = xstrdup(ident->name);
- file->dirname = xstrdup("");
- file->buf = buf.str;
- file->size = buf.pos - 2;
- file->pos = file->buf;
- file->line_start = file->pos;
- file->line = 1;
+ file->prev = *filep;
+ file->basename = xstrdup(ident->name);
+ file->dirname = xstrdup("");
+ file->buf = buf.str;
+ file->size = buf.pos;
+ file->pos = file->buf;
+ file->line = 1;
+ file->line_start = file->pos;
file->report_line = 1;
file->report_name = file->basename;
file->report_dir = file->dirname;
- file->prev = *filep;
+ file->macro = 1;
+ file->trigraphs = 0;
+ file->join_lines = 0;
*filep = file;
return 1;
}
static void enter_if(struct compile_state *state)
{
state->if_depth += 1;
- if (state->if_depth > MAX_CPP_IF_DEPTH) {
+ if (state->if_depth > MAX_PP_IF_DEPTH) {
error(state, 0, "#if depth too great");
}
}
state->if_depth -= 1;
}
-static void cpp_token(struct compile_state *state, struct token *tk)
+static void raw_token(struct compile_state *state, struct token *tk)
{
struct file_state *file;
int rescan;
- next_token(state, tk);
+ file = state->file;
+ raw_next_token(state, file, tk);
do {
rescan = 0;
file = state->file;
/* Exit out of an include directive or macro call */
if ((tk->tok == TOK_EOF) &&
- (state->file && state->macro_file) &&
- file->prev)
+ (file != state->macro_file) && file->prev)
{
state->file = file->prev;
/* file->basename is used keep it */
xfree(file->dirname);
xfree(file->buf);
xfree(file);
- next_token(state, tk);
+ file = 0;
+ raw_next_token(state, state->file, tk);
+ rescan = 1;
+ }
+ } while(rescan);
+}
+
+static void pp_token(struct compile_state *state, struct token *tk)
+{
+ struct file_state *file;
+ int rescan;
+
+ raw_token(state, tk);
+ do {
+ rescan = 0;
+ file = state->file;
+ if (tk->tok == TOK_SPACE) {
+ raw_token(state, tk);
rescan = 1;
}
+ else if (tk->tok == TOK_IDENT) {
+ if (state->token_base == 0) {
+ ident_to_keyword(state, tk);
+ } else {
+ ident_to_macro(state, tk);
+ }
+ }
} while(rescan);
}
static void token(struct compile_state *state, struct token *tk)
{
int rescan;
- cpp_token(state, tk);
+ pp_token(state, tk);
do {
rescan = 0;
/* Process a macro directive */
if (tk->tok == TOK_MACRO) {
- preprocess(state, tk);
- rescan = 1;
+ /* Only match preprocessor directives at the start of a line */
+ const char *ptr;
+ ptr = state->file->line_start;
+ while((ptr < tk->pos)
+ && spacep(get_char(state->file, ptr)))
+ {
+ ptr = next_char(state->file, ptr, 1);
+ }
+ if (ptr == tk->pos) {
+ preprocess(state, tk);
+ rescan = 1;
+ }
}
/* Expand a macro call */
else if (tk->ident && tk->ident->sym_define) {
rescan = compile_macro(state, &state->file, tk);
if (rescan) {
- cpp_token(state, tk);
+ pp_token(state, tk);
}
}
- /* Eat tokens disabled by the preprocessor */
- else if (if_eat(state)) {
- cpp_token(state, tk);
+ /* Eat tokens disabled by the preprocessor
+ * (Unless we are parsing a preprocessor directive
+ */
+ else if (if_eat(state) && (state->token_base == 0)) {
+ pp_token(state, tk);
rescan = 1;
}
- /* When not in macro context hide EOL */
+ /* Make certain EOL only shows up in preprocessor directives */
else if ((tk->tok == TOK_EOL) && (state->token_base == 0)) {
- cpp_token(state, tk);
+ pp_token(state, tk);
rescan = 1;
}
+ /* Error on unknown tokens */
+ else if (tk->tok == TOK_UNKNOWN) {
+ error(state, 0, "unknown token");
+ }
} while(rescan);
}
return tk;
}
-static int cpp_peek(struct compile_state *state)
+static int raw_peek(struct compile_state *state)
+{
+ struct token *tk1;
+ tk1 = get_token(state, 1);
+ if (tk1->tok == -1) {
+ raw_token(state, tk1);
+ }
+ return tk1->tok;
+}
+
+static struct token *raw_eat(struct compile_state *state, int tok)
+{
+ raw_peek(state);
+ return do_eat_token(state, tok);
+}
+
+static int pp_peek(struct compile_state *state)
{
struct token *tk1;
tk1 = get_token(state, 1);
if (tk1->tok == -1) {
- cpp_token(state, tk1);
+ pp_token(state, tk1);
}
return tk1->tok;
}
-static struct token *cpp_eat(struct compile_state *state, int tok)
+static struct token *pp_eat(struct compile_state *state, int tok)
{
- cpp_peek(state);
+ pp_peek(state);
return do_eat_token(state, tok);
}
}
}
if (!dir) {
- error(state, 0, "Cannot find `%s'\n", filename);
+ error(state, 0, "Cannot open `%s'\n", filename);
}
dirlen = strlen(dir);
file->dirname = xmalloc(dirlen + 1 + subdir_len + 1, "dirname");
file->report_line = 1;
file->report_name = file->basename;
file->report_dir = file->dirname;
+ file->macro = 0;
+ file->trigraphs = (state->compiler->flags & COMPILER_TRIGRAPHS)? 1: 0;
+ file->join_lines = 1;
file->prev = state->file;
state->file = file;
-
- process_trigraphs(state);
- splice_lines(state);
}
static struct triple *constant_expr(struct compile_state *state);
* a parser and a major restructuring.
* Postpone that for later.
*/
- struct file_state *file;
int old_token_base;
- int line;
int tok;
- file = state->file;
- state->macro_line = line = file->line;
- state->macro_file = file;
+ state->macro_file = state->file;
old_token_base = state->token_base;
state->token_base = current_token - state->token;
- tok = cpp_peek(state);
- switch(tok) {
+ tok = pp_peek(state);
+ switch(tok) {
case TOK_LIT_INT:
{
struct token *tk;
int override_line;
- tk = cpp_eat(state, TOK_LIT_INT);
+ tk = pp_eat(state, TOK_LIT_INT);
override_line = strtoul(tk->val.str, 0, 10);
- /* I have a cpp line marker parse it */
- if (cpp_peek(state) == TOK_LIT_STRING) {
+ /* I have a preprocessor line marker parse it */
+ if (pp_peek(state) == TOK_LIT_STRING) {
const char *token, *base;
char *name, *dir;
int name_len, dir_len;
- tk = cpp_eat(state, TOK_LIT_STRING);
+ tk = pp_eat(state, TOK_LIT_STRING);
name = xmalloc(tk->str_len, "report_name");
token = tk->val.str + 1;
base = strrchr(token, '/');
dir = xmalloc(dir_len + 1, "report_dir");
memcpy(dir, token, dir_len);
dir[dir_len] = '\0';
- file->report_line = override_line - 1;
- file->report_name = name;
- file->report_dir = dir;
+ state->file->report_line = override_line - 1;
+ state->file->report_name = name;
+ state->file->report_dir = dir;
+ state->file->macro = 0;
}
break;
}
case TOK_MLINE:
{
struct token *tk;
- cpp_eat(state, TOK_MLINE);
+ pp_eat(state, TOK_MLINE);
tk = eat(state, TOK_LIT_INT);
- file->report_line = strtoul(tk->val.str, 0, 10) -1;
- if (cpp_peek(state) == TOK_LIT_STRING) {
+ state->file->report_line = strtoul(tk->val.str, 0, 10) -1;
+ if (pp_peek(state) == TOK_LIT_STRING) {
const char *token, *base;
char *name, *dir;
int name_len, dir_len;
- tk = cpp_eat(state, TOK_LIT_STRING);
+ tk = pp_eat(state, TOK_LIT_STRING);
name = xmalloc(tk->str_len, "report_name");
token = tk->val.str + 1;
base = strrchr(token, '/');
dir = xmalloc(dir_len + 1, "report_dir");
memcpy(dir, token, dir_len);
dir[dir_len] = '\0';
- file->report_name = name;
- file->report_dir = dir;
+ state->file->report_name = name;
+ state->file->report_dir = dir;
+ state->file->macro = 0;
}
break;
}
case TOK_MUNDEF:
{
struct hash_entry *ident;
- cpp_eat(state, TOK_MUNDEF);
+ pp_eat(state, TOK_MUNDEF);
if (if_eat(state)) /* quit early when #if'd out */
break;
- ident = cpp_eat(state, TOK_MIDENT)->ident;
+ ident = pp_eat(state, TOK_MIDENT)->ident;
undef_macro(state, ident);
break;
}
case TOK_MPRAGMA:
- cpp_eat(state, TOK_MPRAGMA);
+ pp_eat(state, TOK_MPRAGMA);
if (if_eat(state)) /* quit early when #if'd out */
break;
warning(state, 0, "Ignoring pragma");
break;
case TOK_MELIF:
- cpp_eat(state, TOK_MELIF);
+ pp_eat(state, TOK_MELIF);
reenter_if(state, "#elif");
if (if_eat(state)) /* quit early when #if'd out */
break;
}
break;
case TOK_MIF:
- cpp_eat(state, TOK_MIF);
+ pp_eat(state, TOK_MIF);
enter_if(state);
if (if_eat(state)) /* quit early when #if'd out */
break;
{
struct hash_entry *ident;
- cpp_eat(state, TOK_MIFNDEF);
+ pp_eat(state, TOK_MIFNDEF);
enter_if(state);
if (if_eat(state)) /* quit early when #if'd out */
break;
- ident = cpp_eat(state, TOK_MIDENT)->ident;
+ ident = pp_eat(state, TOK_MIDENT)->ident;
set_if_value(state, ident->sym_define == 0);
if (!if_value(state)) {
eat_tokens(state, TOK_MELSE);
case TOK_MIFDEF:
{
struct hash_entry *ident;
- cpp_eat(state, TOK_MIFDEF);
+ pp_eat(state, TOK_MIFDEF);
enter_if(state);
if (if_eat(state)) /* quit early when #if'd out */
break;
- ident = cpp_eat(state, TOK_MIDENT)->ident;
+ ident = pp_eat(state, TOK_MIDENT)->ident;
set_if_value(state, ident->sym_define != 0);
if (!if_value(state)) {
eat_tokens(state, TOK_MELSE);
break;
}
case TOK_MELSE:
- cpp_eat(state, TOK_MELSE);
+ pp_eat(state, TOK_MELSE);
enter_else(state, "#else");
if (!if_eat(state) && if_value(state)) {
eat_tokens(state, TOK_MENDIF);
}
break;
case TOK_MENDIF:
- cpp_eat(state, TOK_MENDIF);
+ pp_eat(state, TOK_MENDIF);
exit_if(state, "#endif");
break;
case TOK_MDEFINE:
{
struct hash_entry *ident;
struct macro_arg *args, **larg;
- const char *start, *mstart, *ptr;
+ const char *mstart, *mend;
+ int argc;
- cpp_eat(state, TOK_MDEFINE);
+ pp_eat(state, TOK_MDEFINE);
if (if_eat(state)) /* quit early when #if'd out */
break;
-
- ident = cpp_eat(state, TOK_MIDENT)->ident;
+ ident = pp_eat(state, TOK_MIDENT)->ident;
+ argc = -1;
args = 0;
larg = &args;
- /* Remember the start of the macro */
- start = file->pos;
-
- /* Find the end of the line. */
- for(ptr = start; *ptr != '\n'; ptr++)
- ;
-
- /* remove the trailing whitespace */
- ptr-=1;
- while(spacep(*ptr)) {
- ptr--;
- }
-
- /* Remove leading whitespace */
- while(spacep(*start) && (start < ptr)) {
- start++;
- }
- /* Remember where the macro starts */
- mstart = start;
-
/* Parse macro parameters */
- if (lparen_peek(state, state->file)) {
- cpp_eat(state, TOK_LPAREN);
-
+ if (raw_peek(state) == TOK_LPAREN) {
+ raw_eat(state, TOK_LPAREN);
+ argc += 1;
+
for(;;) {
struct macro_arg *narg, *arg;
struct hash_entry *aident;
int tok;
- tok = cpp_peek(state);
+ tok = pp_peek(state);
if (!args && (tok == TOK_RPAREN)) {
break;
}
else if (tok == TOK_DOTS) {
- cpp_eat(state, TOK_DOTS);
+ pp_eat(state, TOK_DOTS);
aident = state->i___VA_ARGS__;
}
else {
- aident = cpp_eat(state, TOK_MIDENT)->ident;
+ aident = pp_eat(state, TOK_MIDENT)->ident;
}
narg = xcmalloc(sizeof(*arg), "macro arg");
/* Add the new argument to the end of the list */
*larg = narg;
larg = &narg->next;
+ argc += 1;
if ((aident == state->i___VA_ARGS__) ||
- (cpp_peek(state) != TOK_COMMA)) {
+ (pp_peek(state) != TOK_COMMA)) {
break;
}
- cpp_eat(state, TOK_COMMA);
+ pp_eat(state, TOK_COMMA);
}
- cpp_eat(state, TOK_RPAREN);
+ pp_eat(state, TOK_RPAREN);
+ }
+ /* Remove leading whitespace */
+ while(raw_peek(state) == TOK_SPACE) {
+ raw_eat(state, TOK_SPACE);
+ }
- /* Get the start of the macro body */
- mstart = file->pos;
+ /* Remember the start of the macro body */
+ tok = raw_peek(state);
+ mend = mstart = get_token(state, 1)->pos;
- /* Remove leading whitespace */
- while(spacep(*mstart) && (mstart < ptr)) {
- mstart++;
+ /* Find the end of the macro */
+ for(tok = raw_peek(state); tok != TOK_EOL; tok = raw_peek(state)) {
+ raw_eat(state, tok);
+ /* Remember the end of the last non space token */
+ raw_peek(state);
+ if (tok != TOK_SPACE) {
+ mend = get_token(state, 1)->pos;
}
}
- define_macro(state, ident, start, ptr - start + 1,
- mstart - start, args);
+
+ /* Now that I have found the body defined the token */
+ do_define_macro(state, ident,
+ char_strdup(state->file, mstart, mend, "macro buf"),
+ argc, args);
break;
}
case TOK_MERROR:
{
- const char *end;
+ const char *start, *end;
int len;
- cpp_eat(state, TOK_MERROR);
+ pp_eat(state, TOK_MERROR);
+ /* Find the start of the line */
+ raw_peek(state);
+ start = get_token(state, 1)->pos;
+
/* Find the end of the line */
- for(end = file->pos; *end != '\n'; end++)
- ;
- len = (end - file->pos);
+ while((tok = raw_peek(state)) != TOK_EOL) {
+ raw_eat(state, tok);
+ }
+ end = get_token(state, 1)->pos;
+ len = end - start;
if (!if_eat(state)) {
- error(state, 0, "%*.*s", len, len, file->pos);
+ error(state, 0, "%*.*s", len, len, start);
}
- file->pos = end;
break;
}
case TOK_MWARNING:
{
- const char *end;
+ const char *start, *end;
int len;
- cpp_eat(state, TOK_MWARNING);
+ pp_eat(state, TOK_MWARNING);
+
+ /* Find the start of the line */
+ raw_peek(state);
+ start = get_token(state, 1)->pos;
+
/* Find the end of the line */
- for(end = file->pos; *end != '\n'; end++)
- ;
- len = (end - file->pos);
+ while((tok = raw_peek(state)) != TOK_EOL) {
+ raw_eat(state, tok);
+ }
+ end = get_token(state, 1)->pos;
+ len = end - start;
if (!if_eat(state)) {
- warning(state, 0, "%*.*s", len, len, file->pos);
+ warning(state, 0, "%*.*s", len, len, start);
}
- file->pos = end;
break;
}
case TOK_MINCLUDE:
local = 0;
name = 0;
- cpp_eat(state, TOK_MINCLUDE);
+ pp_eat(state, TOK_MINCLUDE);
tok = peek(state);
if (tok == TOK_LIT_STRING) {
struct token *tk;
local = 1;
}
else if (tok == TOK_LESS) {
- const char *start, *end;
+ struct macro_buf buf;
eat(state, TOK_LESS);
- start = file->pos;
- for(end = start; *end != '\n'; end++) {
- if (*end == '>') {
- break;
- }
- }
- if (*end == '\n') {
+
+ buf.len = 40;
+ buf.str = xmalloc(buf.len, "include");
+ buf.pos = 0;
+
+ tok = peek(state);
+ while((tok != TOK_MORE) &&
+ (tok != TOK_EOL) && (tok != TOK_EOF))
+ {
+ struct token *tk;
+ tk = eat(state, tok);
+ append_macro_chars(state, "include", &buf,
+ state->file, tk->pos, state->file->pos);
+ tok = peek(state);
+ }
+ append_macro_text(state, "include", &buf, "\0", 1);
+ if (peek(state) != TOK_MORE) {
error(state, 0, "Unterminated include directive");
}
- name = xmalloc(end - start + 1, "include");
- memcpy(name, start, end - start);
- name[end - start] = '\0';
- file->pos = end;
- local = 0;
eat(state, TOK_MORE);
+ local = 0;
+ name = buf.str;
}
else {
error(state, 0, "Invalid include directive");
}
/* Error if there are any tokens after the include */
- if (cpp_peek(state) != TOK_EOL) {
+ if (pp_peek(state) != TOK_EOL) {
error(state, 0, "garbage after include directive");
}
if (!if_eat(state)) {
}
/* Consume the rest of the macro line */
do {
- tok = cpp_peek(state);
- cpp_eat(state, tok);
+ tok = pp_peek(state);
+ pp_eat(state, tok);
} while((tok != TOK_EOF) && (tok != TOK_EOL));
state->token_base = old_token_base;
+ state->macro_file = NULL;
return;
}
static inline ulong_t mask_uint(ulong_t x)
{
if (SIZEOF_INT < SIZEOF_LONG) {
- ulong_t mask = (((ulong_t)1) << ((ulong_t)(SIZEOF_INT))) -1;
+ ulong_t mask = (1ULL << ((ulong_t)(SIZEOF_INT))) -1;
x &= mask;
}
return x;
static struct type void_type = { .type = TYPE_VOID };
static struct type char_type = { .type = TYPE_CHAR };
static struct type uchar_type = { .type = TYPE_UCHAR };
+#if DEBUG_ROMCC_WARNING
static struct type short_type = { .type = TYPE_SHORT };
+#endif
static struct type ushort_type = { .type = TYPE_USHORT };
static struct type int_type = { .type = TYPE_INT };
static struct type uint_type = { .type = TYPE_UINT };
.left = &void_type,
};
+#if DEBUG_ROMCC_WARNING
static struct type void_func_type = {
.type = TYPE_FUNCTION,
.left = &void_type,
.right = &void_type,
};
+#endif
static size_t bits_to_bytes(size_t size)
{
if (!def) {
return 0;
}
+#if DEBUG_ROMCC_WARNINGS
#warning "CHECK_ME is this the only place I need to do lvalue conversions?"
+#endif
/* Transform lvalues into something we can read */
def = lvalue_conversion(state, def);
if (!is_lvalue(state, def)) {
val = read_expr(state, var);
/* Generate the prog for a logical and */
- def = mkprog(state, var, lstore, jmp, mid, rstore, end, val, 0);
+ def = mkprog(state, var, lstore, jmp, mid, rstore, end, val, 0UL);
return def;
}
val = read_expr(state, var);
/* Generate the prog for a logical or */
- def = mkprog(state, var, left, jmp, mid, right, end, val, 0);
+ def = mkprog(state, var, left, jmp, mid, right, end, val, 0UL);
return def;
}
val = read_expr(state, var);
/* Generate the prog for a conditional expression */
- def = mkprog(state, var, jmp1, top, left, jmp2, mid, right, end, val, 0);
+ def = mkprog(state, var, jmp1, top, left, jmp2, mid, right, end, val, 0UL);
return def;
}
static int expr_depth(struct compile_state *state, struct triple *ins)
{
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME move optimal ordering of subexpressions into the optimizer"
+#endif
int count;
count = 0;
if (!ins || (ins->id & TRIPLE_FLAG_FLATTENED)) {
return is_simple_const(ins) && (ins->u.cval == 1);
}
+#if DEBUG_ROMCC_WARNING
static long_t bit_count(ulong_t value)
{
int count;
return count;
}
+#endif
+
static long_t bsr(ulong_t value)
{
int i;
return -1;
}
-static long_t log2(ulong_t value)
+static long_t ilog2(ulong_t value)
{
return bsr(value);
}
static long_t tlog2(struct triple *ins)
{
- return log2(ins->u.cval);
+ return ilog2(ins->u.cval);
}
static int is_pow2(struct triple *ins)
return 0;
}
value = ins->u.cval;
- log = log2(value);
+ log = ilog2(value);
if (log == -1) {
return 0;
}
}
}
+#if DEBUG_ROMCC_WARNING
static void unuse_misc(struct compile_state *state, struct triple *ins)
{
struct triple **expr;
}
}
+#endif
static void check_misc(struct compile_state *state, struct triple *ins)
{
ins->targ = 0;
}
+#if DEBUG_ROMCC_WARNING
static void wipe_branch(struct compile_state *state, struct triple *ins)
{
/* Becareful which instructions you replace the wiped
ins->misc = 0;
ins->targ = 0;
}
+#endif
static void mkcopy(struct compile_state *state,
struct triple *ins, struct triple *rhs)
struct hash_entry **ident, int need_ident);
static void decl(struct compile_state *state, struct triple *first);
static struct type *specifier_qualifier_list(struct compile_state *state);
+#if DEBUG_ROMCC_WARNING
static int isdecl_specifier(int tok);
+#endif
static struct type *decl_specifiers(struct compile_state *state);
static int istype(int tok);
static struct triple *expr(struct compile_state *state);
int c;
int str_len;
tk = eat(state, TOK_LIT_CHAR);
- str = tk->val.str + 1;
+ str = (signed char *)tk->val.str + 1;
str_len = tk->str_len - 2;
if (str_len <= 0) {
error(state, 0, "empty character constant");
/* The while loop handles string concatenation */
do {
tk = eat(state, TOK_LIT_STRING);
- str = tk->val.str + 1;
+ str = (signed char *)tk->val.str + 1;
str_len = tk->str_len - 2;
if (str_len < 0) {
error(state, 0, "negative string constant length");
int parens;
eat(state, TOK_MDEFINED);
parens = 0;
- if (cpp_peek(state) == TOK_LPAREN) {
- cpp_eat(state, TOK_LPAREN);
+ if (pp_peek(state) == TOK_LPAREN) {
+ pp_eat(state, TOK_LPAREN);
parens = 1;
}
- ident = cpp_eat(state, TOK_MIDENT)->ident;
+ ident = pp_eat(state, TOK_MIDENT)->ident;
if (parens) {
eat(state, TOK_RPAREN);
}
struct type *result_type;
int tok, op, sign;
done = 0;
- switch(tok = (peek(state))) {
+ tok = peek(state);
+ switch(tok) {
case TOK_STAR:
case TOK_DIV:
case TOK_MOD:
static struct triple *relational_expr(struct compile_state *state)
{
+#if DEBUG_ROMCC_WARNINGS
#warning "Extend relational exprs to work on more than arithmetic types"
+#endif
struct triple *def;
int done;
def = shift_expr(state);
static struct triple *equality_expr(struct compile_state *state)
{
+#if DEBUG_ROMCC_WARNINGS
#warning "Extend equality exprs to work on more than arithmetic types"
+#endif
struct triple *def;
int done;
def = relational_expr(state);
def = assignment_expr(state);
while(peek(state) == TOK_COMMA) {
eat(state, TOK_COMMA);
- def = mkprog(state, def, assignment_expr(state), 0);
+ def = mkprog(state, def, assignment_expr(state), 0UL);
}
return def;
}
int last;
eat(state, TOK_RETURN);
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME implement a more general excess branch elimination"
+#endif
val = 0;
/* If we have a return value do some more work */
if (peek(state) != TOK_SEMI) {
return type;
}
+#if DEBUG_ROMCC_WARNING
static int isdecl_specifier(int tok)
{
switch(tok) {
return 0;
}
}
+#endif
static struct type *decl_specifiers(struct compile_state *state)
{
struct compile_state *state, struct type *type)
{
struct triple *result;
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME more consistent initializer handling (where should eval_const_expr go?"
+#endif
if (peek(state) != TOK_LBRACE) {
result = assignment_expr(state);
if (((type->type & TYPE_MASK) == TYPE_ARRAY) &&
struct compile_state *state, struct basic_blocks *bb);
static void free_variable_lifetimes(struct compile_state *state,
struct basic_blocks *bb, struct reg_block *blocks);
+#if DEBUG_EXPLICIT_CLOSURES
static void print_live_variables(struct compile_state *state,
struct basic_blocks *bb, struct reg_block *rb, FILE *fp);
+#endif
static struct triple *call(struct compile_state *state,
}
static void print_blocks(struct compile_state *state, const char *func, FILE *fp)
{
- static void print_dominators(struct compile_state *state, FILE *fp, struct basic_blocks *bb);
- static void print_dominance_frontiers(struct compile_state *state, FILE *fp, struct basic_blocks *bb);
if (state->compiler->debug & DEBUG_BASIC_BLOCKS) {
fprintf(fp, "After %s\n", func);
romcc_print_blocks(state, fp);
{
return do_triple_set(&rb->in, in, 0);
}
+
+#if DEBUG_ROMCC_WARNING
static void unin_triple(struct reg_block *rb, struct triple *unin)
{
do_triple_unset(&rb->in, unin);
}
+#endif
static int out_triple(struct reg_block *rb, struct triple *out)
{
return do_triple_set(&rb->out, out, 0);
}
+#if DEBUG_ROMCC_WARNING
static void unout_triple(struct reg_block *rb, struct triple *unout)
{
do_triple_unset(&rb->out, unout);
}
+#endif
static int initialize_regblock(struct reg_block *blocks,
struct block *block, int vertex)
/* Find the variables we use but don't define and add
* it to the current blocks input set.
*/
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME is this O(N^2) algorithm bad?"
+#endif
struct block *block;
struct triple *ptr;
int done;
struct reg_block *rb;
FILE *fp;
};
+#if DEBUG_EXPLICIT_CLOSURES
static void print_live_variables_block(
struct compile_state *state, struct block *block, void *arg)
walk_blocks(state, bb, print_live_variables_block, &info);
}
-
+#endif
static int count_triples(struct compile_state *state)
{
struct triple *last;
last = user->member->last;
while((last->op == OP_NOOP) && (last != user->member->first)) {
- internal_warning(state, last, "awakening noop?");
+#if DEBUG_ROMCC_WARNINGS
+#warning "Should we bring the awakening noops back?"
+#endif
+ // internal_warning(state, last, "awakening noop?");
last = last->prev;
}
awaken(state, dtriple, &last, &work_list_tail);
*
*/
+#if DEBUG_ROMCC_WARNING
static void different_colored(
struct compile_state *state, struct reg_state *rstate,
struct triple *parent, struct triple *ins)
}
}
}
-
+#endif
static struct live_range *coalesce_ranges(
struct compile_state *state, struct reg_state *rstate,
#endif
/* Append lr2 onto lr1 */
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME should this be a merge instead of a splice?"
+#endif
/* This FIXME item applies to the correctness of live_range_end
* and to the necessity of making multiple passes of coalesce_live_ranges.
* A failure to find some coalesce opportunities in coaleace_live_ranges
return;
}
+#if DEBUG_CONSISTENCY > 1
static struct live_range *get_verify_live_range(
struct compile_state *state, struct reg_state *rstate, struct triple *ins)
{
}
return;
}
-
+#endif
static void print_interference_ins(
struct compile_state *state,
struct reg_block *blocks, struct triple *orig, struct triple *new)
{
int i;
+#if DEBUG_ROMCC_WARNINGS
#warning "WISHLIST visit just those blocks that need it *"
+#endif
for(i = 1; i <= state->bb.last_vertex; i++) {
struct reg_block *rb;
rb = &blocks[i];
struct triple_set *set, *next;
struct triple *copy;
+#if DEBUG_ROMCC_WARNINGS
#warning "WISHLIST recalculate all affected instructions colors"
+#endif
info = find_lhs_color(state, tangle, 0);
for(set = tangle->use; set; set = next) {
struct triple *user;
* Then a triple is not constrained.
* FIXME handle this case!
*/
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME ignore cases that cannot be fixed (a definition followed by a use)"
+#endif
/* Of the constrained live ranges deal with the
for(edge = range->edges; edge; edge = edge->next) {
constrained = find_constrained_def(state, edge->node, constrained);
}
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME should I call find_constrained_def here only if no previous constrained def was found?"
+#endif
if (!constrained) {
constrained = find_constrained_def(state, range, constrained);
}
* it would be useful to have.
*
*/
+#if DEBUG_ROMCC_WARNINGS
#warning "WISHLIST implement live range splitting..."
+#endif
if (!split && (state->compiler->debug & DEBUG_RANGE_CONFLICTS2)) {
FILE *fp = state->errout;
scratch->next = lnode->def->next;
}
/* Recompute the value */
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME see if simplify does anything bad"
+#endif
/* So far it looks like only the strength reduction
* optimization are things I need to worry about.
*/
(( !triple_is_def(state, lnode->def) &&
!triple_is_cbranch(state, lnode->def)) ||
(lnode->def->op == OP_PIECE))) {
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME constant propogate through expressions with multiple left hand sides"
+#endif
if (changed) {
internal_warning(state, lnode->def, "non def changes value?");
}
/* Propogate constants throughout the code */
scc_transform(state);
verify_consistency(state);
+#if DEBUG_ROMCC_WARNINGS
#warning "WISHLIST implement single use constants (least possible register pressure)"
#warning "WISHLIST implement induction variable elimination"
+#endif
/* Select architecture instructions and an initial partial
* coloring based on architecture constraints.
*/
#define REG_XMM7 44
#define REGC_XMM_FIRST REG_XMM0
#define REGC_XMM_LAST REG_XMM7
+
+#if DEBUG_ROMCC_WARNINGS
#warning "WISHLIST figure out how to use pinsrw and pextrw to better use extended regs"
+#endif
+
#define LAST_REG REG_XMM7
#define REGC_GPR32_8_FIRST REG_EAX
static unsigned arch_type_to_regcm(struct compile_state *state, struct type *type)
{
+
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME force types smaller (if legal) before I get here"
+#endif
unsigned mask;
mask = 0;
switch(type->type & TYPE_MASK) {
(RHS(branch, 0)->op != OP_TEST)) {
internal_error(state, branch, "bad branch test");
}
+#if DEBUG_ROMCC_WARNINGS
#warning "FIXME I have observed instructions between the test and branch instructions"
+#endif
ptr = RHS(branch, 0);
for(ptr = RHS(branch, 0)->next; ptr != branch; ptr = ptr->next) {
if (ptr->op != OP_COPY) {
filename = 0;
line = 0;
for(;;) {
+ struct file_state *file;
struct token *tk;
const char *token_str;
tok = peek(state);
tk->ident ? tk->ident->name :
tk->str_len ? tk->val.str :
tokens[tk->tok];
-
- if ((state->file->line != line) ||
- (state->file->basename != filename)) {
+
+ file = state->file;
+ while(file->macro && file->prev) {
+ file = file->prev;
+ }
+ if (!file->macro &&
+ ((file->line != line) || (file->basename != filename)))
+ {
int i, col;
- if ((state->file->basename == filename) &&
- (line < state->file->line)) {
- while(line < state->file->line) {
+ if ((file->basename == filename) &&
+ (line < file->line)) {
+ while(line < file->line) {
fprintf(fp, "\n");
line++;
}
}
else {
fprintf(fp, "\n#line %d \"%s\"\n",
- state->file->line, state->file->basename);
+ file->line, file->basename);
}
- line = state->file->line;
- filename = state->file->basename;
- col = get_col(state->file) - strlen(token_str);
+ line = file->line;
+ filename = file->basename;
+ col = get_col(file) - strlen(token_str);
for(i = 0; i < col; i++) {
fprintf(fp, " ");
}
compile_file(&state, filename, 1);
/* Stop if all we want is preprocessor output */
- if (state.compiler->flags & COMPILER_CPP_ONLY) {
+ if (state.compiler->flags & COMPILER_PP_ONLY) {
print_preprocessed_tokens(&state);
return;
}