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
16c12b0e
Commit
16c12b0e
authored
Sep 22, 2015
by
Matthias Braun
Browse files
amd64: Implement switchjmp in PIC, refactoring
parent
6ab03ddc
Changes
9
Hide whitespace changes
Inline
Side-by-side
ir/be/amd64/amd64_emitter.c
View file @
16c12b0e
...
...
@@ -778,8 +778,9 @@ 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
,
amd64_emitf
(
node
,
"jmp %*AM"
);
ir_mode
*
entry_mode
=
be_options
.
pic
?
mode_Iu
:
mode_Lu
;
be_emit_jump_table
(
node
,
attr
->
table
,
attr
->
table_entity
,
entry_mode
,
emit_jumptable_target
);
}
...
...
ir/be/amd64/amd64_nodes_attr.h
View file @
16c12b0e
...
...
@@ -118,7 +118,7 @@ typedef struct {
}
amd64_cc_attr_t
;
typedef
struct
{
amd64_attr_t
base
;
amd64_a
ddr_a
ttr_t
base
;
const
ir_switch_table
*
table
;
ir_entity
*
table_entity
;
}
amd64_switch_jmp_attr_t
;
...
...
ir/be/amd64/amd64_spec.pl
View file @
16c12b0e
...
...
@@ -76,7 +76,9 @@ $mode_x87 = "x86_mode_E";
"
be_info_init_irn(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
*attr = *attr_init;
",
amd64_switch_jmp_attr_t
=>
"
init_amd64_attributes(res, irn_flags, in_reqs, n_res, AMD64_OP_NONE);
\n
"
"
init_amd64_attributes(res, irn_flags, in_reqs, n_res, op_mode);
\n
"
.
"
\t
attr->base.insn_mode = INSN_MODE_64;
\n
"
.
"
\t
attr->base.addr = *addr;
\n
"
.
"
\t
init_amd64_switch_attributes(res, table, table_entity);
",
amd64_cc_attr_t
=>
"
init_amd64_attributes(res, irn_flags, in_reqs, n_res, AMD64_OP_NONE);
\n
"
...
...
@@ -521,10 +523,10 @@ mov_store => {
jmp_switch
=>
{
op_flags
=>
[
"
cfopcode
",
"
forking
"
],
state
=>
"
pinned
",
in_reqs
=>
[
"
gp
"
]
,
in_reqs
=>
"
...
"
,
out_reqs
=>
"
...
",
attr_type
=>
"
amd64_switch_jmp_attr_t
",
attr
=>
"
const ir_switch_table *table, ir_entity *table_entity
",
attr
=>
"
amd64_op_mode_t op_mode, const amd64_addr_t *addr,
const ir_switch_table *table, ir_entity *table_entity
",
},
call
=>
{
...
...
ir/be/amd64/amd64_transform.c
View file @
16c12b0e
...
...
@@ -482,6 +482,22 @@ static ir_node *gen_Address(ir_node *const node)
return
new_bd_amd64_mov_imm
(
dbgi
,
block
,
INSN_MODE_64
,
&
imm
);
}
static
ir_node
*
create_picaddr_lea
(
ir_node
*
const
block
,
x86_immediate_kind_t
const
kind
,
ir_entity
*
const
entity
)
{
amd64_addr_t
addr
=
{
.
immediate
=
(
x86_imm32_t
)
{
.
kind
=
kind
,
.
entity
=
entity
,
},
.
base_input
=
RIP_INPUT
,
.
index_input
=
NO_INPUT
,
.
mem_input
=
NO_INPUT
,
};
return
new_bd_amd64_lea
(
NULL
,
block
,
0
,
NULL
,
NULL
,
INSN_MODE_64
,
addr
);
}
static
ir_node
*
gen_be_Relocation
(
ir_node
*
const
node
)
{
ir_node
*
const
block
=
be_transform_nodes_block
(
node
);
...
...
@@ -498,18 +514,8 @@ static ir_node *gen_be_Relocation(ir_node *const node)
return
new_bd_amd64_mov_imm
(
NULL
,
block
,
INSN_MODE_64
,
&
imm
);
}
case
X86_IMM_PCREL
:
case
X86_IMM_GOTPCREL
:
{
/* can GOTPCREL happen here? */
amd64_addr_t
addr
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
addr
.
base_input
=
RIP_INPUT
;
addr
.
index_input
=
NO_INPUT
;
addr
.
mem_input
=
NO_INPUT
;
addr
.
immediate
=
(
x86_imm32_t
)
{
.
kind
=
kind
,
.
entity
=
entity
,
};
return
new_bd_amd64_lea
(
NULL
,
block
,
0
,
NULL
,
NULL
,
INSN_MODE_64
,
addr
);
}
case
X86_IMM_GOTPCREL
:
/* can GOTPCREL happen here? */
return
create_picaddr_lea
(
block
,
kind
,
entity
);
default:
break
;
}
...
...
@@ -1004,35 +1010,42 @@ static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
return
be_new_Proj
(
new_node
,
pn_res
);
}
static
ir_node
*
create_lea_as_add
(
ir_node
*
node
,
ir_node
*
op1
,
ir_node
*
op2
)
static
ir_node
*
create_add_lea
(
dbg_info
*
dbgi
,
ir_node
*
new_block
,
amd64_insn_mode_t
insn_mode
,
ir_node
*
op1
,
ir_node
*
op2
)
{
dbg_info
*
const
dbgi
=
get_irn_dbg_info
(
node
);
ir_node
*
const
new_block
=
be_transform_nodes_block
(
node
);
ir_mode
*
const
mode
=
get_irn_mode
(
node
);
amd64_insn_mode_t
insn_mode
=
get_mode_size_bits
(
mode
)
<=
32
?
INSN_MODE_32
:
INSN_MODE_64
;
const
arch_register_req_t
**
reqs
;
amd64_addr_t
addr
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
ir_node
*
in
[
2
];
int
arity
=
0
;
ir_node
*
in
[]
=
{
op1
,
op2
};
amd64_addr_t
addr
=
{
.
base_input
=
0
,
.
index_input
=
1
,
};
return
new_bd_amd64_lea
(
dbgi
,
new_block
,
ARRAY_SIZE
(
in
),
in
,
amd64_reg_reg_reqs
,
insn_mode
,
addr
);
}
if
(
match_immediate_32
(
&
addr
.
immediate
,
op2
,
false
,
true
))
{
in
[
arity
++
]
=
be_transform_node
(
op1
);
reqs
=
reg_reqs
;
addr
.
index_input
=
NO_INPUT
;
static
ir_node
*
match_simple_lea
(
dbg_info
*
dbgi
,
ir_node
*
new_block
,
amd64_insn_mode_t
insn_mode
,
ir_node
*
op1
,
ir_node
*
op2
)
{
x86_imm32_t
immediate
;
memset
(
&
immediate
,
0
,
sizeof
(
immediate
));
if
(
match_immediate_32
(
&
immediate
,
op2
,
false
,
true
))
{
ir_node
*
in
[]
=
{
be_transform_node
(
op1
)
};
amd64_addr_t
addr
=
{
.
immediate
=
immediate
,
.
base_input
=
0
,
.
index_input
=
NO_INPUT
,
.
mem_input
=
NO_INPUT
,
};
return
new_bd_amd64_lea
(
dbgi
,
new_block
,
ARRAY_SIZE
(
in
),
in
,
reg_reqs
,
insn_mode
,
addr
);
}
else
{
in
[
arity
++
]
=
be_transform_node
(
op1
);
in
[
arity
++
]
=
be_transform_node
(
op2
);
addr
.
base_input
=
0
;
addr
.
index_input
=
1
;
reqs
=
amd64_reg_reg_reqs
;
ir_node
*
const
new_op1
=
be_transform_node
(
op1
);
ir_node
*
const
new_op2
=
be_transform_node
(
op2
);
return
create_add_lea
(
dbgi
,
new_block
,
insn_mode
,
new_op1
,
new_op2
);
}
return
new_bd_amd64_lea
(
dbgi
,
new_block
,
arity
,
in
,
reqs
,
insn_mode
,
addr
);
}
static
ir_node
*
gen_Add
(
ir_node
*
const
node
)
...
...
@@ -1060,8 +1073,13 @@ static ir_node *gen_Add(ir_node *const node)
if
(
use_am
)
res
=
gen_binop_am
(
node
,
op1
,
op2
,
new_bd_amd64_add
,
pn_amd64_add_res
,
flags
);
else
res
=
create_lea_as_add
(
node
,
op1
,
op2
);
else
{
amd64_insn_mode_t
insn_mode
=
get_mode_size_bits
(
mode
)
<=
32
?
INSN_MODE_32
:
INSN_MODE_64
;
dbg_info
*
const
dbgi
=
get_irn_dbg_info
(
node
);
ir_node
*
const
new_block
=
be_transform_node
(
block
);
res
=
match_simple_lea
(
dbgi
,
new_block
,
insn_mode
,
op1
,
op2
);
}
x86_mark_non_am
(
node
);
return
res
;
...
...
@@ -1511,10 +1529,60 @@ static ir_node *gen_Switch(ir_node *const node)
set_entity_visibility
(
entity
,
ir_visibility_private
);
add_entity_linkage
(
entity
,
IR_LINKAGE_CONSTANT
);
arch_register_req_t
const
**
in_reqs
;
amd64_op_mode_t
op_mode
;
int
arity
=
0
;
ir_node
*
in
[
1
];
amd64_addr_t
addr
;
if
(
be_options
.
pic
)
{
ir_node
*
const
base
=
create_picaddr_lea
(
new_block
,
X86_IMM_PCREL
,
entity
);
ir_node
*
load_in
[
3
];
int
load_arity
=
0
;
int
load_base
=
load_arity
++
;
int
load_index
=
load_arity
++
;
load_in
[
load_base
]
=
base
;
load_in
[
load_index
]
=
new_sel
;
addr
=
(
amd64_addr_t
)
{
.
base_input
=
load_base
,
.
index_input
=
load_index
,
.
mem_input
=
NO_INPUT
,
.
log_scale
=
2
,
};
ir_node
*
const
load
=
new_bd_amd64_movs
(
dbgi
,
new_block
,
load_arity
,
load_in
,
amd64_reg_reg_reqs
,
INSN_MODE_32
,
AMD64_OP_ADDR
,
addr
);
ir_node
*
const
load_res
=
be_new_Proj
(
load
,
pn_amd64_movs_res
);
ir_node
*
const
add
=
create_add_lea
(
dbgi
,
new_block
,
INSN_MODE_64
,
base
,
load_res
);
memset
(
&
addr
,
0
,
sizeof
(
addr
));
op_mode
=
AMD64_OP_REG
;
in
[
arity
++
]
=
add
;
in_reqs
=
reg_reqs
;
}
else
{
int
index_in
=
arity
++
;
in
[
index_in
]
=
new_sel
;
in_reqs
=
reg_reqs
;
addr
=
(
amd64_addr_t
)
{
.
immediate
=
{
.
kind
=
X86_IMM_ADDR
,
.
entity
=
entity
,
},
.
base_input
=
NO_INPUT
,
.
index_input
=
index_in
,
.
log_scale
=
3
,
};
op_mode
=
AMD64_OP_ADDR
;
}
table
=
ir_switch_table_duplicate
(
irg
,
table
);
ir_node
*
const
out
=
new_bd_amd64_jmp_switch
(
dbgi
,
new_block
,
new_sel
,
n_outs
,
table
,
entity
);
ir_node
*
const
out
=
new_bd_amd64_jmp_switch
(
dbgi
,
new_block
,
arity
,
in
,
in_reqs
,
n_outs
,
op_mode
,
&
addr
,
table
,
entity
);
return
out
;
}
...
...
ir/be/arm/arm_emitter.c
View file @
16c12b0e
...
...
@@ -502,7 +502,7 @@ 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
,
emit_jumptable_target
);
be_emit_jump_table
(
irn
,
attr
->
table
,
NULL
,
mode_P
,
emit_jumptable_target
);
}
/** Emit an IncSP node */
...
...
ir/be/begnuas.c
View file @
16c12b0e
...
...
@@ -1515,7 +1515,7 @@ 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
const
*
const
entity
,
ir_entity
const
*
const
entity
,
ir_mode
*
entry_mode
,
emit_target_func
emit_target
)
{
/* go over all proj's and collect their jump targets */
...
...
@@ -1581,9 +1581,10 @@ void be_emit_jump_table(const ir_node *node, const ir_switch_table *table,
}
/* emit table */
unsigned
pointer_size
=
get_mode_size_bytes
(
mode
_P
);
unsigned
pointer_size
=
get_mode_size_bytes
(
entry_
mode
);
if
(
entity
!=
NULL
)
{
be_gas_emit_switch_section
(
GAS_SECTION_RODATA
);
if
(
be_gas_object_file_format
!=
OBJECT_FILE_FORMAT_MACH_O
)
be_gas_emit_switch_section
(
GAS_SECTION_RODATA
);
be_emit_irprintf
(
"
\t
.align %u
\n
"
,
pointer_size
);
be_gas_emit_entity
(
entity
);
be_emit_cstring
(
":
\n
"
);
...
...
@@ -1599,7 +1600,8 @@ void be_emit_jump_table(const ir_node *node, const ir_switch_table *table,
be_emit_write_line
();
}
if
(
entity
!=
NULL
)
if
(
entity
!=
NULL
&&
be_gas_object_file_format
!=
OBJECT_FILE_FORMAT_MACH_O
)
be_gas_emit_switch_section
(
GAS_SECTION_TEXT
);
free
(
labels
);
...
...
ir/be/begnuas.h
View file @
16c12b0e
...
...
@@ -129,7 +129,7 @@ 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
const
*
entity
,
ir_entity
const
*
entity
,
ir_mode
*
entry_mode
,
emit_target_func
get_cfop_target
);
bool
be_gas_produces_dwarf_line_info
(
void
);
...
...
ir/be/ia32/ia32_emitter.c
View file @
16c12b0e
...
...
@@ -896,7 +896,7 @@ static void emit_ia32_SwitchJmp(const ir_node *node)
{
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
,
be_emit_jump_table
(
node
,
attr
->
table
,
attr
->
table_entity
,
mode_P
,
emit_jumptable_target
);
}
...
...
@@ -2714,7 +2714,7 @@ static void bemit_switchjmp(const ir_node *node)
bemit_mod_am
(
0x05
,
node
);
ia32_switch_attr_t
const
*
const
attr
=
get_ia32_switch_attr_const
(
node
);
be_emit_jump_table
(
node
,
attr
->
table
,
attr
->
table_entity
,
be_emit_jump_table
(
node
,
attr
->
table
,
attr
->
table_entity
,
mode_P
,
emit_jumptable_target
);
}
...
...
ir/be/sparc/sparc_emitter.c
View file @
16c12b0e
...
...
@@ -1282,7 +1282,7 @@ 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
,
be_emit_jump_table
(
node
,
attr
->
table
,
attr
->
table_entity
,
mode_P
,
emit_jumptable_target
);
}
...
...
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