bevarargs.c 2.05 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
 * This file is part of libFirm.
 * Copyright (C) 2012 University of Karlsruhe.
 */

/**
 * @file
 * @brief   Default (pointer-based) implementation of variadic functions
 * @author  Andreas Fried
 */

#include "bevarargs.h"

#include "be.h"
#include "bitfiddle.h"
#include "ircons.h"
#include "irgmod.h"
18
#include "irnode_t.h"
19
20
#include "util.h"

21
static void be_default_lower_va_arg(ir_node *const node, bool const compound_is_ptr)
22
23
24
25
26
{
	ir_node  *block = get_nodes_block(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_graph *irg   = get_irn_irg(node);

27
	ir_type       *aptype   = get_method_res_type(get_Builtin_type(node), 0);
28
29
30
31
32
33
	ir_node *const ap       = get_irn_n(node, 1);
	ir_node *const node_mem = get_Builtin_mem(node);

	ir_mode *apmode = get_type_mode(aptype);
	ir_node *res;
	ir_node *new_mem;
34
35
36
37
	if (apmode) {
		goto load;
	} else if (compound_is_ptr) {
		apmode = mode_P;
38
		aptype = get_type_for_mode(apmode);
39
load:;
40
		ir_node *const load = new_rd_Load(dbgi, block, node_mem, ap, apmode, aptype, cons_none);
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
41
		res     = new_r_Proj(load, apmode, pn_Load_res);
42
43
		new_mem = new_r_Proj(load, mode_M,pn_Load_M);
	} else {
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
44
45
		/* aptype has no associated mode, so it is represented as a pointer. */
		res     = ap;
46
47
48
		new_mem = node_mem;
	}

49
	backend_params const *const be_params = be_get_backend_param();
50
51
	unsigned const round_up    = round_up2(get_type_size(aptype),
	                                       be_params->stack_param_align);
52
53
	ir_mode *const offset_mode = get_reference_offset_mode(mode_P);
	ir_node *const offset      = new_r_Const_long(irg, offset_mode, round_up);
54
	ir_node *const new_ap      = new_rd_Add(dbgi, block, ap, offset);
55
56
57
58

	ir_node *const in[] = { new_mem, res, new_ap };
	turn_into_tuple(node, ARRAY_SIZE(in), in);
}
59
60
61
62
63
64
65
66
67
68

void be_default_lower_va_arg_compound_ptr(ir_node *const node)
{
	be_default_lower_va_arg(node, true);
}

void be_default_lower_va_arg_compound_val(ir_node *const node)
{
	be_default_lower_va_arg(node, false);
}
69
70
71
72
73

void be_set_va_list_type_pointer(backend_params *const p)
{
	p->vararg.va_list_type = new_type_pointer(get_type_for_mode(mode_ANY));
}