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
37ee70a9
Commit
37ee70a9
authored
Jul 27, 2015
by
Matthias Braun
Browse files
amd64: Redo PIC handling, introduce pic prep phase
parent
48563c75
Changes
6
Show whitespace changes
Inline
Side-by-side
ir/be/amd64/TODO
View file @
37ee70a9
...
@@ -13,15 +13,13 @@ Correctness:
...
@@ -13,15 +13,13 @@ Correctness:
- Support ASM node
- Support ASM node
- fail on long double
- fail on long double
- (Support 80bit long double with x87 instructions)
- (Support 80bit long double with x87 instructions)
- Finish PIC code implementation. gen_Address / call with immediate should be
- Finish PIC code implementation. This is mostly done now, usual accesses to
fine. However the address mode matcher must not treat GOTPCREL things as
functions and variables including address mode matching looks fine now.
addresses, we have to load from the GOT first. The easiest solution is
Jumptables are not accessed correctly in PIC yet and
probably a preparation phase similar to ia32_pic.c that create loads.
Improve Quality:
Improve Quality:
- Immediate32 matching could be better and match SymConst, Add(SymConst, Const)
- Immediate32 matching could be better and match SymConst, Add(SymConst, Const)
combinations where possible. Be careful with PIC code this may usually not
combinations where possible.
be legal!
- Support Destination Address Mode
- Support Destination Address Mode
- Match Immediate + Address mode for Cmp
- Match Immediate + Address mode for Cmp
- Support Read-Modify-Store operations (aka destination address mode)
- Support Read-Modify-Store operations (aka destination address mode)
...
...
ir/be/amd64/amd64_emitter.c
View file @
37ee70a9
...
@@ -263,7 +263,7 @@ static void amd64_emit_addr(const ir_node *const node,
...
@@ -263,7 +263,7 @@ static void amd64_emit_addr(const ir_node *const node,
if
(
is_fp_relative
(
entity
))
{
if
(
is_fp_relative
(
entity
))
{
entity
=
NULL
;
/* only emit offset for frame entities */
entity
=
NULL
;
/* only emit offset for frame entities */
}
else
{
}
else
{
be_gas_emit_entity
(
entity
);
emit_relocation_no_offset
(
addr
->
immediate
.
kind
,
entity
);
}
}
}
}
...
...
ir/be/amd64/amd64_pic.c
0 → 100644
View file @
37ee70a9
/*
* This file is part of libFirm.
* Copyright (C) 2015 Matthias Braun
*/
/**
* @file
* @brief position independent code adjustments
* @author Matthias Braun
*/
#include "bearch_amd64_t.h"
#include "be_t.h"
#include "beutil.h"
#include "entity_t.h"
#include "amd64_new_nodes.h"
#include "ircons_t.h"
#include "irgwalk.h"
#include "irnode_t.h"
#include "x86_imm.h"
static
void
fix_address_pic
(
ir_node
*
const
node
,
void
*
const
data
)
{
(
void
)
data
;
foreach_irn_in
(
node
,
i
,
pred
)
{
if
(
!
is_Address
(
pred
))
continue
;
ir_entity
*
const
entity
=
get_Address_entity
(
pred
);
if
(
is_tls_entity
(
entity
))
continue
;
ir_graph
*
const
irg
=
get_irn_irg
(
node
);
ir_node
*
res
;
if
(
i
==
n_Call_ptr
&&
is_Call
(
node
))
{
// Somehow we can always call PC relative. Are there trampolines
// involved?
res
=
be_new_Relocation
(
irg
,
X86_IMM_PCREL
,
entity
);
}
else
if
(
entity_has_definition
(
entity
)
&&
!
(
get_entity_linkage
(
entity
)
&
IR_LINKAGE_MERGE
))
{
res
=
be_new_Relocation
(
irg
,
X86_IMM_PCREL
,
entity
);
}
else
{
ir_node
*
const
addr
=
be_new_Relocation
(
irg
,
X86_IMM_GOTPCREL
,
entity
);
ir_type
*
const
type
=
get_entity_type
(
entity
);
ir_node
*
const
nomem
=
get_irg_no_mem
(
irg
);
ir_node
*
const
block
=
get_irg_start_block
(
irg
);
ir_node
*
const
load
=
new_rd_Load
(
NULL
,
block
,
nomem
,
addr
,
mode_P
,
type
,
cons_floats
);
res
=
new_r_Proj
(
load
,
mode_P
,
pn_Load_res
);
}
set_irn_n
(
node
,
i
,
res
);
}
}
void
amd64_adjust_pic
(
ir_graph
*
irg
)
{
if
(
!
be_options
.
pic
)
return
;
irg_walk_graph
(
irg
,
fix_address_pic
,
NULL
,
NULL
);
be_dump
(
DUMP_BE
,
irg
,
"pic"
);
}
ir/be/amd64/amd64_transform.c
View file @
37ee70a9
...
@@ -303,22 +303,17 @@ ir_entity *create_float_const_entity(ir_tarval *const tv)
...
@@ -303,22 +303,17 @@ ir_entity *create_float_const_entity(ir_tarval *const tv)
return
entity
;
return
entity
;
}
}
typedef
enum
reference_mode_t
{
static
void
init_lconst_addr
(
amd64_addr_t
*
addr
,
ir_entity
*
entity
)
REFERENCE_DIRECT
,
{
REFERENCE_IP_RELATIVE
,
assert
(
entity_has_definition
(
entity
));
REFERENCE_GOT
,
assert
(
get_entity_linkage
(
entity
)
==
IR_LINKAGE_CONSTANT
);
}
reference_mode_t
;
assert
(
get_entity_visibility
(
entity
)
==
ir_visibility_private
);
memset
(
addr
,
0
,
sizeof
(
*
addr
));
static
reference_mode_t
need_relative_addressing
(
const
ir_entity
*
entity
)
x86_immediate_kind_t
kind
=
be_options
.
pic
?
X86_IMM_PCREL
:
X86_IMM_ADDR
;
{
addr
->
immediate
.
entity
=
entity
;
if
(
!
be_options
.
pic
)
addr
->
immediate
.
kind
=
kind
;
return
REFERENCE_DIRECT
;
addr
->
index_input
=
NO_INPUT
;
addr
->
base_input
=
kind
==
X86_IMM_PCREL
?
RIP_INPUT
:
NO_INPUT
;
/* simply everything is instruction pointer relative, external functions
* use a global offset table */
return
entity_has_definition
(
entity
)
&&
(
get_entity_linkage
(
entity
)
&
IR_LINKAGE_MERGE
)
==
0
?
REFERENCE_IP_RELATIVE
:
REFERENCE_GOT
;
}
}
static
ir_node
*
create_float_const
(
dbg_info
*
dbgi
,
ir_node
*
block
,
static
ir_node
*
create_float_const
(
dbg_info
*
dbgi
,
ir_node
*
block
,
...
@@ -331,21 +326,11 @@ static ir_node *create_float_const(dbg_info *dbgi, ir_node *block,
...
@@ -331,21 +326,11 @@ static ir_node *create_float_const(dbg_info *dbgi, ir_node *block,
ir_node
*
in
[]
=
{
nomem
};
ir_node
*
in
[]
=
{
nomem
};
amd64_addr_t
addr
;
amd64_addr_t
addr
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
init_lconst_addr
(
&
addr
,
entity
);
addr
.
immediate
.
entity
=
entity
;
amd64_insn_mode_t
insn_mode
=
get_insn_mode_from_mode
(
tv_mode
);
addr
.
index_input
=
NO_INPUT
;
if
(
need_relative_addressing
(
entity
)
==
REFERENCE_DIRECT
)
{
addr
.
base_input
=
NO_INPUT
;
}
else
{
assert
(
need_relative_addressing
(
entity
)
==
REFERENCE_IP_RELATIVE
);
addr
.
base_input
=
RIP_INPUT
;
}
ir_node
*
load
;
ir_node
*
load
;
unsigned
pn_res
;
unsigned
pn_res
;
amd64_insn_mode_t
insn_mode
=
get_insn_mode_from_mode
(
tv_mode
);
if
(
insn_mode
==
INSN_MODE_128
)
{
if
(
insn_mode
==
INSN_MODE_128
)
{
load
=
new_bd_amd64_movdqa
(
dbgi
,
block
,
ARRAY_SIZE
(
in
),
in
,
load
=
new_bd_amd64_movdqa
(
dbgi
,
block
,
ARRAY_SIZE
(
in
),
in
,
AMD64_OP_ADDR
,
addr
);
AMD64_OP_ADDR
,
addr
);
...
@@ -403,40 +388,45 @@ static ir_node *gen_Address(ir_node *node)
...
@@ -403,40 +388,45 @@ static ir_node *gen_Address(ir_node *node)
dbg_info
*
dbgi
=
get_irn_dbg_info
(
node
);
dbg_info
*
dbgi
=
get_irn_dbg_info
(
node
);
ir_entity
*
entity
=
get_Address_entity
(
node
);
ir_entity
*
entity
=
get_Address_entity
(
node
);
/* do we need RIP-relative addressing because of PIC? */
reference_mode_t
mode
=
need_relative_addressing
(
entity
);
if
(
mode
==
REFERENCE_DIRECT
)
{
amd64_imm64_t
const
imm
=
{
amd64_imm64_t
const
imm
=
{
.
kind
=
X86_IMM_ADDR
,
.
kind
=
X86_IMM_ADDR
,
.
entity
=
entity
,
.
entity
=
entity
,
};
};
return
new_bd_amd64_mov_imm
(
dbgi
,
block
,
INSN_MODE_64
,
&
imm
);
return
new_bd_amd64_mov_imm
(
dbgi
,
block
,
INSN_MODE_64
,
&
imm
);
}
}
static
ir_node
*
gen_be_Relocation
(
ir_node
*
node
)
{
ir_node
*
const
block
=
be_transform_nodes_block
(
node
);
ir_entity
*
const
entity
=
be_get_Relocation_entity
(
node
);
x86_immediate_kind_t
const
kind
=
(
x86_immediate_kind_t
)
be_get_Relocation_kind
(
node
);
switch
(
kind
)
{
case
X86_IMM_ADDR
:
{
amd64_imm64_t
const
imm
=
{
.
kind
=
X86_IMM_ADDR
,
.
entity
=
entity
,
};
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
;
amd64_addr_t
addr
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
memset
(
&
addr
,
0
,
sizeof
(
addr
));
addr
.
base_input
=
RIP_INPUT
;
addr
.
base_input
=
RIP_INPUT
;
addr
.
index_input
=
NO_INPUT
;
addr
.
index_input
=
NO_INPUT
;
addr
.
mem_input
=
NO_INPUT
;
addr
.
mem_input
=
NO_INPUT
;
if
(
mode
==
REFERENCE_IP_RELATIVE
)
{
addr
.
immediate
=
(
x86_imm32_t
)
{
addr
.
immediate
=
(
x86_imm32_t
)
{
/* TODO: create an ip-relative kind? (even though it looks the same
.
kind
=
kind
,
* in the assembler) */
.
kind
=
X86_IMM_ADDR
,
.
entity
=
entity
,
.
entity
=
entity
,
};
};
return
new_bd_amd64_lea
(
dbgi
,
block
,
0
,
NULL
,
INSN_MODE_64
,
addr
);
return
new_bd_amd64_lea
(
NULL
,
block
,
0
,
NULL
,
INSN_MODE_64
,
addr
);
}
else
{
assert
(
mode
==
REFERENCE_GOT
);
addr
.
immediate
=
(
x86_imm32_t
)
{
.
kind
=
X86_IMM_GOTPCREL
,
.
entity
=
entity
,
};
ir_node
*
load
=
new_bd_amd64_mov_gp
(
dbgi
,
block
,
0
,
NULL
,
INSN_MODE_64
,
AMD64_OP_ADDR
,
addr
);
return
be_new_Proj
(
load
,
pn_amd64_mov_gp_res
);
}
}
default:
break
;
}
panic
(
"Unexpected relocation kind"
);
}
}
ir_node
*
amd64_new_IncSP
(
ir_node
*
block
,
ir_node
*
old_sp
,
int
offset
,
ir_node
*
amd64_new_IncSP
(
ir_node
*
block
,
ir_node
*
old_sp
,
int
offset
,
...
@@ -503,12 +493,12 @@ static bool match_immediate_32(x86_imm32_t *imm, const ir_node *op,
...
@@ -503,12 +493,12 @@ static bool match_immediate_32(x86_imm32_t *imm, const ir_node *op,
x86_immediate_kind_t
kind
=
(
x86_immediate_kind_t
)
reloc_kind
;
x86_immediate_kind_t
kind
=
(
x86_immediate_kind_t
)
reloc_kind
;
if
(
entity
!=
NULL
)
{
if
(
entity
!=
NULL
)
{
if
(
!
can_match_ip_relative
)
{
if
(
!
can_match_ip_relative
)
/* TODO: check if entity is in lower 4GB address space/relative */
return
false
;
if
(
kind
==
X86_IMM_VALUE
||
kind
==
X86_IMM_ADDR
)
{
kind
=
X86_IMM_PCREL
;
}
else
if
(
kind
!=
X86_IMM_PCREL
)
return
false
;
return
false
;
}
if
(
kind
==
X86_IMM_VALUE
)
kind
=
X86_IMM_ADDR
;
}
}
imm
->
entity
=
entity
;
imm
->
entity
=
entity
;
...
@@ -637,13 +627,7 @@ static void perform_address_matching(ir_node *ptr, int *arity,
...
@@ -637,13 +627,7 @@ static void perform_address_matching(ir_node *ptr, int *arity,
addr
->
base_input
=
base_input
;
addr
->
base_input
=
base_input
;
in
[
base_input
]
=
be_transform_node
(
maddr
.
base
);
in
[
base_input
]
=
be_transform_node
(
maddr
.
base
);
}
else
{
}
else
{
ir_entity
*
entity
=
maddr
.
imm
.
entity
;
addr
->
base_input
=
maddr
.
ip_base
?
RIP_INPUT
:
NO_INPUT
;
if
(
entity
!=
NULL
&&
need_relative_addressing
(
entity
)
!=
REFERENCE_DIRECT
)
{
addr
->
base_input
=
RIP_INPUT
;
}
else
{
addr
->
base_input
=
NO_INPUT
;
}
}
}
if
(
maddr
.
index
!=
NULL
)
{
if
(
maddr
.
index
!=
NULL
)
{
int
index_input
=
(
*
arity
)
++
;
int
index_input
=
(
*
arity
)
++
;
...
@@ -2643,8 +2627,9 @@ static void amd64_register_transformers(void)
...
@@ -2643,8 +2627,9 @@ static void amd64_register_transformers(void)
be_set_transform_function
(
op_Switch
,
gen_Switch
);
be_set_transform_function
(
op_Switch
,
gen_Switch
);
be_set_transform_function
(
op_Unknown
,
gen_Unknown
);
be_set_transform_function
(
op_Unknown
,
gen_Unknown
);
be_set_transform_function
(
op_amd64_l_punpckldq
,
gen_amd64_l_punpckldq
);
be_set_transform_function
(
op_amd64_l_punpckldq
,
gen_amd64_l_punpckldq
);
be_set_transform_function
(
op_amd64_l_subpd
,
gen_amd64_l_subpd
);
be_set_transform_function
(
op_amd64_l_haddpd
,
gen_amd64_l_haddpd
);
be_set_transform_function
(
op_amd64_l_haddpd
,
gen_amd64_l_haddpd
);
be_set_transform_function
(
op_amd64_l_subpd
,
gen_amd64_l_subpd
);
be_set_transform_function
(
op_be_Relocation
,
gen_be_Relocation
);
be_set_transform_proj_function
(
op_Alloc
,
gen_Proj_Alloc
);
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_Builtin
,
gen_Proj_Builtin
);
...
...
ir/be/amd64/bearch_amd64.c
View file @
37ee70a9
...
@@ -497,6 +497,8 @@ static int determine_rbp_input(ir_node *ret)
...
@@ -497,6 +497,8 @@ static int determine_rbp_input(ir_node *ret)
*/
*/
static
void
amd64_select_instructions
(
ir_graph
*
irg
)
static
void
amd64_select_instructions
(
ir_graph
*
irg
)
{
{
amd64_adjust_pic
(
irg
);
be_timer_push
(
T_CODEGEN
);
be_timer_push
(
T_CODEGEN
);
amd64_transform_graph
(
irg
);
amd64_transform_graph
(
irg
);
be_timer_pop
(
T_CODEGEN
);
be_timer_pop
(
T_CODEGEN
);
...
...
ir/be/amd64/bearch_amd64_t.h
View file @
37ee70a9
...
@@ -37,4 +37,6 @@ x86_cconv_t *amd64_decide_calling_convention(ir_type *function_type,
...
@@ -37,4 +37,6 @@ x86_cconv_t *amd64_decide_calling_convention(ir_type *function_type,
void
amd64_cconv_init
(
void
);
void
amd64_cconv_init
(
void
);
void
amd64_adjust_pic
(
ir_graph
*
irg
);
#endif
#endif
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