summaryrefslogtreecommitdiffhomepage
path: root/ir/be/riscv
diff options
context:
space:
mode:
authorJohannes Bucher <johannes.bucher2@student.kit.edu>2019-05-07 18:11:03 +0200
committerJohannes Bucher <johannes.bucher2@student.kit.edu>2019-06-11 16:34:58 +0200
commit98db20e910bc82cc593520d800aab16f16cf4aeb (patch)
tree86091bf19e55110100962f6676a55f7031df01a6 /ir/be/riscv
parentb7ae14237ed251a098b68e855eb1018a4664f4aa (diff)
riscv: support Alloc nodes
Introduced riscv backend nodes SubSP and SubSPimm for stack allocations
Diffstat (limited to 'ir/be/riscv')
-rw-r--r--ir/be/riscv/riscv_bearch.c8
-rw-r--r--ir/be/riscv/riscv_bearch_t.h3
-rw-r--r--ir/be/riscv/riscv_emitter.c17
-rw-r--r--ir/be/riscv/riscv_new_nodes.c4
-rw-r--r--ir/be/riscv/riscv_new_nodes_t.h3
-rw-r--r--ir/be/riscv/riscv_spec.pl16
-rw-r--r--ir/be/riscv/riscv_transform.c42
7 files changed, 89 insertions, 4 deletions
diff --git a/ir/be/riscv/riscv_bearch.c b/ir/be/riscv/riscv_bearch.c
index 7b489a7..ee422cf 100644
--- a/ir/be/riscv/riscv_bearch.c
+++ b/ir/be/riscv/riscv_bearch.c
@@ -22,6 +22,7 @@
#include "irgwalk.h"
#include "irprog_t.h"
#include "lower_builtins.h"
+#include "lower_alloc.h"
#include "lowering.h"
#include "riscv_emitter.h"
#include "riscv_lower64.h"
@@ -265,7 +266,7 @@ static void riscv_generate_code(FILE *const output, char const *const cup_name)
riscv_introduce_prologue_epilogue(irg);
be_fix_stack_nodes(irg, &riscv_registers[REG_SP]);
birg->non_ssa_regs = NULL;
- be_sim_stack_pointer(irg, 0, 3, &riscv_sp_sim);
+ be_sim_stack_pointer(irg, 0, RISCV_PO2_STACK_ALIGNMENT, &riscv_sp_sim);
riscv_finish_graph(irg);
be_handle_2addr(irg, NULL);
@@ -300,6 +301,11 @@ static void riscv_lower_for_target(void)
riscv_lower64();
be_after_irp_transform("lower-64");
+
+ foreach_irp_irg(i, irg) {
+ lower_alloc(irg, RISCV_PO2_STACK_ALIGNMENT);
+ be_after_transform(irg, "lower-alloc");
+ }
}
static unsigned riscv_get_op_estimated_cost(ir_node const *const node)
diff --git a/ir/be/riscv/riscv_bearch_t.h b/ir/be/riscv/riscv_bearch_t.h
index 7ce4c20..62b01f0 100644
--- a/ir/be/riscv/riscv_bearch_t.h
+++ b/ir/be/riscv/riscv_bearch_t.h
@@ -7,6 +7,7 @@
#define FIRM_BE_RISCV_RISCV_BEARCH_T_H
#define RISCV_MACHINE_SIZE 32
+#define RISCV_PO2_STACK_ALIGNMENT 4
#include <stdbool.h>
#include <stdint.h>
@@ -20,7 +21,7 @@ static inline bool is_uimm5(long const val)
static inline bool is_simm12(long const val)
{
- return -2048 <= val && val < 2048;
+ return -2048 <= (int32_t)val && (int32_t)val < 2048;
}
typedef struct riscv_hi_lo_imm {
diff --git a/ir/be/riscv/riscv_emitter.c b/ir/be/riscv/riscv_emitter.c
index 2059fc1..b794f57 100644
--- a/ir/be/riscv/riscv_emitter.c
+++ b/ir/be/riscv/riscv_emitter.c
@@ -250,6 +250,21 @@ static void emit_riscv_FrameAddr(const ir_node *node)
riscv_emitf(node, "addi\t%D0, %S0, %d", (int)offset);
}
+static void emit_riscv_SubSP(ir_node const *const node)
+{
+ riscv_emitf(node, "sub\t%D0, %S1, %S2");
+ riscv_emitf(node, "mv\t%D1, %S1");
+}
+
+static void emit_riscv_SubSPimm(ir_node const *const node)
+{
+ const riscv_immediate_attr_t *attr = get_riscv_immediate_attr_const(node);
+ int32_t val = attr->val;
+ assert(is_simm12((long)val));
+ riscv_emitf(node, "addi\t%D0, %S1, %d", (int)val);
+ riscv_emitf(node, "mv\t%D1, %S1");
+}
+
static void riscv_register_emitters(void)
{
be_init_emitters();
@@ -262,6 +277,8 @@ static void riscv_register_emitters(void)
be_set_emitter(op_riscv_FrameAddr, emit_riscv_FrameAddr);
be_set_emitter(op_riscv_bcc, emit_riscv_bcc);
be_set_emitter(op_riscv_j, emit_riscv_j);
+ be_set_emitter(op_riscv_SubSP, emit_riscv_SubSP);
+ be_set_emitter(op_riscv_SubSPimm, emit_riscv_SubSPimm);
be_set_emitter(op_riscv_switch, emit_riscv_switch);
}
diff --git a/ir/be/riscv/riscv_new_nodes.c b/ir/be/riscv/riscv_new_nodes.c
index 94f6e9d..0930dc9 100644
--- a/ir/be/riscv/riscv_new_nodes.c
+++ b/ir/be/riscv/riscv_new_nodes.c
@@ -5,8 +5,6 @@
#include "riscv_new_nodes_t.h"
-#include <inttypes.h>
-
#include "gen_riscv_new_nodes.h"
#include "riscv_nodes_attr.h"
@@ -143,6 +141,8 @@ void riscv_dump_node(FILE *const F, ir_node const *const n, dump_reason_t const
case iro_riscv_sra:
case iro_riscv_srl:
case iro_riscv_sub:
+ case iro_riscv_SubSP:
+ case iro_riscv_SubSPimm:
case iro_riscv_switch:
case iro_riscv_xor:
break;
diff --git a/ir/be/riscv/riscv_new_nodes_t.h b/ir/be/riscv/riscv_new_nodes_t.h
index a520224..8df67d6 100644
--- a/ir/be/riscv/riscv_new_nodes_t.h
+++ b/ir/be/riscv/riscv_new_nodes_t.h
@@ -11,6 +11,7 @@
#define FIRM_BE_RISCV_RISCV_NEW_NODES_T_H
#include <stdio.h>
+#include <inttypes.h>
#include "firm_types.h"
#include "irop.h"
@@ -22,4 +23,6 @@ int riscv_immediate_attrs_equal(ir_node const *a, ir_node const *b);
int riscv_cond_attrs_equal(ir_node const *a, ir_node const *b);
int riscv_switch_attrs_equal(ir_node const *a, ir_node const *b);
+void riscv_set_attr_imm(ir_node *res, ir_entity *entity, int32_t immediate_value);
+
#endif
diff --git a/ir/be/riscv/riscv_spec.pl b/ir/be/riscv/riscv_spec.pl
index b36af18..1a0ff7d 100644
--- a/ir/be/riscv/riscv_spec.pl
+++ b/ir/be/riscv/riscv_spec.pl
@@ -247,4 +247,20 @@ FrameAddr => {
attr_type => "riscv_immediate_attr_t",
},
+SubSP => {
+ in_reqs => [ "mem", "sp", "cls-gp" ],
+ ins => [ "mem", "stack", "size" ],
+ out_reqs => [ "sp:I", "cls-gp", "mem" ],
+ outs => [ "stack", "addr", "M" ],
+},
+
+SubSPimm => {
+ in_reqs => [ "mem", "sp" ],
+ ins => [ "mem", "stack" ],
+ out_reqs => [ "sp:I", "cls-gp", "mem" ],
+ outs => [ "stack", "addr", "M" ],
+ attr_type => "riscv_immediate_attr_t",
+ attr => "ir_entity *ent, int32_t val",
+},
+
);
diff --git a/ir/be/riscv/riscv_transform.c b/ir/be/riscv/riscv_transform.c
index 8f30c9c..2d4a843 100644
--- a/ir/be/riscv/riscv_transform.c
+++ b/ir/be/riscv/riscv_transform.c
@@ -296,6 +296,46 @@ static ir_node *gen_Address(ir_node *const node)
return make_address(node, ent, 0);
}
+static ir_node *gen_Alloc(ir_node *node)
+{
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *new_block = be_transform_nodes_block(node);
+ ir_node *size = get_Alloc_size(node);
+ ir_graph *irg = get_irn_irg(node);
+ ir_node *stack_pred = be_get_Start_proj(irg, &riscv_registers[REG_SP]);
+ ir_node *mem = get_Alloc_mem(node);
+ ir_node *new_mem = be_transform_node(mem);
+
+ ir_node *subsp;
+ if (is_Const(size)) {
+ long const sizel = get_Const_long(size);
+ assert((sizel & ((1<<RISCV_PO2_STACK_ALIGNMENT) - 1)) == 0 && "Found Alloc with misaligned constant");
+ assert(is_simm12(sizel));
+ subsp = new_bd_riscv_SubSPimm(dbgi, new_block, new_mem, stack_pred, NULL, sizel);
+ } else {
+ ir_node *new_size = be_transform_node(size);
+ subsp = new_bd_riscv_SubSP(dbgi, new_block, new_mem, stack_pred, new_size);
+ }
+
+ ir_node *const stack_proj = be_new_Proj_reg(subsp, pn_riscv_SubSP_stack, &riscv_registers[REG_SP]);
+ be_stack_record_chain(&stack_env, subsp, n_riscv_SubSP_stack, stack_proj);
+
+ return subsp;
+}
+
+static ir_node *gen_Proj_Alloc(ir_node *node)
+{
+ ir_node *alloc = get_Proj_pred(node);
+ ir_node *new_alloc = be_transform_node(alloc);
+ unsigned pn = get_Proj_num(node);
+
+ switch ((pn_Alloc)pn) {
+ case pn_Alloc_M: return be_new_Proj(new_alloc, pn_riscv_SubSP_M);
+ case pn_Alloc_res: return be_new_Proj(new_alloc, pn_riscv_SubSP_addr);
+ }
+ panic("invalid Proj->Alloc");
+}
+
typedef ir_node *cons_binop(dbg_info*, ir_node*, ir_node*, ir_node*);
typedef ir_node *cons_binop_imm(dbg_info*, ir_node*, ir_node*, ir_entity*, int32_t);
@@ -1121,6 +1161,7 @@ static void riscv_register_transformers(void)
be_set_transform_function(op_ASM, gen_ASM);
be_set_transform_function(op_Add, gen_Add);
be_set_transform_function(op_Address, gen_Address);
+ be_set_transform_function(op_Alloc, gen_Alloc);
be_set_transform_function(op_And, gen_And);
be_set_transform_function(op_Builtin, gen_Builtin);
be_set_transform_function(op_Call, gen_Call);
@@ -1152,6 +1193,7 @@ static void riscv_register_transformers(void)
be_set_transform_function(op_Switch, gen_Switch);
be_set_transform_function(op_Unknown, gen_Unknown);
+ be_set_transform_proj_function(op_Alloc, gen_Proj_Alloc);
be_set_transform_proj_function(op_Builtin, gen_Proj_Builtin);
be_set_transform_proj_function(op_Call, gen_Proj_Call);
be_set_transform_proj_function(op_Div, gen_Proj_Div);