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