/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt.ir.ia32;
import org.jikesrvm.classloader.VM_Atom;
import org.jikesrvm.classloader.VM_Field;
import org.jikesrvm.classloader.VM_MethodReference;
import org.jikesrvm.classloader.VM_TypeReference;
import org.jikesrvm.compilers.opt.OPT_MagicNotImplementedException;
import org.jikesrvm.compilers.opt.ir.Binary;
import org.jikesrvm.compilers.opt.ir.CacheOp;
import org.jikesrvm.compilers.opt.ir.Empty;
import org.jikesrvm.compilers.opt.ir.GetField;
import org.jikesrvm.compilers.opt.ir.Load;
import org.jikesrvm.compilers.opt.ir.Move;
import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand;
import org.jikesrvm.compilers.opt.ir.OPT_BC2IR;
import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext;
import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand;
import org.jikesrvm.compilers.opt.ir.OPT_LocationOperand;
import org.jikesrvm.compilers.opt.ir.OPT_Operand;
import org.jikesrvm.compilers.opt.ir.OPT_Operators;
import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand;
import org.jikesrvm.compilers.opt.ir.OPT_TrueGuardOperand;
import org.jikesrvm.compilers.opt.ir.Store;
import org.jikesrvm.ia32.VM_StackframeLayoutConstants;
import org.jikesrvm.runtime.VM_ArchEntrypoints;
import org.jikesrvm.runtime.VM_Magic;
import org.jikesrvm.runtime.VM_MagicNames;
/**
* This class implements the machine-specific magics for the opt compiler.
*
* @see org.jikesrvm.compilers.opt.ir.OPT_GenerateMagic for the machine-independent magics
*/
public abstract class OPT_GenerateMachineSpecificMagic implements OPT_Operators, VM_StackframeLayoutConstants {
/**
* "Semantic inlining" of methods of the VM_Magic class.
* Based on the methodName, generate a sequence of opt instructions
* that implement the magic, updating the stack as necessary
*
* @param bc2ir the bc2ir object generating the ir containing this magic
* @param gc == bc2ir.gc
* @param meth the VM_Method that is the magic method
*/
public static boolean generateMagic(OPT_BC2IR bc2ir, OPT_GenerationContext gc, VM_MethodReference meth)
throws OPT_MagicNotImplementedException {
VM_Atom methodName = meth.getName();
OPT_PhysicalRegisterSet phys = gc.temps.getPhysicalRegisterSet();
if (methodName == VM_MagicNames.getESIAsProcessor) {
OPT_RegisterOperand rop = gc.temps.makePROp();
bc2ir.markGuardlessNonNull(rop);
bc2ir.push(rop);
} else if (methodName == VM_MagicNames.setESIAsProcessor) {
OPT_Operand val = bc2ir.popRef();
if (val instanceof OPT_RegisterOperand) {
bc2ir.appendInstruction(Move.create(REF_MOVE, gc.temps.makePROp(), val));
} else {
String msg = " Unexpected operand VM_Magic.setProcessorRegister";
throw OPT_MagicNotImplementedException.UNEXPECTED(msg);
}
} else if (methodName == VM_MagicNames.getFramePointer) {
gc.allocFrame = true;
OPT_RegisterOperand val = gc.temps.makeTemp(VM_TypeReference.Address);
VM_Field f = VM_ArchEntrypoints.framePointerField;
OPT_RegisterOperand pr = new OPT_RegisterOperand(phys.getESI(), VM_TypeReference.Int);
bc2ir.appendInstruction(GetField.create(GETFIELD,
val,
pr.copy(),
new OPT_AddressConstantOperand(f.getOffset()),
new OPT_LocationOperand(f),
new OPT_TrueGuardOperand()));
bc2ir.push(val.copyD2U());
} else if (methodName == VM_MagicNames.getJTOC || methodName == VM_MagicNames.getTocPointer) {
VM_TypeReference t = (methodName == VM_MagicNames.getJTOC ? VM_TypeReference.IntArray : VM_TypeReference.Address);
OPT_RegisterOperand val = gc.temps.makeTemp(t);
OPT_AddressConstantOperand addr = new OPT_AddressConstantOperand(VM_Magic.getTocPointer());
bc2ir.appendInstruction(Move.create(REF_MOVE, val, addr));
bc2ir.push(val.copyD2U());
} else if (methodName == VM_MagicNames.isync) {
// nothing required on Intel
} else if (methodName == VM_MagicNames.sync) {
// nothing required on Intel
} else if (methodName == VM_MagicNames.prefetch) {
bc2ir.appendInstruction(CacheOp.create(PREFETCH, bc2ir.popAddress()));
} else if (methodName == VM_MagicNames.pause) {
bc2ir.appendInstruction(Empty.create(PAUSE));
} else if (methodName == VM_MagicNames.getCallerFramePointer) {
OPT_Operand fp = bc2ir.popAddress();
OPT_RegisterOperand val = gc.temps.makeTemp(VM_TypeReference.Address);
bc2ir.appendInstruction(Load.create(REF_LOAD,
val,
fp,
new OPT_IntConstantOperand(STACKFRAME_FRAME_POINTER_OFFSET),
null));
bc2ir.push(val.copyD2U());
} else if (methodName == VM_MagicNames.setCallerFramePointer) {
OPT_Operand val = bc2ir.popAddress();
OPT_Operand fp = bc2ir.popAddress();
bc2ir.appendInstruction(Store.create(REF_STORE,
val,
fp,
new OPT_IntConstantOperand(STACKFRAME_FRAME_POINTER_OFFSET),
null));
} else if (methodName == VM_MagicNames.getCompiledMethodID) {
OPT_Operand fp = bc2ir.popAddress();
OPT_RegisterOperand val = gc.temps.makeTempInt();
bc2ir.appendInstruction(Load.create(INT_LOAD,
val,
fp,
new OPT_IntConstantOperand(STACKFRAME_METHOD_ID_OFFSET),
null));
bc2ir.push(val.copyD2U());
} else if (methodName == VM_MagicNames.setCompiledMethodID) {
OPT_Operand val = bc2ir.popInt();
OPT_Operand fp = bc2ir.popAddress();
bc2ir.appendInstruction(Store.create(INT_STORE,
val,
fp,
new OPT_IntConstantOperand(STACKFRAME_METHOD_ID_OFFSET),
null));
} else if (methodName == VM_MagicNames.getReturnAddressLocation) {
OPT_Operand fp = bc2ir.popAddress();
OPT_RegisterOperand val = gc.temps.makeTemp(VM_TypeReference.Address);
bc2ir.appendInstruction(Binary.create(REF_ADD,
val,
fp,
new OPT_IntConstantOperand(STACKFRAME_RETURN_ADDRESS_OFFSET)));
bc2ir.push(val.copyD2U());
} else {
// Distinguish between magics that we know we don't implement
// (and never plan to implement) and those (usually new ones)
// that we want to be warned that we don't implement.
String msg = " Magic method not implemented: " + meth;
if (methodName == VM_MagicNames.returnToNewStack) {
throw OPT_MagicNotImplementedException.EXPECTED(msg);
} else {
return false;
// throw OPT_MagicNotImplementedException.UNEXPECTED(msg);
}
}
return true;
}
}