amd64_pic.c 1.62 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
 * 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");
}