2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief calling convention helpers
9 * @author Matthias Braun
13 #include "arm_cconv.h"
21 static const unsigned ignore_regs[] = {
28 static const arch_register_t* const param_regs[] = {
29 &arm_registers[REG_R0],
30 &arm_registers[REG_R1],
31 &arm_registers[REG_R2],
32 &arm_registers[REG_R3]
35 static const arch_register_t* const result_regs[] = {
36 &arm_registers[REG_R0],
37 &arm_registers[REG_R1],
38 &arm_registers[REG_R2],
39 &arm_registers[REG_R3]
42 static const arch_register_t* const float_result_regs[] = {
43 &arm_registers[REG_F0],
44 &arm_registers[REG_F1]
47 calling_convention_t *arm_decide_calling_convention(const ir_graph *irg,
48 ir_type *function_type)
50 unsigned stack_offset = 0;
51 unsigned n_param_regs_used = 0;
52 reg_or_stackslot_t *params;
53 reg_or_stackslot_t *results;
54 size_t const n_param_regs = ARRAY_SIZE(param_regs);
55 size_t const n_result_regs = ARRAY_SIZE(result_regs);
56 size_t const n_float_result_regs = ARRAY_SIZE(float_result_regs);
62 calling_convention_t *cconv;
64 /* determine how parameters are passed */
65 n_params = get_method_n_params(function_type);
67 params = XMALLOCNZ(reg_or_stackslot_t, n_params);
69 for (i = 0; i < n_params; ++i) {
70 ir_type *param_type = get_method_param_type(function_type,i);
71 ir_mode *mode = get_type_mode(param_type);
72 int bits = get_mode_size_bits(mode);
73 reg_or_stackslot_t *param = ¶ms[i];
74 param->type = param_type;
76 if (regnum < n_param_regs) {
77 const arch_register_t *reg = param_regs[regnum++];
80 param->offset = stack_offset;
81 /* increase offset 4 bytes so everything is aligned */
82 stack_offset += bits > 32 ? bits/8 : 4;
86 /* we might need a 2nd 32bit component (for 64bit or double values) */
89 panic("only 32 and 64bit modes supported");
91 if (regnum < n_param_regs) {
92 const arch_register_t *reg = param_regs[regnum++];
95 ir_mode *pmode = param_regs[0]->reg_class->mode;
96 ir_type *type = get_type_for_mode(pmode);
98 param->offset = stack_offset;
99 assert(get_mode_size_bits(pmode) == 32);
104 n_param_regs_used = regnum;
106 n_results = get_method_n_ress(function_type);
109 results = XMALLOCNZ(reg_or_stackslot_t, n_results);
110 for (i = 0; i < n_results; ++i) {
111 ir_type *result_type = get_method_res_type(function_type, i);
112 ir_mode *result_mode = get_type_mode(result_type);
113 reg_or_stackslot_t *result = &results[i];
115 if (mode_is_float(result_mode)) {
116 if (float_regnum >= n_float_result_regs) {
117 panic("Too many float results");
119 const arch_register_t *reg = float_result_regs[float_regnum++];
123 if (get_mode_size_bits(result_mode) > 32) {
124 panic("Results with more than 32bits not supported yet");
127 if (regnum >= n_result_regs) {
128 panic("Too many results");
130 const arch_register_t *reg = result_regs[regnum++];
136 cconv = XMALLOCZ(calling_convention_t);
137 cconv->parameters = params;
138 cconv->param_stack_size = stack_offset;
139 cconv->n_reg_params = n_param_regs_used;
140 cconv->results = results;
142 /* setup allocatable registers */
144 be_irg_t *birg = be_birg_from_irg(irg);
145 size_t n_ignores = ARRAY_SIZE(ignore_regs);
146 struct obstack *obst = &birg->obst;
149 assert(birg->allocatable_regs == NULL);
150 birg->allocatable_regs = rbitset_obstack_alloc(obst, N_ARM_REGISTERS);
151 rbitset_set_all(birg->allocatable_regs, N_ARM_REGISTERS);
152 for (r = 0; r < n_ignores; ++r) {
153 rbitset_clear(birg->allocatable_regs, ignore_regs[r]);
160 void arm_free_calling_convention(calling_convention_t *cconv)
162 free(cconv->parameters);
163 free(cconv->results);