Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
bb1e3f1e
Commit
bb1e3f1e
authored
Sep 07, 2015
by
Matthias Braun
Browse files
begnuas/i32: properly emit jump tables in PIC mode
parent
aba0611e
Changes
10
Show whitespace changes
Inline
Side-by-side
ir/be/amd64/amd64_emitter.c
View file @
bb1e3f1e
...
...
@@ -712,13 +712,24 @@ static void emit_amd64_jmp(const ir_node *node)
}
}
static
void
emit_jumptable_target
(
ir_entity
const
*
const
table
,
ir_node
const
*
const
proj_x
)
{
ir_node
const
*
const
block
=
get_cfop_target_block
(
proj_x
);
be_gas_emit_block_name
(
block
);
if
(
be_options
.
pic
)
{
be_emit_char
(
'-'
);
be_gas_emit_entity
(
table
);
}
}
static
void
emit_amd64_jmp_switch
(
const
ir_node
*
node
)
{
const
amd64_switch_jmp_attr_t
*
attr
=
get_amd64_switch_jmp_attr_const
(
node
);
amd64_emitf
(
node
,
"jmp *%E(,%^S0,8)"
,
attr
->
table_entity
);
be_emit_jump_table
(
node
,
attr
->
table
,
attr
->
table_entity
,
get_cfop
_target
_block
);
emit_jumptable
_target
);
}
/**
...
...
ir/be/arm/arm_emitter.c
View file @
bb1e3f1e
...
...
@@ -489,12 +489,19 @@ static void emit_arm_B(const ir_node *irn)
}
}
static
void
emit_jumptable_target
(
ir_entity
const
*
const
table
,
ir_node
const
*
const
proj_x
)
{
(
void
)
table
;
arm_emit_cfop_target
(
proj_x
);
}
static
void
emit_arm_SwitchJmp
(
const
ir_node
*
irn
)
{
const
arm_SwitchJmp_attr_t
*
attr
=
get_arm_SwitchJmp_attr_const
(
irn
);
arm_emitf
(
irn
,
"ldrls pc, [pc, %S0, asl #2]"
);
be_emit_jump_table
(
irn
,
attr
->
table
,
NULL
,
get_cfop
_target
_block
);
be_emit_jump_table
(
irn
,
attr
->
table
,
NULL
,
emit_jumptable
_target
);
}
/** Emit an IncSP node */
...
...
ir/be/begnuas.c
View file @
bb1e3f1e
...
...
@@ -1504,7 +1504,8 @@ static void emit_global_decls(const be_main_env_t *main_env)
}
void
be_emit_jump_table
(
const
ir_node
*
node
,
const
ir_switch_table
*
table
,
ir_entity
*
entity
,
get_cfop_target_func
get_cfop_target
)
ir_entity
const
*
const
entity
,
emit_target_func
emit_target
)
{
/* go over all proj's and collect their jump targets */
unsigned
n_outs
=
arch_get_irn_n_outs
(
node
);
...
...
@@ -1512,9 +1513,7 @@ void be_emit_jump_table(const ir_node *node, const ir_switch_table *table,
foreach_out_edge
(
node
,
edge
)
{
ir_node
*
proj
=
get_edge_src_irn
(
edge
);
unsigned
pn
=
get_Proj_num
(
proj
);
ir_node
*
target
=
get_cfop_target
(
proj
);
assert
(
targets
[
pn
]
==
NULL
);
targets
[
pn
]
=
target
;
targets
[
pn
]
=
proj
;
}
/* go over table to determine max value (note that we normalized the
...
...
@@ -1580,11 +1579,11 @@ void be_emit_jump_table(const ir_node *node, const ir_switch_table *table,
}
for
(
unsigned
long
i
=
0
;
i
<
length
;
++
i
)
{
const
ir_node
*
block
=
labels
[
i
];
if
(
block
==
NULL
)
block
=
targets
[
0
];
const
ir_node
*
target
=
labels
[
i
];
if
(
target
==
NULL
)
target
=
targets
[
0
];
emit_size_type
(
pointer_size
);
be_gas_emit_block_name
(
block
);
emit_target
(
entity
,
target
);
be_emit_char
(
'\n'
);
be_emit_write_line
();
}
...
...
ir/be/begnuas.h
View file @
bb1e3f1e
...
...
@@ -123,14 +123,14 @@ void be_gas_end_compilation_unit(const be_main_env_t *env);
*/
const
char
*
be_gas_insn_label_prefix
(
void
);
typedef
ir_node
*
(
*
get_cfop_target_func
)(
const
ir_node
*
cfop
);
typedef
void
(
*
emit_target_func
)(
ir_entity
const
*
table
,
ir_node
const
*
proj_x
);
/**
* Emits a jump table for switch operations
*/
void
be_emit_jump_table
(
const
ir_node
*
node
,
const
ir_switch_table
*
table
,
ir_entity
*
entity
,
get_cfop
_target_func
get_cfop_target
);
ir_entity
const
*
entity
,
emit
_target_func
get_cfop_target
);
bool
be_gas_produces_dwarf_line_info
(
void
);
...
...
ir/be/ia32/ia32_emitter.c
View file @
bb1e3f1e
...
...
@@ -874,16 +874,30 @@ static void emit_ia32_Setcc(const ir_node *node)
}
}
static
void
emit_jumptable_target
(
ir_entity
const
*
const
table
,
ir_node
const
*
const
proj_x
)
{
(
void
)
table
;
ir_node
const
*
const
block
=
get_cfop_target_block
(
proj_x
);
be_gas_emit_block_name
(
block
);
if
(
ia32_pic_style
==
IA32_PIC_ELF_PLT
||
ia32_pic_style
==
IA32_PIC_ELF_NO_PLT
)
{
be_emit_cstring
(
"@GOTOFF"
);
}
else
if
(
ia32_pic_style
==
IA32_PIC_MACH_O
)
{
be_emit_char
(
'-'
);
be_emit_string
(
pic_base_label
);
}
}
/**
* Emits code for a SwitchJmp
*/
static
void
emit_ia32_SwitchJmp
(
const
ir_node
*
node
)
{
ir_entity
*
jump_table
=
get_ia32_am_ent
(
node
);
const
ir_switch_table
*
table
=
get_ia32_switch_table
(
node
);
ia32_emitf
(
node
,
"jmp %*AM"
);
be_emit_jump_table
(
node
,
table
,
jump_table
,
get_cfop_target_block
);
ia32_switch_attr_t
const
*
const
attr
=
get_ia32_switch_attr_const
(
node
);
ia32_emitf
(
node
,
"jmp %*AS0"
);
be_emit_jump_table
(
node
,
attr
->
table
,
attr
->
table_entity
,
emit_jumptable_target
);
}
/**
...
...
@@ -2702,7 +2716,7 @@ static void bemit_switchjmp(const ir_node *node)
bemit8
(
0xFF
);
// jmp *tbl.label(,%in,4)
bemit_mod_am
(
0x05
,
node
);
be_emit_jump_table
(
node
,
table
,
jump_table
,
get_cfop
_target
_block
);
be_emit_jump_table
(
node
,
table
,
jump_table
,
emit_jumptable
_target
);
}
static
void
bemit_return
(
const
ir_node
*
node
)
...
...
ir/be/ia32/ia32_new_nodes.c
View file @
bb1e3f1e
...
...
@@ -735,13 +735,15 @@ static void init_ia32_climbframe_attributes(ir_node *res, unsigned count)
}
static
void
init_ia32_switch_attributes
(
ir_node
*
node
,
const
ir_switch_table
*
table
)
ir_switch_table
const
*
const
table
,
ir_entity
const
*
const
table_entity
)
{
ia32_switch_attr_t
*
attr
=
(
ia32_switch_attr_t
*
)
get_irn_generic_attr
(
node
);
#ifndef NDEBUG
attr
->
attr
.
attr_type
|=
IA32_ATTR_ia32_switch_attr_t
;
#endif
attr
->
table
=
table
;
attr
->
table_entity
=
table_entity
;
be_foreach_out
(
node
,
o
)
{
arch_set_irn_register_req_out
(
node
,
o
,
arch_exec_req
);
...
...
@@ -849,7 +851,7 @@ static int ia32_switch_attrs_equal(const ir_node *a, const ir_node *b)
const
ia32_switch_attr_t
*
attr_b
=
get_ia32_switch_attr_const
(
b
);
return
ia32_attrs_equal_
(
&
attr_a
->
attr
,
&
attr_b
->
attr
)
&&
attr_a
->
table
==
attr_b
->
table
&&
attr_a
->
jump_table
==
attr_b
->
jump_table
;
&&
attr_a
->
table_entity
==
attr_b
->
table_entity
;
}
static
int
ia32_return_attrs_equal
(
const
ir_node
*
a
,
const
ir_node
*
b
)
...
...
ir/be/ia32/ia32_nodes_attr.h
View file @
bb1e3f1e
...
...
@@ -147,7 +147,7 @@ typedef struct ia32_switch_attr_t ia32_switch_attr_t;
struct
ia32_switch_attr_t
{
ia32_attr_t
attr
;
/**< generic attribute */
const
ir_switch_table
*
table
;
ir_entity
*
jump_
table
;
const
ir_entity
*
table
_entity
;
};
/**
...
...
ir/be/ia32/ia32_spec.pl
View file @
bb1e3f1e
...
...
@@ -100,7 +100,7 @@ $custom_init_attr_func = \&ia32_custom_init_attr;
"
\t
init_ia32_condcode_attributes(res, condition_code);
",
ia32_switch_attr_t
=>
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_switch_attributes(res, switch_table);
",
"
\t
init_ia32_switch_attributes(res, switch_table
, table_entity
);
",
ia32_copyb_attr_t
=>
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_copyb_attributes(res, size);
",
...
...
@@ -821,7 +821,7 @@ SwitchJmp => {
ins
=>
[
"
base
",
"
index
"
],
out_reqs
=>
"
...
",
attr_type
=>
"
ia32_switch_attr_t
",
attr
=>
"
const ir_switch_table *switch_table
",
attr
=>
"
const ir_switch_table *switch_table
, const ir_entity *table_entity
",
latency
=>
2
,
},
...
...
ir/be/ia32/ia32_transform.c
View file @
bb1e3f1e
...
...
@@ -2941,14 +2941,47 @@ static ir_node *gen_Switch(ir_node *node)
ir_node
*
const
block
=
be_transform_nodes_block
(
node
);
ir_node
*
const
base
=
get_global_base
(
irg
);
unsigned
const
n_outs
=
get_Switch_n_outs
(
node
);
ir_node
*
const
new_node
=
new_bd_ia32_SwitchJmp
(
dbgi
,
block
,
base
,
new_sel
,
n_outs
,
table
);
set_ia32_am_scale
(
new_node
,
2
);
set_ia32_op_type
(
new_node
,
ia32_AddrModeS
);
set_ia32_ls_mode
(
new_node
,
ia32_mode_gp
);
SET_IA32_ORIG_NODE
(
new_node
,
node
);
set_am_const_entity
(
new_node
,
entity
);
return
new_node
;
ir_node
*
switchjmp
;
ir_node
*
table_am
;
ir_node
*
target
;
switch
(
ia32_pic_style
)
{
case
IA32_PIC_NONE
:
switchjmp
=
new_bd_ia32_SwitchJmp
(
dbgi
,
block
,
base
,
new_sel
,
n_outs
,
table
,
entity
);
table_am
=
switchjmp
;
goto
finish
;
case
IA32_PIC_ELF_PLT
:
case
IA32_PIC_ELF_NO_PLT
:
{
ir_node
*
const
load
=
new_bd_ia32_Load
(
dbgi
,
block
,
base
,
new_sel
,
nomem
);
table_am
=
load
;
ir_node
*
const
load_res
=
be_new_Proj
(
load
,
pn_ia32_Load_res
);
target
=
new_bd_ia32_Lea
(
dbgi
,
block
,
base
,
load_res
);
goto
simple_jmp
;
}
case
IA32_PIC_MACH_O
:
{
target
=
new_bd_ia32_Add
(
dbgi
,
block
,
base
,
new_sel
,
nomem
,
base
,
noreg_GP
);
set_ia32_commutative
(
target
);
table_am
=
target
;
simple_jmp:
switchjmp
=
new_bd_ia32_SwitchJmp
(
dbgi
,
block
,
target
,
noreg_GP
,
n_outs
,
table
,
entity
);
set_ia32_op_type
(
switchjmp
,
ia32_Normal
);
set_ia32_ls_mode
(
switchjmp
,
ia32_mode_gp
);
goto
finish
;
}
}
panic
(
"invalid PIC style"
);
finish:
set_ia32_am_scale
(
table_am
,
2
);
set_ia32_op_type
(
table_am
,
ia32_AddrModeS
);
set_ia32_ls_mode
(
table_am
,
ia32_mode_gp
);
set_am_const_entity
(
table_am
,
entity
);
SET_IA32_ORIG_NODE
(
switchjmp
,
node
);
return
switchjmp
;
}
/**
...
...
ir/be/sparc/sparc_emitter.c
View file @
bb1e3f1e
...
...
@@ -1267,6 +1267,13 @@ static void emit_sparc_Ba(const ir_node *node)
}
}
static
void
emit_jumptable_target
(
ir_entity
const
*
const
table
,
ir_node
const
*
const
proj_x
)
{
(
void
)
table
;
sparc_emit_cfop_target
(
proj_x
);
}
static
void
emit_sparc_SwitchJmp
(
const
ir_node
*
node
)
{
const
sparc_switch_jmp_attr_t
*
attr
=
get_sparc_switch_jmp_attr_const
(
node
);
...
...
@@ -1274,7 +1281,8 @@ static void emit_sparc_SwitchJmp(const ir_node *node)
sparc_emitf
(
node
,
"jmp %S0"
);
fill_delay_slot
(
node
);
be_emit_jump_table
(
node
,
attr
->
table
,
attr
->
table_entity
,
get_jump_target
);
be_emit_jump_table
(
node
,
attr
->
table
,
attr
->
table_entity
,
emit_jumptable_target
);
}
static
void
emit_fmov
(
const
ir_node
*
node
,
const
arch_register_t
*
src_reg
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment