001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt.bc2ir.ia32; 014 015import static org.jikesrvm.compilers.opt.ir.IRTools.offsetOperand; 016import static org.jikesrvm.compilers.opt.ir.Operators.GETFIELD; 017import static org.jikesrvm.compilers.opt.ir.Operators.INT_LOAD; 018import static org.jikesrvm.compilers.opt.ir.Operators.INT_STORE; 019import static org.jikesrvm.compilers.opt.ir.Operators.REF_ADD; 020import static org.jikesrvm.compilers.opt.ir.Operators.REF_LOAD; 021import static org.jikesrvm.compilers.opt.ir.Operators.REF_MOVE; 022import static org.jikesrvm.compilers.opt.ir.Operators.REF_STORE; 023import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.PAUSE; 024import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.PREFETCH; 025import static org.jikesrvm.ia32.StackframeLayoutConstants.STACKFRAME_FRAME_POINTER_OFFSET; 026import static org.jikesrvm.ia32.StackframeLayoutConstants.STACKFRAME_METHOD_ID_OFFSET; 027import static org.jikesrvm.ia32.StackframeLayoutConstants.STACKFRAME_RETURN_ADDRESS_OFFSET; 028 029import org.jikesrvm.classloader.Atom; 030import org.jikesrvm.classloader.MethodReference; 031import org.jikesrvm.classloader.RVMField; 032import org.jikesrvm.classloader.TypeReference; 033import org.jikesrvm.compilers.opt.MagicNotImplementedException; 034import org.jikesrvm.compilers.opt.bc2ir.BC2IR; 035import org.jikesrvm.compilers.opt.bc2ir.GenerationContext; 036import org.jikesrvm.compilers.opt.ir.CacheOp; 037import org.jikesrvm.compilers.opt.ir.Empty; 038import org.jikesrvm.compilers.opt.ir.GetField; 039import org.jikesrvm.compilers.opt.ir.Instruction; 040import org.jikesrvm.compilers.opt.ir.Load; 041import org.jikesrvm.compilers.opt.ir.Move; 042import org.jikesrvm.compilers.opt.ir.Store; 043import org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet; 044import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand; 045import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 046import org.jikesrvm.compilers.opt.ir.operand.Operand; 047import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 048import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand; 049import org.jikesrvm.runtime.ArchEntrypoints; 050import org.jikesrvm.runtime.Magic; 051import org.jikesrvm.runtime.MagicNames; 052 053/** 054 * This class implements the machine-specific magics for the opt compiler. 055 * 056 * @see org.jikesrvm.compilers.opt.bc2ir.GenerateMagic for the machine-independent magics 057 */ 058public abstract class GenerateMachineSpecificMagic { 059 060 /** 061 * "Semantic inlining" of methods of the Magic class. 062 * Based on the methodName, generate a sequence of opt instructions 063 * that implement the magic, updating the stack as necessary 064 * 065 * @param bc2ir the bc2ir object generating the ir containing this magic 066 * @param gc == bc2ir.gc 067 * @param meth the RVMMethod that is the magic method 068 * @return {@code true} if and only if magic was generated 069 */ 070 public static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth) 071 throws MagicNotImplementedException { 072 073 Atom methodName = meth.getName(); 074 PhysicalRegisterSet phys = gc.getTemps().getPhysicalRegisterSet().asIA32(); 075 076 if (methodName == MagicNames.getESIAsThread) { 077 RegisterOperand rop = gc.getTemps().makeTROp(); 078 bc2ir.markGuardlessNonNull(rop); 079 bc2ir.push(rop); 080 } else if (methodName == MagicNames.setESIAsThread) { 081 Operand val = bc2ir.popRef(); 082 if (val instanceof RegisterOperand) { 083 bc2ir.appendInstruction(Move.create(REF_MOVE, gc.getTemps().makeTROp(), val)); 084 } else { 085 String msg = " Unexpected operand Magic.setESIAsThread"; 086 throw MagicNotImplementedException.UNEXPECTED(msg); 087 } 088 } else if (methodName == MagicNames.getFramePointer) { 089 gc.forceFrameAllocation(); 090 RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address); 091 RVMField f = ArchEntrypoints.framePointerField; 092 RegisterOperand pr = new RegisterOperand(phys.getESI(), TypeReference.Address); 093 bc2ir.appendInstruction(GetField.create(GETFIELD, 094 val, 095 pr.copy(), 096 new AddressConstantOperand(f.getOffset()), 097 new LocationOperand(f), 098 new TrueGuardOperand())); 099 bc2ir.push(val.copyD2U()); 100 } else if (methodName == MagicNames.getJTOC || methodName == MagicNames.getTocPointer) { 101 TypeReference t = (methodName == MagicNames.getJTOC ? TypeReference.IntArray : TypeReference.Address); 102 RegisterOperand val = gc.getTemps().makeTemp(t); 103 AddressConstantOperand addr = new AddressConstantOperand(Magic.getTocPointer()); 104 bc2ir.appendInstruction(Move.create(REF_MOVE, val, addr)); 105 bc2ir.push(val.copyD2U()); 106 } else if (methodName == MagicNames.isync) { 107 // nothing required on Intel 108 } else if (methodName == MagicNames.sync) { 109 // nothing required on Intel 110 } else if (methodName == MagicNames.prefetch) { 111 bc2ir.appendInstruction(CacheOp.create(PREFETCH, bc2ir.popAddress())); 112 } else if (methodName == MagicNames.pause) { 113 bc2ir.appendInstruction(Empty.create(PAUSE)); 114 } else if (methodName == MagicNames.getCallerFramePointer) { 115 Operand fp = bc2ir.popAddress(); 116 RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address); 117 bc2ir.appendInstruction(Load.create(REF_LOAD, 118 val, 119 fp, 120 offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), 121 null)); 122 bc2ir.push(val.copyD2U()); 123 } else if (methodName == MagicNames.setCallerFramePointer) { 124 Operand val = bc2ir.popAddress(); 125 Operand fp = bc2ir.popAddress(); 126 bc2ir.appendInstruction(Store.create(REF_STORE, 127 val, 128 fp, 129 offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), 130 null)); 131 } else if (methodName == MagicNames.getCompiledMethodID) { 132 Operand fp = bc2ir.popAddress(); 133 RegisterOperand val = gc.getTemps().makeTempInt(); 134 bc2ir.appendInstruction(Load.create(INT_LOAD, 135 val, 136 fp, 137 offsetOperand(STACKFRAME_METHOD_ID_OFFSET), 138 null)); 139 bc2ir.push(val.copyD2U()); 140 } else if (methodName == MagicNames.setCompiledMethodID) { 141 Operand val = bc2ir.popInt(); 142 Operand fp = bc2ir.popAddress(); 143 bc2ir.appendInstruction(Store.create(INT_STORE, 144 val, 145 fp, 146 offsetOperand(STACKFRAME_METHOD_ID_OFFSET), 147 null)); 148 } else if (methodName == MagicNames.getReturnAddressLocation) { 149 Operand fp = bc2ir.popAddress(); 150 Instruction s = bc2ir._binaryHelper(REF_ADD, fp, offsetOperand(STACKFRAME_RETURN_ADDRESS_OFFSET), TypeReference.Address); 151 bc2ir.appendInstruction(s); 152 } else { 153 // Distinguish between magics that we know we don't implement 154 // (and never plan to implement) and those (usually new ones) 155 // that we want to be warned that we don't implement. 156 String msg = " Magic method not implemented: " + meth; 157 if (methodName == MagicNames.returnToNewStack) { 158 throw MagicNotImplementedException.EXPECTED(msg); 159 } else { 160 return false; 161 // throw MagicNotImplementedException.UNEXPECTED(msg); 162 } 163 } 164 return true; 165 } 166}