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 }