blob: 889aa2ea99241cfbe83875577cf648ab57090ac0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Alexander Astapchuk
*/
/**
* @file
* @brief Implementation of CallSig routines.
*/
#include "csig.h"
namespace Jitrino {
namespace Jet {
const CallSig helper_v(CCONV_HELPERS, jvoid);
const CallSig platform_v(CCONV_HELPERS, iplatf);
void CallSig::init()
{
unsigned num = (unsigned)m_args.size();
m_data.resize(num);
unsigned fps = 0, gps = 0;
// Assign return value
m_ret_reg[0] = -1;
m_ret_reg[1] = -1;
if (is_f(m_ret_jt)) {
if (m_cc & CCONV_RETURN_FP_THROUGH_FPU) {
m_ret_reg[0] = fp0;
} else {
m_ret_reg[0] = fr0;
}
} else if (m_ret_jt != jvoid) {
m_ret_reg[0] = gr0;
if (is_wide(m_ret_jt)) {
m_ret_reg[1] = gr3;
}
}
//
// Assign registers
//
bool regs = !(m_cc & CCONV_MEM);
// Note: Registers are always assigned in left-to-right order,
// regardless of L2R setting in calling convention. This is how all our
// conventions behave - might want to document it somewhere - TODO.
for (unsigned i=0; i<num; i++) {
jtype jt = m_args[i];
if (regs && is_f(jt) && get_cconv_fr(fps, i) != fr_x) {
m_data[i] = get_cconv_fr(fps, i);
++fps;
}
else if (regs && !is_f(jt) && get_cconv_gr(gps, i) != gr_x) {
m_data[i] = get_cconv_gr(gps, i);
++gps;
}
else {
// mark the items that need to be assigned to memory
m_data[i] = -1;
}
}
bool l2r = m_cc & CCONV_L2R;
int start, end, step;
if (l2r) {
start = num-1;
end = -1;
step = -1;
}
else {
start = 0;
end = num;
step = 1;
}
int off = 0;
m_stack = 0;
for (int i=start; i != end; i+=step) {
jtype jt = m_args[i];
if (m_data[i]<0) {
m_data[i] = off;
off -= STACK_SIZE(jtypes[jt].size);
}
}
m_stack = -off;
m_alignment = 0;
unsigned stack_on_enter_size = m_stack + sizeof(POINTER_SIZE_INT);
// Do alignment.
unsigned alignment = (m_cc & CCONV_STACK_ALIGN_HALF16) ? CCONV_STACK_ALIGN16
: m_cc & CCONV_STACK_ALIGN_MASK;
if (alignment != 0 && stack_on_enter_size & (alignment - 1)) {
unsigned stack_on_enter_aligned =
(stack_on_enter_size + (alignment - 1)) & ~((alignment - 1));
m_alignment = stack_on_enter_aligned - stack_on_enter_size;
}
m_stack += m_alignment;
}
}}; // ~namespace Jitrino::Jet