aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-12-13 00:22:35 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:06:06 -0700
commit9be6384968d2626972c454efa7a9f8b8d48974fe (patch)
tree8176381d44c4d7a4dd331509f1921901927ef6a5 /example.c
parent[PATCH] Diff to make sparse not complain about __format_arg__ (diff)
downloadsparse-9be6384968d2626972c454efa7a9f8b8d48974fe.tar.gz
sparse-9be6384968d2626972c454efa7a9f8b8d48974fe.tar.bz2
sparse-9be6384968d2626972c454efa7a9f8b8d48974fe.zip
Do absolutely horrid job of generating code for asms.
I totally botch the constraints handling, but hey, it's just an example.
Diffstat (limited to 'example.c')
-rw-r--r--example.c144
1 files changed, 137 insertions, 7 deletions
diff --git a/example.c b/example.c
index 004d87f..c7ce22c 100644
--- a/example.c
+++ b/example.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <string.h>
#include <assert.h>
#include "symbol.h"
@@ -917,38 +918,167 @@ static void generate_select(struct bb_state *state, struct instruction *insn)
output_insn(state, "sel%s %s,%s", cond, src2->name, dst->name);
}
-static void generate_asm_inputs(struct bb_state *state, struct asm_constraint_list *list)
+struct asm_arg {
+ const struct ident *name;
+ const char *value;
+};
+
+static void replace_asm_arg(char **dst_p, struct asm_arg *arg)
+{
+ char *dst = *dst_p;
+ int len = strlen(arg->value);
+
+ memcpy(dst, arg->value, len);
+ *dst_p = dst + len;
+}
+
+static void replace_asm_percent(const char **src_p, char **dst_p, struct asm_arg *args, int nr)
+{
+ const char *src = *src_p;
+ char c;
+ int index;
+
+ c = *src++;
+ switch (c) {
+ case '0' ... '9':
+ index = c - '0';
+ if (index < nr)
+ replace_asm_arg(dst_p, args+index);
+ break;
+ }
+ *src_p = src;
+ return;
+}
+
+static void replace_asm_named(const char **src_p, char **dst_p, struct asm_arg *args, int nr)
+{
+ const char *src = *src_p;
+ const char *end = src;
+
+ for(;;) {
+ char c = *end++;
+ if (!c)
+ return;
+ if (c == ']') {
+ int i;
+
+ *src_p = end;
+ for (i = 0; i < nr; i++) {
+ const struct ident *ident = args[i].name;
+ int len;
+ if (!ident)
+ continue;
+ len = ident->len;
+ if (memcmp(src, ident->name, len))
+ continue;
+ replace_asm_arg(dst_p, args+i);
+ return;
+ }
+ }
+ }
+}
+
+static const char *replace_asm_args(const char *str, struct asm_arg *args, int nr)
+{
+ static char buffer[1000];
+ char *p = buffer;
+
+ for (;;) {
+ char c = *str;
+ *p = c;
+ if (!c)
+ return buffer;
+ str++;
+ switch (c) {
+ case '%':
+ if (*str == '%') {
+ str++;
+ p++;
+ continue;
+ }
+ replace_asm_percent(&str, &p, args, nr);
+ continue;
+ case '[':
+ replace_asm_named(&str, &p, args, nr);
+ continue;
+ default:
+ break;
+ }
+ p++;
+ }
+}
+
+#define MAX_ASM_ARG (50)
+static struct asm_arg *generate_asm_inputs(struct bb_state *state, struct asm_constraint_list *list, struct asm_arg *arg)
{
struct asm_constraint *entry;
FOR_EACH_PTR(list, entry) {
const char *constraint = entry->constraint;
pseudo_t pseudo = entry->pseudo;
+ const char *string;
- output_insn(state, "# asm input \"%s\": %s", constraint, show_pseudo(pseudo));
+ string = "undef";
+ switch (*constraint) {
+ case 'r':
+ string = getreg(state, pseudo, NULL)->name;
+ break;
+ default:
+ string = generic(state, pseudo);
+ break;
+ }
+
+ output_insn(state, "# asm input \"%s\": %s : %s", constraint, show_pseudo(pseudo), string);
+
+ arg->name = entry->ident;
+ arg->value = string;
+ arg++;
} END_FOR_EACH_PTR(entry);
+ return arg;
}
-static void generate_asm_outputs(struct bb_state *state, struct asm_constraint_list *list)
+static struct asm_arg *generate_asm_outputs(struct bb_state *state, struct asm_constraint_list *list, struct asm_arg *arg)
{
struct asm_constraint *entry;
FOR_EACH_PTR(list, entry) {
const char *constraint = entry->constraint;
pseudo_t pseudo = entry->pseudo;
+ const char *string;
while (*constraint == '=' || *constraint == '+')
constraint++;
- output_insn(state, "# asm output \"%s\": %s", constraint, show_pseudo(pseudo));
+ string = "undef";
+ switch (*constraint) {
+ case 'r':
+ default:
+ string = target_reg(state, pseudo, NULL)->name;
+ break;
+ }
+
+ output_insn(state, "# asm output \"%s\": %s : %s", constraint, show_pseudo(pseudo), string);
+
+ arg->name = entry->ident;
+ arg->value = string;
+ arg++;
} END_FOR_EACH_PTR(entry);
+ return arg;
}
static void generate_asm(struct bb_state *state, struct instruction *insn)
{
- generate_asm_inputs(state, insn->asm_rules->inputs);
- output_insn(state, "ASM: %s", insn->string);
- generate_asm_outputs(state, insn->asm_rules->outputs);
+ const char *str = insn->string;
+
+ if (insn->asm_rules->outputs || insn->asm_rules->inputs) {
+ static struct asm_arg args[MAX_ASM_ARG];
+ struct asm_arg *arg;
+
+ arg = generate_asm_outputs(state, insn->asm_rules->outputs, args);
+ arg = generate_asm_inputs(state, insn->asm_rules->inputs, arg);
+ str = replace_asm_args(str, args, arg - args);
+ }
+ output_insn(state, "%s", str);
}
static void generate_compare(struct bb_state *state, struct instruction *insn)