summaryrefslogtreecommitdiffhomepage
path: root/ir/lower/lower_calls.h
blob: 6d5b5b7a84744e4c0829d4a0a857c138150b40bf (plain)
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 * This file is part of libFirm.
 * Copyright (C) 2012 University of Karlsruhe.
 */

/**
 * @file
 * @brief   Lowering of calls with compound arguments
 * @author  Michael Beck
 */
#ifndef FIRM_LOWER_CALLS_H
#define FIRM_LOWER_CALLS_H

#include <stdbool.h>

#include "firm_types.h"

/*
 * Note: This API is designed with future support for ARM and MIPS in
 * mind. Their calling conventions require two further features:
 *
 * - Passing part of a struct in registers and part in memory.
 *
 * - Passing dynamically-sized objects via pointers, but
 *   statically-sized objects directly on stack.
 */

/**
 * The maximum number of registers used to split up an aggregate type
 * across all ABIs.
 */
#define MAX_REGS_PER_AGGREGATE 2

/**
 * Additional flags for the lowering.
 */
typedef enum compound_call_lowering_flags {
	LF_NONE                 = 0,      /**< no additional flags */
	LF_RETURN_HIDDEN        = 1 << 0, /**< return the hidden address instead of void */
} compound_call_lowering_flags;
ENUM_BITSET(compound_call_lowering_flags)

/**
 * Specifies how an argument or result should be passed. Each argument
 * or result may be split into multiple values, which will become
 * registers in the backend. The array 'modes' holds the mode of each
 * of these values. Two modes have a special meaning. If these are
 * used, they must be the only element of the array.
 *
 * mode_M: The lowering phase does not change the function's type, and
 * provides the argument as-is. The backend is responsible for
 * managing the actual stack. mode_M may not be used for return
 * values.
 *
 * mode_P: The argument or return value should be copied into
 * temporary memory by the caller, and a pointer to this temporary
 * memory should be passed in its stead.
 *
 * When mode_P is used for a return value, the pointer to the
 * temporary memory is transmitted as a hidden first argument, and
 * also returned from the function is LF_RETURN_HIDDEN is set.
 *
 * 'length' holds the number of values or special modes used for the
 * argument or result.
 */
typedef struct aggregate_spec_t {
	unsigned  length;
	ir_mode  *modes[MAX_REGS_PER_AGGREGATE];
} aggregate_spec_t;

/**
 * Callback to decide how the specified type should be passed to or
 * returned by a function. env points to a piece of backend-specific
 * data, which is the env argument of lower_calls_with_compounds for
 * the first callback, and may be updated by the callback.
 *
 * In order to support stateful ABIs, which need to know about every
 * parameter, this function is also called for non-compound types. It
 * should then return an aggregate_spec_t with length = 1 and
 * modes[0] = get_type_mode(type).
 */
typedef aggregate_spec_t (*lower_call_func)(void *env, ir_type const *type);

/**
 * Callback to reset the state of the ABI for the next function.
 */
typedef void (*reset_abi_state_func)(void *param_env, void *result_env);

/**
 * Lower calls with compound parameter and return types.
 * This function does the following transformations:
 *
 * - Transform compound results according to the aggregate_spec_t
 *   returned from the backend. If necessary, insert a hidden
 *   parameter.
 *
 * - Transform compound parameters according to the
 *   aggregate_spec_t returned from the backend.
 *
 * - Use of the hidden parameters in the function code.
 *
 * - Change all calls to functions with compound return
 *   by providing space for the hidden parameter on the callers
 *   stack.
 *
 * - Replace a possible block copy after the function call.
 *
 * General:
 *
 * - Changes the types of methods and calls to the lowered ones
 *
 * - lower all method types of existing entities
 */
void lower_calls_with_compounds(compound_call_lowering_flags flags,
                                lower_call_func lower_parameter,
                                void *lower_parameter_env,
                                lower_call_func lower_return,
                                void *lower_return_env,
                                reset_abi_state_func reset_state);

/**
 * Lower aggregate types by replacing them with a pointer to the
 * actual data. The caller allocates space for this data in its
 * frame. This is firm's old default behaviour. This implements the
 * SPARC ABI.
 *
 * This function can be used as a provisional ABI for unfinished
 * backends. However, these backends will only be able to link to
 * other code produced by firm.
 *
 * This function is stateless and does not require an environment (you
 * may pass NULL).
 */
aggregate_spec_t lower_aggregates_as_pointers(void *env, ir_type const *type);

/**
 * Do not lower aggregate types. This may only be used to lower
 * parameters, return values must always be lowered. When using this
 * function, the call lowering does not change aggregate parameters,
 * and the backend is responsible for correctly handling them.
 *
 * This function is stateless and does not require an environment (you
 * may pass NULL).
 */
aggregate_spec_t dont_lower_aggregates(void *env, ir_type const *type);

/**
 * This function may be passed as the reset_state argument for a
 * stateless ABI. It ignores its arguments.
 */
void reset_stateless_abi(void *param_env, void *result_env);

#endif