summaryrefslogtreecommitdiffstats
path: root/compile.c
diff options
context:
space:
mode:
authorNicolas Williams <nico@cryptonector.com>2014-08-09 20:27:08 -0500
committerNicolas Williams <nico@cryptonector.com>2014-08-09 20:27:08 -0500
commitf87521183f5c499b3c58e016c5936ade14819fd3 (patch)
treee98607208d323cc91189f9e23ab9451420fe68e5 /compile.c
parent8a561120c41969439f786ee133d7d699ee8edd1b (diff)
Fold constant arrays
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/compile.c b/compile.c
index 92c7d2c5..612920c0 100644
--- a/compile.c
+++ b/compile.c
@@ -499,8 +499,70 @@ block gen_both(block a, block b) {
return c;
}
+block gen_const_array(block expr) {
+ /*
+ * An expr of all constant elements looks like this:
+ *
+ * 0009 FORK 0027
+ * 0011 FORK 0023
+ * 0013 FORK 0019
+ * 0015 LOADK 1
+ * 0017 JUMP 0021
+ * 0019 LOADK 2
+ * 0021 JUMP 0025
+ * 0023 LOADK 3
+ * 0025 JUMP 0029
+ * 0027 LOADK 4
+ *
+ * That's: N-1 commas for N elements, N LOADKs, and a JUMP between
+ * every LOADK. The sequence ends in a LOADK. Any deviation and it's
+ * not a list of constants.
+ *
+ * Here we check for this pattern almost exactly. We don't check that
+ * the targets of the FORK and JUMP instructions are in the right
+ * sequence.
+ */
+ int all_const = 1;
+ int commas = 0;
+ int normal = 1;
+ jv a = jv_array();
+ for (inst *i = expr.first; i; i = i->next) {
+ if (i->op == FORK) {
+ commas++;
+ if (i->imm.target == NULL || i->imm.target->op != JUMP ||
+ jv_array_length(jv_copy(a)) > 0) {
+ normal = 0;
+ break;
+ }
+ } else if (all_const && i->op == LOADK) {
+ if (i->next != NULL && i->next->op != JUMP) {
+ normal = 0;
+ break;
+ }
+ a = jv_array_append(a, jv_copy(i->imm.constant));
+ } else if (i->op != JUMP || i->imm.target == NULL ||
+ i->imm.target->op != LOADK) {
+ all_const = 0;
+ }
+ }
+
+ if (all_const && normal &&
+ (expr.last == NULL || expr.last->op == LOADK) &&
+ jv_array_length(jv_copy(a)) == commas + 1) {
+ block_free(expr);
+ return gen_const(a);
+ }
+
+ jv_free(a);
+ block b = {0,0};
+ return b;
+}
block gen_collect(block expr) {
+ block const_array = gen_const_array(expr);
+ if (const_array.first != NULL)
+ return const_array;
+
block array_var = gen_op_var_fresh(STOREV, "collect");
block c = BLOCK(gen_op_simple(DUP), gen_const(jv_array()), array_var);