summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChristoph Mallon <christoph.mallon@gmx.de>2019-04-05 21:05:57 +0200
committerChristoph Mallon <christoph.mallon@gmx.de>2019-04-05 21:05:57 +0200
commitb5566dd4d9b3b16cf4e757feb12343b72e4b9ef1 (patch)
treed7836558a01caa9e77a3de3bcf4018e20e81ff4e
parent15f358575deb58dea6bbf8aa66e70cb1b86d20ee (diff)
parent3ec27c3c9a1e7d3addca3d7c0d7723e24765d3ec (diff)
Merge branch 'asm_goto'.HEADmaster
-rw-r--r--NEWS.md1
m---------libfirm0
-rw-r--r--src/firm/ast2firm.c67
-rw-r--r--src/parser/parser.c2
4 files changed, 57 insertions, 13 deletions
diff --git a/NEWS.md b/NEWS.md
index 613b056..b097862 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -20,6 +20,7 @@ cparser 1.22.1 (2016-01-23)
* Accept asm qualifiers in arbitrary order
* Accept (and ignore) the asm qualifier `inline`
* The target triple can also be set by prefixing the executable name, e.g. `x86_64-unknown-elf-cparser`
+* Support `asm goto`; even allow output constraints, which gcc and clang do not
* Bugfixes
cparser 1.22.0 (2015-12-31)
diff --git a/libfirm b/libfirm
-Subproject 80146aaacf50c17449e07b8aac0000e5267aed5
+Subproject b405d397f43ac08df63dd838152b0301f6c201a
diff --git a/src/firm/ast2firm.c b/src/firm/ast2firm.c
index af67d5a..fdf0063 100644
--- a/src/firm/ast2firm.c
+++ b/src/firm/ast2firm.c
@@ -4540,6 +4540,28 @@ static ir_node *computed_goto_to_firm(computed_goto_statement_t const *const sta
return NULL;
}
+typedef struct out_info {
+ expression_t const *expr;
+ ir_node *addr;
+ ir_node *proj;
+} out_info;
+
+static void asm_make_target(ir_node *const asmn, unsigned const pos)
+{
+ ir_node *const proj = new_Proj(asmn, mode_X, pos);
+ ir_node *const in[] = { proj };
+ ir_node *const block = new_Block(ARRAY_SIZE(in), in);
+ set_cur_block(block);
+}
+
+static void asm_set_values(out_info const *const outs)
+{
+ for (size_t i = 0, n = ARR_LEN(outs); i < n; ++i) {
+ out_info const *const o = &outs[i];
+ set_value_for_expression_addr(o->expr, o->proj, o->addr);
+ }
+}
+
static ir_node *asm_statement_to_firm(const asm_statement_t *statement)
{
if (!currently_reachable())
@@ -4566,11 +4588,6 @@ static ir_node *asm_statement_to_firm(const asm_statement_t *statement)
clobbers = obstack_finish(&asm_obst);
}
- typedef struct out_info {
- expression_t const *expr;
- ir_node *addr;
- } out_info;
-
ir_node **ins = NEW_ARR_F(ir_node*, 0);
out_info *outs = NEW_ARR_F(out_info, 0);
ir_asm_constraint *constraints = NEW_ARR_F(ir_asm_constraint, 0);
@@ -4599,7 +4616,7 @@ static ir_node *asm_statement_to_firm(const asm_statement_t *statement)
constraint.out_pos = pn_ASM_first_out + ARR_LEN(outs);
constraint.mode = get_ir_mode_storage(expr->base.type);
- ARR_APP1(out_info, outs, ((out_info){ expr, addr }));
+ ARR_APP1(out_info, outs, ((out_info){ expr, addr, NULL }));
} else {
/* the only case where an argument doesn't "write" is when it is
* a memor operand (so we really write to the pointed memory instead
@@ -4644,6 +4661,19 @@ static ir_node *asm_statement_to_firm(const asm_statement_t *statement)
ARR_APP1(ir_asm_constraint, constraints, constraint);
}
+ {
+ size_t label_pos = pn_ASM_first_out + ARR_LEN(outs);
+ for (entity_t const *l = statement->labels; l; l = l->base.next) {
+ ir_asm_constraint const c = {
+ .in_pos = -1,
+ .out_pos = label_pos++,
+ .constraint = NULL,
+ .mode = mode_X,
+ };
+ ARR_APP1(ir_asm_constraint, constraints, c);
+ }
+ }
+
ir_node *mem = needs_memory ? get_store() : new_NoMem();
size_t const n_ins = ARR_LEN(ins);
@@ -4652,6 +4682,8 @@ static ir_node *asm_statement_to_firm(const asm_statement_t *statement)
ir_cons_flags flags = cons_none;
if (!statement->is_volatile)
flags |= cons_floats;
+ if (statement->labels)
+ flags |= cons_throws_exception;
/* create asm node */
dbg_info *dbgi = get_dbg_info(&statement->base.pos);
@@ -4666,14 +4698,25 @@ static ir_node *asm_statement_to_firm(const asm_statement_t *statement)
set_store(projm);
}
- for (size_t i = 0, n_outs = ARR_LEN(outs); i < n_outs; ++i) {
- expression_t const *const out_expr = outs[i].expr;
- ir_mode *const mode = get_ir_mode_storage(out_expr->base.type);
- ir_node *const proj = new_Proj(node, mode, pn_ASM_first_out + i);
- ir_node *const addr = outs[i].addr;
- set_value_for_expression_addr(out_expr, proj, addr);
+ unsigned out_pos = pn_ASM_first_out;
+ for (size_t i = 0, n = ARR_LEN(outs); i < n; ++i) {
+ ir_mode *const mode = get_ir_mode_storage(outs[i].expr->base.type);
+ outs[i].proj = new_Proj(node, mode, out_pos++);
}
+ entity_t const *l = statement->labels;
+ if (l) {
+ for (; l; l = l->base.next) {
+ asm_make_target(node, out_pos++);
+ asm_set_values(outs);
+ jump_to_label(l->asm_label.label);
+ }
+
+ asm_make_target(node, pn_ASM_X_regular);
+ }
+
+ asm_set_values(outs);
+
DEL_ARR_F(constraints);
DEL_ARR_F(outs);
DEL_ARR_F(ins);
diff --git a/src/parser/parser.c b/src/parser/parser.c
index 4252a56..37486d9 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -9365,7 +9365,7 @@ check_duplicate:
"assembler statement with labels should be 'asm goto'");
parse_asm_labels(&asm_statement->labels);
if (asm_statement->labels)
- errorf(&statement->base.pos, "'asm goto' not supported");
+ asm_statement->is_volatile = true;
} else if (asm_goto)
warningf(WARN_OTHER, &statement->base.pos,
"'asm goto' without labels");