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:
- Support ASM node
- fail on long double
- (Support 80bit long double with x87 instructions)
- Finish PIC code implementation. gen_Address / call with immediate should be
fine. However the address mode matcher must not treat GOTPCREL things as
addresses, we have to load from the GOT first. The easiest solution is
probably a preparation phase similar to ia32_pic.c that create loads.
- Finish PIC code implementation. This is mostly done now, usual accesses to
functions and variables including address mode matching looks fine now.
Jumptables are not accessed correctly in PIC yet and
Improve Quality:
- Immediate32 matching could be better and match SymConst, Add(SymConst, Const)
combinations where possible. Be careful with PIC code this may usually not
be legal!
combinations where possible.
- Support Destination Address Mode
- Match Immediate + Address mode for Cmp
- 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,
if
(
is_fp_relative
(
entity
))
{
entity
=
NULL
;
/* only emit offset for frame entities */
}
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)
return
entity
;
}
typedef
enum
reference_mode_t
{
REFERENCE_DIRECT
,
REFERENCE_IP_RELATIVE
,
REFERENCE_GOT
,
}
reference_mode_t
;
static
reference_mode_t
need_relative_addressing
(
const
ir_entity
*
entity
)
{
if
(
!
be_options
.
pic
)
return
REFERENCE_DIRECT
;
/* 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
void
init_lconst_addr
(
amd64_addr_t
*
addr
,
ir_entity
*
entity
)
{
assert
(
entity_has_definition
(
entity
));
assert
(
get_entity_linkage
(
entity
)
==
IR_LINKAGE_CONSTANT
);
assert
(
get_entity_visibility
(
entity
)
==
ir_visibility_private
);
memset
(
addr
,
0
,
sizeof
(
*
addr
));
x86_immediate_kind_t
kind
=
be_options
.
pic
?
X86_IMM_PCREL
:
X86_IMM_ADDR
;
addr
->
immediate
.
entity
=
entity
;
addr
->
immediate
.
kind
=
kind
;
addr
->
index_input
=
NO_INPUT
;
addr
->
base_input
=
kind
==
X86_IMM_PCREL
?
RIP_INPUT
:
NO_INPUT
;
}
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
};
amd64_addr_t
addr
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
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
;
}
init_lconst_addr
(
&
addr
,
entity
);
ir_node
*
load
;
unsigned
pn_res
;
amd64_insn_mode_t
insn_mode
=
get_insn_mode_from_mode
(
tv_mode
);
if
(
insn_mode
==
INSN_MODE_128
)
{
load
=
new_bd_amd64_movdqa
(
dbgi
,
block
,
ARRAY_SIZE
(
in
),
in
,
AMD64_OP_ADDR
,
addr
);
...
...
@@ -403,40 +388,45 @@ static ir_node *gen_Address(ir_node *node)
dbg_info
*
dbgi
=
get_irn_dbg_info
(
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
=
{
.
kind
=
X86_IMM_ADDR
,
.
entity
=
entity
,
};
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
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
addr
.
base_input
=
RIP_INPUT
;
addr
.
index_input
=
NO_INPUT
;
addr
.
mem_input
=
NO_INPUT
;
if
(
mode
==
REFERENCE_IP_RELATIVE
)
{
addr
.
immediate
=
(
x86_imm32_t
)
{
/* TODO: create an ip-relative kind? (even though it looks the same
* in the assembler) */
.
kind
=
X86_IMM_ADDR
,
.
kind
=
kind
,
.
entity
=
entity
,
};
return
new_bd_amd64_lea
(
dbgi
,
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
);
return
new_bd_amd64_lea
(
NULL
,
block
,
0
,
NULL
,
INSN_MODE_64
,
addr
);
}
default:
break
;
}
panic
(
"Unexpected relocation kind"
);
}
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,
x86_immediate_kind_t
kind
=
(
x86_immediate_kind_t
)
reloc_kind
;
if
(
entity
!=
NULL
)
{
if
(
!
can_match_ip_relative
)
{
/* TODO: check if entity is in lower 4GB address space/relative */
if
(
!
can_match_ip_relative
)
return
false
;
if
(
kind
==
X86_IMM_VALUE
||
kind
==
X86_IMM_ADDR
)
{
kind
=
X86_IMM_PCREL
;
}
else
if
(
kind
!=
X86_IMM_PCREL
)
return
false
;
}
if
(
kind
==
X86_IMM_VALUE
)
kind
=
X86_IMM_ADDR
;
}
imm
->
entity
=
entity
;
...
...
@@ -637,13 +627,7 @@ static void perform_address_matching(ir_node *ptr, int *arity,
addr
->
base_input
=
base_input
;
in
[
base_input
]
=
be_transform_node
(
maddr
.
base
);
}
else
{
ir_entity
*
entity
=
maddr
.
imm
.
entity
;
if
(
entity
!=
NULL
&&
need_relative_addressing
(
entity
)
!=
REFERENCE_DIRECT
)
{
addr
->
base_input
=
RIP_INPUT
;
}
else
{
addr
->
base_input
=
NO_INPUT
;
}
addr
->
base_input
=
maddr
.
ip_base
?
RIP_INPUT
:
NO_INPUT
;
}
if
(
maddr
.
index
!=
NULL
)
{
int
index_input
=
(
*
arity
)
++
;
...
...
@@ -2643,8 +2627,9 @@ static void amd64_register_transformers(void)
be_set_transform_function
(
op_Switch
,
gen_Switch
);
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_subpd
,
gen_amd64_l_subpd
);
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_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)
*/
static
void
amd64_select_instructions
(
ir_graph
*
irg
)
{
amd64_adjust_pic
(
irg
);
be_timer_push
(
T_CODEGEN
);
amd64_transform_graph
(
irg
);
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,
void
amd64_cconv_init
(
void
);
void
amd64_adjust_pic
(
ir_graph
*
irg
);
#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