bevarargs.c 2.12 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"

Matthias Braun's avatar
Matthias Braun committed
21 22
void be_default_lower_va_arg(ir_node *const node, bool const compound_is_ptr,
                             unsigned const stack_param_align)
23 24 25 26 27
{
	ir_node  *block = get_nodes_block(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_graph *irg   = get_irn_irg(node);

28
	ir_type       *aptype   = get_method_res_type(get_Builtin_type(node), 0);
29 30 31 32 33 34
	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;
35 36 37 38
	if (apmode) {
		goto load;
	} else if (compound_is_ptr) {
		apmode = mode_P;
39
		aptype = get_type_for_mode(apmode);
40
load:;
41
		ir_node *const load = new_rd_Load(dbgi, block, node_mem, ap, apmode, aptype, cons_none);
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
42
		res     = new_r_Proj(load, apmode, pn_Load_res);
43 44
		new_mem = new_r_Proj(load, mode_M,pn_Load_M);
	} else {
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
45 46
		/* aptype has no associated mode, so it is represented as a pointer. */
		res     = ap;
47 48 49
		new_mem = node_mem;
	}

50
	unsigned const round_up    = round_up2(get_type_size(aptype),
Matthias Braun's avatar
Matthias Braun committed
51
	                                       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
ir_entity *be_make_va_start_entity(ir_type *const frame_type, int const offset)
{
	ident     *const id       = new_id_from_str("$va_start");
	ir_type   *const unknown  = get_unknown_type();
	ir_entity *const va_start = new_entity(frame_type, id, unknown);
	set_entity_offset(va_start, offset);
	return va_start;
}
68 69 70 71 72

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