use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class ShortArrayReplacer method transform.
@Override
public void transform() {
// first set up temporary scalars for the array elements
// initialize them before the def.
RegisterOperand[] scalars = new RegisterOperand[size];
TypeReference elementType = vmArray.getElementType().getTypeRef();
RegisterOperand def = reg.defList;
Instruction defI = def.instruction;
Operand defaultValue = IRTools.getDefaultOperand(elementType);
for (int i = 0; i < size; i++) {
scalars[i] = IRTools.moveIntoRegister(elementType, IRTools.getMoveOp(elementType), ir.regpool, defI, defaultValue.copy());
}
transform2(this.reg, defI, scalars);
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class ShortArrayReplacer method scalarReplace.
/**
* Replace a given use of an array with its scalar equivalent.
*
* @param use the use to replace
* @param scalars an array of scalar register operands to replace
* the array with
* @param visited TODO currently useless. Is this parameter
* necessary or should it be removed?
*/
private void scalarReplace(RegisterOperand use, RegisterOperand[] scalars, Set<Register> visited) {
Instruction inst = use.instruction;
RVMType type = vmArray.getElementType();
switch(inst.getOpcode()) {
case INT_ALOAD_opcode:
case LONG_ALOAD_opcode:
case FLOAT_ALOAD_opcode:
case DOUBLE_ALOAD_opcode:
case BYTE_ALOAD_opcode:
case UBYTE_ALOAD_opcode:
case USHORT_ALOAD_opcode:
case SHORT_ALOAD_opcode:
case REF_ALOAD_opcode:
{
// of a trap
if (ALoad.getIndex(inst).isIntConstant()) {
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
int index = ALoad.getIndex(inst).asIntConstant().value;
if (index >= 0 && index < size) {
Instruction i2 = Move.create(moveOp, ALoad.getClearResult(inst), scalars[index].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
} else {
if (VM.BuildForIA32) {
if (size == 0) {
DefUse.removeInstructionAndUpdateDU(inst);
} else if (size == 1) {
int index = 0;
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, ALoad.getClearResult(inst), scalars[index].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
Operator moveOp = IRTools.getCondMoveOp(type.getTypeRef());
Instruction i2 = CondMove.create(moveOp, ALoad.getClearResult(inst), ALoad.getClearIndex(inst), IC(0), ConditionOperand.EQUAL(), scalars[0].copyRO(), scalars[1].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
} else {
if (size == 1) {
int index = 0;
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, ALoad.getClearResult(inst), scalars[index].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
}
}
}
break;
case INT_ASTORE_opcode:
case LONG_ASTORE_opcode:
case FLOAT_ASTORE_opcode:
case DOUBLE_ASTORE_opcode:
case BYTE_ASTORE_opcode:
case SHORT_ASTORE_opcode:
case REF_ASTORE_opcode:
{
// of a trap
if (AStore.getIndex(inst).isIntConstant()) {
int index = AStore.getIndex(inst).asIntConstant().value;
if (index >= 0 && index < size) {
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, scalars[index].copyRO(), AStore.getClearValue(inst));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
} else {
if (VM.BuildForIA32) {
if (size == 0) {
DefUse.removeInstructionAndUpdateDU(inst);
} else if (size == 1) {
int index = 0;
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, scalars[index].copyRO(), AStore.getClearValue(inst));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
Operator moveOp = IRTools.getCondMoveOp(type.getTypeRef());
Operand value = AStore.getClearValue(inst);
Instruction i2 = CondMove.create(moveOp, scalars[0].copyRO(), AStore.getIndex(inst), IC(0), ConditionOperand.EQUAL(), value, scalars[0].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
Instruction i3 = CondMove.create(moveOp, scalars[1].copyRO(), AStore.getIndex(inst), IC(0), ConditionOperand.NOT_EQUAL(), value, scalars[1].copyRO());
i2.insertAfter(i3);
DefUse.updateDUForNewInstruction(i3);
}
} else {
if (size == 1) {
int index = 0;
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, scalars[index].copyRO(), AStore.getClearValue(inst));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
}
}
}
break;
case NULL_CHECK_opcode:
{
// Null check on result of new array must succeed
Instruction i2 = Move.create(GUARD_MOVE, NullCheck.getClearGuardResult(inst), new TrueGuardOperand());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case BOUNDS_CHECK_opcode:
{
// Remove or create trap as appropriate
Instruction i2 = TrapIf.create(TRAP_IF, BoundsCheck.getClearGuardResult(inst), IC(size), BoundsCheck.getClearIndex(inst), ConditionOperand.LOWER_EQUAL(), TrapCodeOperand.ArrayBounds());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case CHECKCAST_opcode:
case CHECKCAST_NOTNULL_opcode:
case CHECKCAST_UNRESOLVED_opcode:
{
// We cannot handle removing the checkcast if the result of the
// checkcast test is unknown
TypeReference lhsType = TypeCheck.getType(inst).getTypeRef();
if (ClassLoaderProxy.includesType(lhsType, vmArray.getTypeRef()) == YES) {
if (visited == null) {
visited = new HashSet<Register>();
}
Register copy = TypeCheck.getResult(inst).getRegister();
if (!visited.contains(copy)) {
visited.add(copy);
transform2(copy, inst, scalars);
// NB will remove inst
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
} else {
Instruction i2 = Trap.create(TRAP, null, TrapCodeOperand.CheckCast());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
}
break;
case INSTANCEOF_opcode:
case INSTANCEOF_NOTNULL_opcode:
case INSTANCEOF_UNRESOLVED_opcode:
{
// We cannot handle removing the instanceof if the result of the
// instanceof test is unknown
TypeReference lhsType = InstanceOf.getType(inst).getTypeRef();
Instruction i2;
if (ClassLoaderProxy.includesType(lhsType, vmArray.getTypeRef()) == YES) {
i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(1));
} else {
i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(0));
}
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case GET_OBJ_TIB_opcode:
{
Instruction i2 = Move.create(REF_MOVE, GuardedUnary.getClearResult(inst), new TIBConstantOperand(vmArray));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case REF_MOVE_opcode:
{
if (visited == null) {
visited = new HashSet<Register>();
}
Register copy = Move.getResult(inst).getRegister();
if (!visited.contains(copy)) {
visited.add(copy);
transform2(copy, inst, scalars);
// NB will remove inst
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
}
break;
default:
throw new OptimizingCompilerException("Unexpected instruction: " + inst);
}
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class LiveAnalysis method computeBlockGenAndKill.
/**
* Compute summary (local) live variable analysis for a basic block, which
* is basically Gen and Kill information.<p>
*
* For more details, see the paper "Efficient and Precise Modeling of
* Exceptions for the Analysis of Java Programs" by Choi, Grove, Hind
* and Sarkar in ACM PASTE99 workshop.
*
* @param bblock the basic block
* @param ir the governing IR
*/
private void computeBlockGenAndKill(BasicBlock bblock, IR ir) {
if (VERBOSE) {
System.out.println(" --> Computing Gen/Kill for block " + bblock);
}
// Tells whether we've seen the first PEI
boolean seenFirstPEI = false;
// Because control flow may emanate from a potentially excepting
// instruction (PEI) out of the basic block, care must be taken
// when computing what can be killed by a basic block.
//
// S1: y =
// S2: <exception-raising inst>
// S3: x =
// For example in the block above, live variables coming from
// the normal exit of the block (i.e., after S3) can be killed
// by S1 or S3 (depending on the variable). However, live variables
// coming from the PEI edge (at S2) can only be killed by S1.
// Thus, when a block contains PEIs, we need to distinguish the
// kill sets. Namely, we need
// Kill_tot - what can be killed anywhere in the block
// Kill_n - what can be killed from PEI_n on up
// Kill_n-1 - what can be killed from PEI_n-1 on up
// ...
// Kill_1 - what can be killed from PEI_1 on up
// We would then compute In as follows
//
// In = Out_norm - Kill_tot (all vars entering from bottom are eligible
// to be killed)
// U Out_n - Kill_n
// U Out_n-1 - Kill_n-1
// ...
// U Out_1 - Kill_1
// U Gen
// where Out_n is the out information at PEI i, i.e., the IN information
// for whatever handlers may catch PEI i
// ...
// PEI 1
// ...
// PEI n-1
// ...
// PEI n
// ...
// If we conservatively assume all handlers for the block of interest
// can be reached by all PEIs in this block then the equation becomes
// In = (Out_norm - Kill_tot)
// U (Out_hand - Kill_n)
// U (Out_hand - Kill_n-1)
// ...
// U (Out_hand - Kill_1)
// U Gen
// where "Out_hand" is the union of the in sets for all handlers.
// Since Kill_i is a subset of Kill_j, for i < j, we can simplify to
// In = (Out_norm - Kill_tot)
// U (Out_hand - Kill_1) (1)
// U Gen
// Since kill_1 is a subset of kill_tot, we don't need the
// the parenthesis (and the intermediate set)
// If there are no handlers than (1) is empty and we don't need
// to compute Kill_1. We will take this approach for now.
// So for each block we will have at most 2 kill sets: Kill_tot and Kill_1
// This code finds the first PEI in the block
Instruction firstPEI = null;
if (bblock.canThrowExceptions()) {
for (Instruction inst = bblock.firstInstruction(); inst != bblock.lastInstruction(); inst = inst.nextInstructionInCodeOrder()) {
if (inst.isPEI() && bblock.getApplicableExceptionalOut(inst).hasMoreElements()) {
firstPEI = inst;
// remember that this block has a PEI with a handler for use
// later in "processBlock"
bbLiveInfo[bblock.getNumber()].setContainsPEIWithHandler(true);
break;
}
}
}
// Get any uses from PHIs, which are in the successor blocks
getUsesFromPhis(bblock);
// Traverse instructions in reverse order within the basic block.
for (Instruction inst = bblock.lastInstruction(); inst != bblock.firstInstruction(); inst = inst.prevInstructionInCodeOrder()) {
// traverse from defs to uses becauses uses happen after
// (in a backward sense) defs
Enumeration<Operand> defs = inst.getPureDefs();
while (defs.hasMoreElements()) {
Operand def = defs.nextElement();
if (def instanceof RegisterOperand) {
RegisterOperand regOp = (RegisterOperand) def;
// Do we care about this reg?
if (isSkippableReg(regOp, ir)) {
continue;
}
TypeReference regType = regOp.getType();
// include it. It will be picked up later by local propagation phase.
if (regOp.getRegister().spansBasicBlock() && regType != null) {
// if it is a DEF we place it is the BBKillSet and remove it from
// the GEN set, (GEN should only contain upward-exposed uses,
// i.e., uses that are NOT dominated by a DEF).
// We don't need to worry about PEIs here because
// later instructions (traversing backwards like we are)
// will always dominate earlier instructions *of this block*
bbLiveInfo[bblock.getNumber()].BBKillSet().add(regOp);
bbLiveInfo[bblock.getNumber()].getGen().remove(regOp);
// If there are no PEIs in this block we don't bother to add
if (seenFirstPEI) {
bbLiveInfo[bblock.getNumber()].firstPEIKillSet().add(regOp);
}
}
}
}
// Now process the uses, unless this is a PHI operator
if (inst.operator() != PHI) {
for (Enumeration<Operand> uses = inst.getUses(); uses.hasMoreElements(); ) {
Operand use = uses.nextElement();
if (use instanceof RegisterOperand) {
RegisterOperand regOp = (RegisterOperand) use;
// Do we care about this reg?
if (isSkippableReg(regOp, ir)) {
continue;
}
TypeReference regType = regOp.getType();
// later by local propagation phase.
if (regOp.getRegister().spansBasicBlock() && regType != null) {
bbLiveInfo[bblock.getNumber()].getGen().add(regOp);
}
}
// is RegOp
}
// foreach use
}
// If so, set the flag so we can start killing.
if (firstPEI == inst) {
seenFirstPEI = true;
}
}
// foreach instruction in block
if (VERBOSE) {
System.out.println(" Gen: " + bbLiveInfo[bblock.getNumber()].getGen());
System.out.println(" Kill: " + bbLiveInfo[bblock.getNumber()].BBKillSet());
System.out.println(" 1st PEI Kill: " + bbLiveInfo[bblock.getNumber()].firstPEIKillSet());
System.out.println(" ---> Done computing Gen/Kill for block");
}
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class CallingConvention method expandPrologue.
private static void expandPrologue(IR ir) {
boolean useDU = ir.options.getOptLevel() >= 1;
if (useDU) {
// set up register lists for dead code elimination.
DefUse.computeDU(ir);
}
Instruction p = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
if (VM.VerifyAssertions)
VM._assert(p.operator() == IR_PROLOGUE);
Instruction start = p.nextInstructionInCodeOrder();
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
int gprIndex = 0;
int fprIndex = 0;
int paramByteOffset = ir.incomingParameterBytes() + 2 * WORDSIZE;
// count the number of FPR params in a pre-pass
int FPRRegisterParams = countFPRParamsInPrologue(p);
FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams());
ir.MIRInfo.fpStackHeight = Math.max(ir.MIRInfo.fpStackHeight, FPRRegisterParams);
// deal with each parameter
for (Enumeration<Operand> e = p.getDefs(); e.hasMoreElements(); ) {
RegisterOperand symbOp = (RegisterOperand) e.nextElement();
TypeReference rType = symbOp.getType();
if (rType.isFloatingPointType()) {
int size;
if (rType.isFloatType()) {
size = BYTES_IN_FLOAT;
paramByteOffset -= WORDSIZE;
} else {
size = BYTES_IN_DOUBLE;
paramByteOffset -= 2 * WORDSIZE;
}
// if optimizing, only define the register if it has uses
if (!useDU || symbOp.getRegister().useList != null) {
if (fprIndex < PhysicalRegisterSet.getNumberOfFPRParams()) {
// the 2nd goes in F(k-2), etc...
if (SSE2_FULL) {
Register param = phys.getFPRParam(fprIndex);
if (rType.isFloatType()) {
start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), F(param)));
} else {
start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), D(param)));
}
} else {
Register param = phys.getFPRParam(FPRRegisterParams - fprIndex - 1);
start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), D(param)));
}
} else {
Operand M = new StackLocationOperand(true, paramByteOffset, size);
if (SSE2_FULL) {
if (rType.isFloatType()) {
start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), M));
} else {
start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), M));
}
} else {
start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), M));
}
}
}
fprIndex++;
} else {
// if optimizing, only define the register if it has uses
paramByteOffset -= WORDSIZE;
if (paramIsNativeLongOn64Bit(symbOp)) {
paramByteOffset -= WORDSIZE;
}
if (!useDU || symbOp.getRegister().useList != null) {
// t is object, 1/2 of a long, int, short, char, byte, or boolean
if (gprIndex < PhysicalRegisterSet.getNumberOfGPRParams()) {
// to give the register allocator more freedom, we
// insert two move instructions to get the physical into
// the symbolic. First a move from the physical to a fresh temp
// before start and second a move from the temp to the
// 'real' parameter symbolic after start.
RegisterOperand tmp = ir.regpool.makeTemp(rType);
Register param = phys.getGPRParam(gprIndex);
RegisterOperand pOp = new RegisterOperand(param, rType);
start.insertBefore(PhysicalRegisterTools.makeMoveInstruction(tmp, pOp));
Instruction m2 = PhysicalRegisterTools.makeMoveInstruction(symbOp.copyRO(), tmp.copyD2U());
start.insertBefore(m2);
start = m2;
} else {
int stackLocSize = WORDSIZE;
if (VM.BuildFor64Addr && rType.getMemoryBytes() <= BYTES_IN_INT) {
stackLocSize = BYTES_IN_INT;
}
Operand M = new StackLocationOperand(true, paramByteOffset, stackLocSize);
start.insertBefore(MIR_Move.create(IA32_MOV, symbOp.copyRO(), M));
}
}
gprIndex++;
}
}
if (VM.VerifyAssertions && paramByteOffset != 2 * WORDSIZE) {
String msg = "pb = " + paramByteOffset + "; expected " + 2 * WORDSIZE;
VM._assert(VM.NOT_REACHED, msg);
}
removeDefsFromPrologue(p);
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class CallingConvention method expandParametersToSysCall.
/**
* Explicitly copy parameters to a system call into the appropriate physical
* registers as defined by the calling convention. Note that for a system
* call (ie., a call to C), the order of parameters on the stack is
* <em> reversed </em> compared to the normal RVM calling convention<p>
*
* Note: Assumes that ESP points to the word before the slot where the
* first parameter should be stored.<p>
*
* TODO: much of this code is exactly the same as in expandParametersToCall().
* factor out the common code.
*
* @param call the call instruction
* @param ir the IR that contains the call
* @return the number of bytes necessary to hold the parameters
*/
private static int expandParametersToSysCall(Instruction call, IR ir) {
int nGPRParams = 0;
int nFPRParams = 0;
int parameterBytes = 0;
int numParams = MIR_Call.getNumberOfParams(call);
if (VM.BuildFor32Addr) {
// NOTE: All params to syscall are passed on the stack!
for (int i = numParams - 1; i >= 0; i--) {
Operand param = MIR_Call.getClearParam(call, i);
MIR_Call.setParam(call, i, null);
TypeReference paramType = param.getType();
if (paramType.isFloatingPointType()) {
nFPRParams++;
int size;
if (paramType.isFloatType()) {
size = BYTES_IN_FLOAT;
parameterBytes -= WORDSIZE;
} else {
size = BYTES_IN_DOUBLE;
parameterBytes -= 2 * WORDSIZE;
}
Operand M = new StackLocationOperand(false, parameterBytes, size);
if (SSE2_FULL) {
if (paramType.isFloatType()) {
call.insertBefore(MIR_Move.create(IA32_MOVSS, M, param));
} else {
call.insertBefore(MIR_Move.create(IA32_MOVSD, M, param));
}
} else {
call.insertBefore(MIR_Move.create(IA32_FMOV, M, param));
}
} else {
nGPRParams++;
parameterBytes -= WORDSIZE;
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + WORDSIZE)));
call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, param));
}
}
return parameterBytes;
} else {
if (VM.VerifyAssertions)
VM._assert(SSE2_FULL, "x64 builds must have SSE2_FULL enabled");
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
// count the number FPR parameters in a pre-pass
int FPRRegisterParams = countFPRParams(call);
FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfNativeFPRParams());
// offset, in bytes, from the SP, for the next parameter slot on the
// stack
parameterBytes = -2 * WORDSIZE;
RegisterOperand fpCount = new RegisterOperand(phys.getEAX(), TypeReference.Int);
// Save count of vector parameters (= XMM) in EAX as defined by
// the ABI for varargs convention
call.insertBefore(MIR_Move.create(IA32_MOV, fpCount, IC(FPRRegisterParams)));
// Save volatiles to non-volatiles that are currently not used
call.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(phys.getGPR(R14), TypeReference.Long), new RegisterOperand(phys.getESI(), TypeReference.Long)));
call.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(phys.getGPR(R13), TypeReference.Long), new RegisterOperand(phys.getEDI(), TypeReference.Long)));
// Restore volatiles from non-volatiles
call.insertAfter(MIR_Move.create(IA32_MOV, new RegisterOperand(phys.getESI(), TypeReference.Long), new RegisterOperand(phys.getGPR(R14), TypeReference.Long)));
call.insertAfter(MIR_Move.create(IA32_MOV, new RegisterOperand(phys.getEDI(), TypeReference.Long), new RegisterOperand(phys.getGPR(R13), TypeReference.Long)));
if (VM.BuildFor64Addr) {
// Add a marker instruction. When processing x64 syscalls, the block of the syscall
// needs to be split up to copy the code for the call. Copying has to occur
// to be able to ensure stack alignment for the x64 ABI. This instruction
// marks the border for the copy: everything before this instruction isn't duplicated.
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(MARKER)));
}
// Require ESP to be at bottom of frame before a call,
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(0)));
// Determine if a parameter is in a register or not
boolean[] inRegister = new boolean[numParams];
nFPRParams = 0;
nGPRParams = 0;
for (int i = 0; i < numParams; i++) {
Operand param = MIR_Call.getParam(call, i);
TypeReference paramType = param.getType();
if (paramType.isFloatingPointType()) {
nFPRParams++;
inRegister[i] = nFPRParams <= PhysicalRegisterSet.getNumberOfNativeFPRParams();
} else {
nGPRParams++;
inRegister[i] = nGPRParams <= PhysicalRegisterSet.getNumberOfNativeGPRParams();
}
}
// Walk over non-register parameters from right-to-left and assign stack slots
int[] stackSlot = new int[numParams];
for (int i = numParams - 1; i >= 0; i--) {
if (!inRegister[i]) {
parameterBytes -= BYTES_IN_STACKSLOT;
stackSlot[i] = parameterBytes;
}
}
// Pass stack slot parameters from right-to-left
for (int i = numParams - 1; i >= 0; i--) {
if (!inRegister[i]) {
Operand param = MIR_Call.getClearParam(call, i);
TypeReference paramType = param.getType();
if (paramType.isFloatingPointType()) {
// pass the FP parameter on the stack
Operand M = new StackLocationOperand(false, stackSlot[i], BYTES_IN_STACKSLOT);
if (paramType.isFloatType()) {
call.insertBefore(MIR_Move.create(IA32_MOVSS, M, param));
} else {
call.insertBefore(MIR_Move.create(IA32_MOVSD, M, param));
}
} else {
// Write the parameter into the appropriate stack frame location.
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(stackSlot[i] + BYTES_IN_STACKSLOT)));
call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, param));
}
}
}
// Pass register parameters from left-to-right
int nParamsInRegisters = 0;
nFPRParams = 0;
nGPRParams = 0;
for (int i = 0; i < numParams; i++) {
if (inRegister[i]) {
Operand param = MIR_Call.getClearParam(call, i);
TypeReference paramType = param.getType();
if (paramType.isFloatingPointType()) {
// Pass the parameter in a register.
RegisterOperand real = new RegisterOperand(phys.getNativeFPRParam(nFPRParams), paramType);
nFPRParams++;
if (paramType.isFloatType()) {
call.insertBefore(MIR_Move.create(IA32_MOVSS, real, param));
} else {
call.insertBefore(MIR_Move.create(IA32_MOVSD, real, param));
}
// Record that the call now has a use of the real register.
MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
} else {
Register phy = phys.getNativeGPRParam(nGPRParams);
nGPRParams++;
RegisterOperand real = new RegisterOperand(phy, paramType);
call.insertBefore(MIR_Move.create(IA32_MOV, real, param));
// Record that the call now has a use of the real register.
MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
}
}
}
return parameterBytes;
}
}
Aggregations