// Create a NoReg dependency for each child of a call that has been evaluated into a register. // Ignore children that do not have a register since their live range should not persist outside of // the helper call stream. // TR::RegisterDependencyConditions *TR_OutlinedInstructions::formEvaluatedArgumentDepList() { int32_t i, c=0; for (i=_callNode->getFirstArgumentIndex(); i<_callNode->getNumChildren(); i++) { TR::Register *reg = _callNode->getChild(i)->getRegister(); if (reg) { TR::RegisterPair *regPair = reg->getRegisterPair(); c += regPair? 2 : 1; } } TR::RegisterDependencyConditions *depConds = NULL; if (c) { TR::Machine *machine = _cg->machine(); depConds = generateRegisterDependencyConditions(0, c, _cg); for (i=_callNode->getFirstArgumentIndex(); i<_callNode->getNumChildren(); i++) { TR::Register *reg = _callNode->getChild(i)->getRegister(); if (reg) { TR::RegisterPair *regPair = reg->getRegisterPair(); if (regPair) { depConds->addPostCondition(regPair->getLowOrder(), TR::RealRegister::NoReg, _cg); depConds->addPostCondition(regPair->getHighOrder(), TR::RealRegister::NoReg, _cg); } else { depConds->addPostCondition(reg, TR::RealRegister::NoReg, _cg); } } } depConds->stopAddingConditions(); } return depConds; }
TR::Register *TR::IA32SystemLinkage::buildDirectDispatch(TR::Node *callNode, bool spillFPRegs) { TR::RealRegister *stackPointerReg = machine()->getX86RealRegister(TR::RealRegister::esp); TR::SymbolReference *methodSymRef = callNode->getSymbolReference(); TR::MethodSymbol *methodSymbol = callNode->getSymbol()->castToMethodSymbol(); TR::ILOpCodes callOpCodeValue = callNode->getOpCodeValue(); if (!methodSymbol->isHelper()) diagnostic("Building call site for %s\n", methodSymbol->getMethod()->signature(trMemory())); TR::RegisterDependencyConditions *deps; deps = generateRegisterDependencyConditions((uint8_t)0, (uint8_t)6, cg()); TR::Register *returnReg = buildVolatileAndReturnDependencies(callNode, deps); deps->stopAddingConditions(); TR::RegisterDependencyConditions *dummy = generateRegisterDependencyConditions((uint8_t)0, (uint8_t)0, cg()); uint32_t argSize = buildArgs(callNode, dummy); TR::Register* targetAddressReg = NULL; TR::MemoryReference* targetAddressMem = NULL; // Call-out int32_t stackAdjustment = cg()->getProperties().getCallerCleanup() ? 0 : -argSize; TR::X86ImmInstruction* instr = generateImmSymInstruction(CALLImm4, callNode, (uintptr_t)methodSymbol->getMethodAddress(), methodSymRef, cg()); instr->setAdjustsFramePointerBy(stackAdjustment); if (cg()->getProperties().getCallerCleanup() && argSize > 0) { // Clean up arguments // generateRegImmInstruction( (argSize <= 127) ? ADD4RegImms : ADD4RegImm4, callNode, stackPointerReg, argSize, cg() ); } // Label denoting end of dispatch code sequence; dependencies are on // this label rather than on the call // TR::LabelSymbol *endSystemCallSequence = generateLabelSymbol(cg()); generateLabelInstruction(LABEL, callNode, endSystemCallSequence, deps, cg()); // Stop using the killed registers that are not going to persist // if (deps) stopUsingKilledRegisters(deps, returnReg); // If the method returns a floating point value that is not used, insert a dummy store to // eventually pop the value from the floating point stack. // if ((callNode->getDataType() == TR::Float || callNode->getDataType() == TR::Double) && callNode->getReferenceCount() == 1) { generateFPSTiST0RegRegInstruction(FSTRegReg, callNode, returnReg, returnReg, cg()); } if (cg()->enableRegisterAssociations()) associatePreservedRegisters(deps, returnReg); return returnReg; }