void TR::AMD64ABILinkage::mapIncomingParms( TR::ResolvedMethodSymbol *method, uint32_t &stackIndex) { ListIterator<TR::ParameterSymbol> parameterIterator(&method->getParameterList()); TR::ParameterSymbol *parmCursor = parameterIterator.getFirst(); if (!parmCursor) return; if (parmCursor->getLinkageRegisterIndex() < 0) { copyLinkageInfoToParameterSymbols(); } // 1st: handle parameters which are passed through stack // TR::X86SystemLinkage::mapIncomingParms(method); // 2nd: handle parameters which are passed through linkage registers, but are // not assigned any register after RA (or say, by their first usage point, // a MOV is needed to load it from stack to register). // // AMD64 SysV ABI says that: a parameter is placed either in registers or // pushed on the stack, but can't take both. So, for parms passed through // linkage registers but don't have physical registers assigned after RA, // we will allocate stack space in local variable region. // for (parmCursor = parameterIterator.getFirst(); parmCursor; parmCursor = parameterIterator.getNext()) { if ((parmCursor->getLinkageRegisterIndex() >= 0) && (parmCursor->getAllocatedIndex() < 0 || hasToBeOnStack(parmCursor))) { uint32_t align = getAlignment(parmCursor->getDataType()); uint32_t alignMinus1 = (align <= AMD64_STACK_SLOT_SIZE) ? (AMD64_STACK_SLOT_SIZE - 1) : (align - 1); uint32_t pos = -stackIndex; pos += parmCursor->getSize(); pos = (pos + alignMinus1) & (~alignMinus1); stackIndex = -pos; parmCursor->setParameterOffset(stackIndex); if (comp()->getOption(TR_TraceCG)) traceMsg(comp(), "mapIncomingParms setParameterOffset %d for param symbol (reg param without home location) %p, hasToBeOnStack() %d\n", parmCursor->getParameterOffset(), parmCursor, hasToBeOnStack(parmCursor)); } else if (parmCursor->getLinkageRegisterIndex() >=0 && parmCursor->getAllocatedIndex() >= 0) { //parmCursor->setDontHaveStackSlot(0); // this is a hack , so as we could print stack layout table in createPrologue if (comp()->getOption(TR_TraceCG)) traceMsg(comp(), "mapIncomingParms no need to set parm %p, for it has got register %d assigned\n", parmCursor, parmCursor->getAllocatedIndex()); } } }
void TR::ARM64SystemLinkage::createPrologue(TR::Instruction *cursor, List<TR::ParameterSymbol> &parmList) { TR::CodeGenerator *codeGen = cg(); TR::Machine *machine = codeGen->machine(); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); const TR::ARM64LinkageProperties& properties = getProperties(); TR::RealRegister *sp = machine->getRealRegister(properties.getStackPointerRegister()); TR::Node *firstNode = comp()->getStartTree()->getNode(); // allocate stack space uint32_t frameSize = (uint32_t)codeGen->getFrameSizeInBytes(); if (constantIsUnsignedImm12(frameSize)) { cursor = generateTrg1Src1ImmInstruction(codeGen, TR::InstOpCode::subimmx, firstNode, sp, sp, frameSize, cursor); } else { TR_UNIMPLEMENTED(); } // save link register (x30) if (machine->getLinkRegisterKilled()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, 0, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::strimmx, firstNode, stackSlot, machine->getRealRegister(TR::RealRegister::x30), cursor); } // spill argument registers int32_t nextIntArgReg = 0; int32_t nextFltArgReg = 0; ListIterator<TR::ParameterSymbol> parameterIterator(&parmList); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter != NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter = parameterIterator.getNext()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, parameter->getParameterOffset(), codeGen); TR::InstOpCode::Mnemonic op; switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { op = (parameter->getSize() == 8) ? TR::InstOpCode::strimmx : TR::InstOpCode::strimmw; cursor = generateMemSrc1Instruction(cg(), op, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::x0 + nextIntArgReg)), cursor); nextIntArgReg++; } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Float: case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { op = (parameter->getSize() == 8) ? TR::InstOpCode::vstrimmd : TR::InstOpCode::vstrimms; cursor = generateMemSrc1Instruction(cg(), op, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::v0 + nextFltArgReg)), cursor); nextFltArgReg++; } else { nextFltArgReg = getProperties().getNumFloatArgRegs() + 1; } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on AArch64."); break; default: TR_ASSERT(false, "Unknown parameter type."); } } // save callee-saved registers uint32_t offset = bodySymbol->getLocalMappingCursor(); for (int r = TR::RealRegister::x19; r <= TR::RealRegister::x28; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::strimmx, firstNode, stackSlot, rr, cursor); offset += 8; } } for (int r = TR::RealRegister::v8; r <= TR::RealRegister::v15; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::vstrimmd, firstNode, stackSlot, rr, cursor); offset += 8; } } }