Commit 6751e3ac authored by Matthias Braun's avatar Matthias Braun
Browse files

lower_dw: Nasty hack to mark lowered paramters

This is necessary as the arm backend needs special calling conventions
(only even register numbers) in these cases.
parent 2e97a73d
...@@ -59,6 +59,18 @@ calling_convention_t *arm_decide_calling_convention(const ir_graph *irg, ...@@ -59,6 +59,18 @@ calling_convention_t *arm_decide_calling_convention(const ir_graph *irg,
reg_or_stackslot_t *param = &params[i]; reg_or_stackslot_t *param = &params[i];
param->type = param_type; param->type = param_type;
/* doubleword modes need to be passed in even registers */
if (param_type->flags & tf_lowered_dw) {
if (regnum < n_param_regs) {
if ((regnum & 1) != 0)
++regnum;
} else {
unsigned misalign = stack_offset % 8;
if (misalign > 0)
stack_offset += 8 - misalign;
}
}
if (regnum < n_param_regs) { if (regnum < n_param_regs) {
const arch_register_t *reg = param_regs[regnum]; const arch_register_t *reg = param_regs[regnum];
param->reg0 = reg; param->reg0 = reg;
......
...@@ -14,32 +14,33 @@ ...@@ -14,32 +14,33 @@
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
#include "array.h"
#include "be.h" #include "be.h"
#include "panic.h"
#include "lowering.h"
#include "irnode_t.h"
#include "irnodeset.h"
#include "irgraph_t.h"
#include "irmode_t.h"
#include "iropt_t.h"
#include "irgmod.h"
#include "tv_t.h"
#include "dbginfo_t.h" #include "dbginfo_t.h"
#include "iropt_dbg.h" #include "debug.h"
#include "irflag_t.h"
#include "firmstat.h" #include "firmstat.h"
#include "irgwalk.h"
#include "ircons_t.h" #include "ircons_t.h"
#include "irdump.h"
#include "irflag.h" #include "irflag.h"
#include "irflag_t.h"
#include "irgmod.h"
#include "irgraph_t.h"
#include "irgwalk.h"
#include "irmode_t.h"
#include "irnodeset.h"
#include "irnode_t.h"
#include "iropt_dbg.h"
#include "iroptimize.h" #include "iroptimize.h"
#include "debug.h" #include "iropt_t.h"
#include "irprog_t.h" #include "irprog_t.h"
#include "set.h"
#include "pmap.h"
#include "pdeq.h"
#include "irdump.h"
#include "array.h"
#include "lower_dw.h" #include "lower_dw.h"
#include "lowering.h"
#include "panic.h"
#include "pdeq.h"
#include "pmap.h"
#include "set.h"
#include "tv_t.h"
#include "type_t.h"
/** A map from (op, imode, omode) to Intrinsic functions entities. */ /** A map from (op, imode, omode) to Intrinsic functions entities. */
static set *intrinsic_fkt; static set *intrinsic_fkt;
...@@ -55,7 +56,14 @@ static pmap *lowered_builtin_type_high; ...@@ -55,7 +56,14 @@ static pmap *lowered_builtin_type_high;
static pmap *lowered_builtin_type_low; static pmap *lowered_builtin_type_low;
/** The types for the binop and unop intrinsics. */ /** The types for the binop and unop intrinsics. */
static ir_type *binop_tp_u, *binop_tp_s, *unop_tp_u, *unop_tp_s, *tp_s, *tp_u; static ir_type *binop_tp_u;
static ir_type *binop_tp_s;
static ir_type *unop_tp_u;
static ir_type *unop_tp_s;
static ir_type *tp_s;
static ir_type *tp_u;
static ir_type *tp_l_s;
static ir_type *tp_l_u;
static ir_nodeset_t created_mux_nodes; static ir_nodeset_t created_mux_nodes;
...@@ -147,14 +155,14 @@ static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode) ...@@ -147,14 +155,14 @@ static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode)
if (needs_lowering(imode)) { if (needs_lowering(imode)) {
if (mode_is_signed(imode)) { if (mode_is_signed(imode)) {
if (env.p.big_endian) { if (env.p.big_endian) {
set_method_param_type(mtd, n_param++, tp_s); set_method_param_type(mtd, n_param++, tp_l_s);
set_method_param_type(mtd, n_param++, tp_u); set_method_param_type(mtd, n_param++, tp_u);
} else { } else {
set_method_param_type(mtd, n_param++, tp_u); set_method_param_type(mtd, n_param++, tp_l_u);
set_method_param_type(mtd, n_param++, tp_s); set_method_param_type(mtd, n_param++, tp_s);
} }
} else { } else {
set_method_param_type(mtd, n_param++, tp_u); set_method_param_type(mtd, n_param++, tp_l_u);
set_method_param_type(mtd, n_param++, tp_u); set_method_param_type(mtd, n_param++, tp_u);
} }
} else { } else {
...@@ -166,14 +174,14 @@ static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode) ...@@ -166,14 +174,14 @@ static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode)
if (needs_lowering(omode)) { if (needs_lowering(omode)) {
if (mode_is_signed(omode)) { if (mode_is_signed(omode)) {
if (env.p.big_endian) { if (env.p.big_endian) {
set_method_res_type(mtd, n_res++, tp_s); set_method_res_type(mtd, n_res++, tp_l_s);
set_method_res_type(mtd, n_res++, tp_u); set_method_res_type(mtd, n_res++, tp_u);
} else { } else {
set_method_res_type(mtd, n_res++, tp_u); set_method_res_type(mtd, n_res++, tp_l_u);
set_method_res_type(mtd, n_res++, tp_s); set_method_res_type(mtd, n_res++, tp_s);
} }
} else { } else {
set_method_res_type(mtd, n_res++, tp_u); set_method_res_type(mtd, n_res++, tp_l_u);
set_method_res_type(mtd, n_res++, tp_u); set_method_res_type(mtd, n_res++, tp_u);
} }
} else { } else {
...@@ -1679,14 +1687,14 @@ static ir_type *lower_mtp(ir_type *mtp) ...@@ -1679,14 +1687,14 @@ static ir_type *lower_mtp(ir_type *mtp)
if (needs_lowering(mode)) { if (needs_lowering(mode)) {
if (mode_is_signed(mode)) { if (mode_is_signed(mode)) {
if (env.p.big_endian) { if (env.p.big_endian) {
set_method_param_type(res, n_param++, tp_s); set_method_param_type(res, n_param++, tp_l_s);
set_method_param_type(res, n_param++, tp_u); set_method_param_type(res, n_param++, tp_u);
} else { } else {
set_method_param_type(res, n_param++, tp_u); set_method_param_type(res, n_param++, tp_l_u);
set_method_param_type(res, n_param++, tp_s); set_method_param_type(res, n_param++, tp_s);
} }
} else { } else {
set_method_param_type(res, n_param++, tp_u); set_method_param_type(res, n_param++, tp_l_u);
set_method_param_type(res, n_param++, tp_u); set_method_param_type(res, n_param++, tp_u);
} }
continue; continue;
...@@ -1702,14 +1710,14 @@ static ir_type *lower_mtp(ir_type *mtp) ...@@ -1702,14 +1710,14 @@ static ir_type *lower_mtp(ir_type *mtp)
if (needs_lowering(mode)) { if (needs_lowering(mode)) {
if (mode_is_signed(mode)) { if (mode_is_signed(mode)) {
if (env.p.big_endian) { if (env.p.big_endian) {
set_method_res_type(res, n_res++, tp_s); set_method_res_type(res, n_res++, tp_l_s);
set_method_res_type(res, n_res++, tp_u); set_method_res_type(res, n_res++, tp_u);
} else { } else {
set_method_res_type(res, n_res++, tp_u); set_method_res_type(res, n_res++, tp_l_u);
set_method_res_type(res, n_res++, tp_s); set_method_res_type(res, n_res++, tp_s);
} }
} else { } else {
set_method_res_type(res, n_res++, tp_u); set_method_res_type(res, n_res++, tp_l_u);
set_method_res_type(res, n_res++, tp_u); set_method_res_type(res, n_res++, tp_u);
} }
continue; continue;
...@@ -2801,48 +2809,52 @@ void ir_lower_dw_ops(void) ...@@ -2801,48 +2809,52 @@ void ir_lower_dw_ops(void)
lowered_builtin_type_high = pmap_create(); lowered_builtin_type_high = pmap_create();
tp_u = get_type_for_mode(env.p.word_unsigned); tp_u = get_type_for_mode(env.p.word_unsigned);
tp_s = get_type_for_mode(env.p.word_signed); tp_s = get_type_for_mode(env.p.word_signed);
tp_l_u = new_type_primitive(env.p.word_unsigned);
tp_l_u->flags |= tf_lowered_dw;
tp_l_s = new_type_primitive(env.p.word_signed);
tp_l_s->flags |= tf_lowered_dw;
binop_tp_u = new_type_method(4, 2); binop_tp_u = new_type_method(4, 2);
set_method_param_type(binop_tp_u, 0, tp_u); set_method_param_type(binop_tp_u, 0, tp_l_u);
set_method_param_type(binop_tp_u, 1, tp_u); set_method_param_type(binop_tp_u, 1, tp_u);
set_method_param_type(binop_tp_u, 2, tp_u); set_method_param_type(binop_tp_u, 2, tp_l_u);
set_method_param_type(binop_tp_u, 3, tp_u); set_method_param_type(binop_tp_u, 3, tp_u);
set_method_res_type(binop_tp_u, 0, tp_u); set_method_res_type(binop_tp_u, 0, tp_l_u);
set_method_res_type(binop_tp_u, 1, tp_u); set_method_res_type(binop_tp_u, 1, tp_u);
binop_tp_s = new_type_method(4, 2); binop_tp_s = new_type_method(4, 2);
if (env.p.big_endian) { if (env.p.big_endian) {
set_method_param_type(binop_tp_s, 0, tp_s); set_method_param_type(binop_tp_s, 0, tp_l_s);
set_method_param_type(binop_tp_s, 1, tp_u); set_method_param_type(binop_tp_s, 1, tp_u);
set_method_param_type(binop_tp_s, 2, tp_s); set_method_param_type(binop_tp_s, 2, tp_l_s);
set_method_param_type(binop_tp_s, 3, tp_u); set_method_param_type(binop_tp_s, 3, tp_u);
set_method_res_type(binop_tp_s, 0, tp_s); set_method_res_type(binop_tp_s, 0, tp_l_s);
set_method_res_type(binop_tp_s, 1, tp_u); set_method_res_type(binop_tp_s, 1, tp_u);
} else { } else {
set_method_param_type(binop_tp_s, 0, tp_u); set_method_param_type(binop_tp_s, 0, tp_l_u);
set_method_param_type(binop_tp_s, 1, tp_s); set_method_param_type(binop_tp_s, 1, tp_s);
set_method_param_type(binop_tp_s, 2, tp_u); set_method_param_type(binop_tp_s, 2, tp_l_u);
set_method_param_type(binop_tp_s, 3, tp_s); set_method_param_type(binop_tp_s, 3, tp_s);
set_method_res_type(binop_tp_s, 0, tp_u); set_method_res_type(binop_tp_s, 0, tp_l_u);
set_method_res_type(binop_tp_s, 1, tp_s); set_method_res_type(binop_tp_s, 1, tp_s);
} }
unop_tp_u = new_type_method(2, 2); unop_tp_u = new_type_method(2, 2);
set_method_param_type(unop_tp_u, 0, tp_u); set_method_param_type(unop_tp_u, 0, tp_l_u);
set_method_param_type(unop_tp_u, 1, tp_u); set_method_param_type(unop_tp_u, 1, tp_u);
set_method_res_type(unop_tp_u, 0, tp_u); set_method_res_type(unop_tp_u, 0, tp_l_u);
set_method_res_type(unop_tp_u, 1, tp_u); set_method_res_type(unop_tp_u, 1, tp_u);
unop_tp_s = new_type_method(2, 2); unop_tp_s = new_type_method(2, 2);
if (env.p.big_endian) { if (env.p.big_endian) {
set_method_param_type(unop_tp_s, 0, tp_s); set_method_param_type(unop_tp_s, 0, tp_l_s);
set_method_param_type(unop_tp_s, 1, tp_u); set_method_param_type(unop_tp_s, 1, tp_u);
set_method_res_type(unop_tp_s, 0, tp_s); set_method_res_type(unop_tp_s, 0, tp_l_s);
set_method_res_type(unop_tp_s, 1, tp_u); set_method_res_type(unop_tp_s, 1, tp_u);
} else { } else {
set_method_param_type(unop_tp_s, 0, tp_u); set_method_param_type(unop_tp_s, 0, tp_l_u);
set_method_param_type(unop_tp_s, 1, tp_s); set_method_param_type(unop_tp_s, 1, tp_s);
set_method_res_type(unop_tp_s, 0, tp_u); set_method_res_type(unop_tp_s, 0, tp_l_u);
set_method_res_type(unop_tp_s, 1, tp_s); set_method_res_type(unop_tp_s, 1, tp_s);
} }
} }
......
...@@ -108,7 +108,8 @@ typedef enum type_flags { ...@@ -108,7 +108,8 @@ typedef enum type_flags {
tf_global_type = 1U << 4, /**< Set only for the global type */ tf_global_type = 1U << 4, /**< Set only for the global type */
tf_tls_type = 1U << 5, /**< Set only for the tls type */ tf_tls_type = 1U << 5, /**< Set only for the tls type */
tf_info = 1U << 6, /**< infos (for example constructor, destructor pointers) */ tf_info = 1U << 6, /**< infos (for example constructor, destructor pointers) */
tf_variable_size = 1U << 8, /**< compound or array type may have variable size last element */ tf_variable_size = 1U << 7, /**< compound or array type may have variable size last element */
tf_lowered_dw = 1U << 8, /**< hack to identify lowered doubleword params */
} type_flags; } type_flags;
ENUM_BITSET(type_flags) ENUM_BITSET(type_flags)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment