aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/compile-i386.c
diff options
authorJeff Garzik <jgarzik@redhat.com>2003-09-07 20:30:38 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:01:05 -0700
commit890dcd116c0a953ef8fd232f7bf0064d13ada448 (patch)
tree73d4ac3926a91fa24e0af30b8b524cafb0db6733 /compile-i386.c
parent221af696b37591f53138482cb8e6a4f27ab307f3 (diff)
downloadsparse-dev-890dcd116c0a953ef8fd232f7bf0064d13ada448.tar.gz
[be] Instead of buffering output with a hand-rolled list of
text buffers, update code to use a ptr_list of "atoms". Atoms basically correspond to a single line of assembly. There are ATOM_TEXT atoms for ASCII text (the only kind of atom currently in use) and ATOM_INSN for instructions.
Diffstat (limited to 'compile-i386.c')
-rw-r--r--compile-i386.c99
1 files changed, 92 insertions, 7 deletions
diff --git a/compile-i386.c b/compile-i386.c
index ecc6a0fe..a9f0184c 100644
--- a/compile-i386.c
+++ b/compile-i386.c
@@ -39,7 +39,7 @@ struct textbuf {
struct function {
int pseudo_nr;
struct ptr_list *pseudo_list;
- struct textbuf *buf;
+ struct ptr_list *atom_list;
struct symbol **argv;
unsigned int argc;
int ret_target;
@@ -73,6 +73,32 @@ struct symbol_private {
struct storage *addr;
};
+enum atom_type {
+ ATOM_TEXT,
+ ATOM_INSN,
+};
+
+struct atom {
+ enum atom_type type;
+ union {
+ /* stuff for text */
+ struct {
+ char *text;
+ unsigned int text_len; /* w/o terminating null */
+ };
+
+ /* stuff for insns */
+ struct {
+ char insn[32];
+ char comment[40];
+ struct storage *op1;
+ struct storage *op2;
+ unsigned long flags;
+ };
+ };
+};
+
+
struct function *current_func = NULL;
struct textbuf *unit_post_text = NULL;
static const char *current_section;
@@ -164,6 +190,34 @@ static const char *stor_op_name(struct storage *s)
return name;
}
+static struct atom *new_atom(enum atom_type type)
+{
+ struct atom *atom;
+
+ atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
+ if (!atom)
+ die("nuclear OOM");
+
+ atom->type = type;
+
+ return atom;
+}
+
+static inline void push_atom(struct function *f, struct atom *atom)
+{
+ add_ptr_list(&f->atom_list, atom);
+}
+
+static void push_text_atom(struct function *f, const char *text)
+{
+ struct atom *atom = new_atom(ATOM_TEXT);
+
+ atom->text = strdup(text);
+ atom->text_len = strlen(text);
+
+ push_atom(f, atom);
+}
+
static struct storage *new_pseudo(void)
{
struct function *f = current_func;
@@ -261,7 +315,7 @@ static void insn(const char *insn, const char *op1, const char *op2,
else
sprintf(s, "\t%s\t%s%s\n", insn,
comment[0] ? "\t\t" : "", comment);
- textbuf_push(&f->buf, s);
+ push_text_atom(f, s);
}
static void emit_unit_pre(const char *basename)
@@ -287,14 +341,44 @@ static void emit_section(const char *s)
current_section = s;
}
+static void emit_atom(struct function *f, struct atom *atom)
+{
+ switch (atom->type) {
+ case ATOM_TEXT: {
+ ssize_t rc = write(STDOUT_FILENO, atom->text, atom->text_len);
+ (void) rc; /* FIXME */
+ break;
+ }
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static void emit_atom_list(struct function *f)
+{
+ struct atom *atom;
+
+ FOR_EACH_PTR(f->atom_list, atom) {
+ emit_atom(f, atom);
+ } END_FOR_EACH_PTR;
+}
+
static void func_cleanup(struct function *f)
{
struct storage *stor;
+ struct atom *atom;
FOR_EACH_PTR(f->pseudo_list, stor) {
free(stor);
} END_FOR_EACH_PTR;
+ FOR_EACH_PTR(f->atom_list, atom) {
+ if ((atom->type == ATOM_TEXT) && (atom->text))
+ free(atom->text);
+ free(atom);
+ } END_FOR_EACH_PTR;
+
free_ptr_list(&f->pseudo_list);
free(f);
}
@@ -369,7 +453,7 @@ static void emit_func_post(struct symbol *sym, struct storage *val)
/* jump target for 'return' statements */
sprintf(jump_target, ".L%d:\n", f->ret_target);
- textbuf_push(&f->buf, jump_target);
+ push_text_atom(f, jump_target);
/* function prologue */
if (val)
@@ -378,7 +462,8 @@ static void emit_func_post(struct symbol *sym, struct storage *val)
insn("ret", NULL, NULL, NULL);
/* output everything to stdout */
- textbuf_emit(&f->buf);
+ fflush(stdout); /* paranoia; needed? */
+ emit_atom_list(f);
/* function footer */
printf("\t.size\t%s, .-%s\n", name, name);
@@ -784,14 +869,14 @@ static void emit_if_conditional(struct statement *stmt)
* the failed-conditional case will fall through to here
*/
sprintf(s, ".L%d:\n", target);
- textbuf_push(&f->buf, s);
+ push_text_atom(f, s);
target = last;
x86_statement(stmt->if_false);
}
sprintf(s, ".L%d:\t\t\t\t\t# end if\n", target);
- textbuf_push(&f->buf, s);
+ push_text_atom(f, s);
}
static struct storage *emit_inc_dec(struct expression *expr, int postop)
@@ -834,7 +919,7 @@ static struct storage *emit_return_stmt(struct statement *stmt)
val = x86_expression(expr);
sprintf(s, "\tjmp\t.L%d\n", f->ret_target);
- textbuf_push(&f->buf, s);
+ push_text_atom(f, s);
return val;
}