/* * 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.ia32; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.OPT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.Binary; import org.jikesrvm.compilers.opt.ir.Load; import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_ClassConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_CodeConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_DoubleConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_FloatConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_IR; import org.jikesrvm.compilers.opt.ir.OPT_Instruction; import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_LocationOperand; import org.jikesrvm.compilers.opt.ir.OPT_NullConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_ObjectConstantOperand; 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_StringConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_TIBConstantOperand; import org.jikesrvm.runtime.VM_Magic; import org.jikesrvm.runtime.VM_Statics; import org.vmmagic.unboxed.Offset; //TODO - Deal with Subarch /** * Normalize the use of constants in the LIR * to match the patterns supported in LIR2MIR.rules */ public abstract class OPT_NormalizeConstants implements OPT_Operators { /** * Only thing we do for IA32 is to restrict the usage of * String, Float, and Double constants. The rules are prepared * to deal with everything else. * * @param ir IR to normalize */ public static void perform(OPT_IR ir) { for (OPT_Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) { // Get 'large' constants into a form the the BURS rules are // prepared to deal with. // Constants can't appear as defs, so only scan the uses. // int numUses = s.getNumberOfUses(); if (numUses > 0) { int numDefs = s.getNumberOfDefs(); for (int idx = numDefs; idx < numUses + numDefs; idx++) { OPT_Operand use = s.getOperand(idx); if (use != null) { if (use instanceof OPT_ObjectConstantOperand) { OPT_ObjectConstantOperand oc = (OPT_ObjectConstantOperand) use; if(oc.moveable) { OPT_RegisterOperand rop = ir.regpool.makeTemp(use.getType()); OPT_Operand jtoc = ir.regpool.makeJTOCOp(ir, s); Offset offset = oc.offset; if (offset.isZero()) { if (use instanceof OPT_StringConstantOperand) { throw new OPT_OptimizingCompilerException("String constant w/o valid JTOC offset"); } else if (use instanceof OPT_ClassConstantOperand) { throw new OPT_OptimizingCompilerException("Class constant w/o valid JTOC offset"); } offset = Offset.fromIntSignExtend(VM_Statics.findOrCreateObjectLiteral(oc.value)); } OPT_LocationOperand loc = new OPT_LocationOperand(offset); s.insertBefore(Load.create(INT_LOAD, rop, jtoc, new OPT_IntConstantOperand(offset.toInt()), loc)); s.putOperand(idx, rop.copyD2U()); } else { s.putOperand(idx, new OPT_IntConstantOperand(VM_Magic.objectAsAddress(oc.value).toInt())); } } else if (use instanceof OPT_DoubleConstantOperand) { OPT_RegisterOperand rop = ir.regpool.makeTemp(VM_TypeReference.Double); OPT_Operand jtoc = ir.regpool.makeJTOCOp(ir, s); OPT_DoubleConstantOperand dc = (OPT_DoubleConstantOperand) use.copy(); if (dc.offset.isZero()) { dc.offset = Offset.fromIntSignExtend(VM_Statics.findOrCreateLongSizeLiteral(Double.doubleToLongBits(dc.value))); } s.insertBefore(Binary.create(MATERIALIZE_FP_CONSTANT, rop, jtoc, dc)); s.putOperand(idx, rop.copyD2U()); } else if (use instanceof OPT_FloatConstantOperand) { OPT_RegisterOperand rop = ir.regpool.makeTemp(VM_TypeReference.Float); OPT_Operand jtoc = ir.regpool.makeJTOCOp(ir, s); OPT_FloatConstantOperand fc = (OPT_FloatConstantOperand) use.copy(); if (fc.offset.isZero()) { fc.offset = Offset.fromIntSignExtend(VM_Statics.findOrCreateIntSizeLiteral(Float.floatToIntBits(fc.value))); } s.insertBefore(Binary.create(MATERIALIZE_FP_CONSTANT, rop, jtoc, fc)); s.putOperand(idx, rop.copyD2U()); } else if (use instanceof OPT_NullConstantOperand) { s.putOperand(idx, new OPT_IntConstantOperand(0)); } else if (use instanceof OPT_AddressConstantOperand) { int v = ((OPT_AddressConstantOperand) use).value.toInt(); s.putOperand(idx, new OPT_IntConstantOperand(v)); } else if (use instanceof OPT_TIBConstantOperand) { OPT_RegisterOperand rop = ir.regpool.makeTemp(VM_TypeReference.JavaLangObjectArray); OPT_Operand jtoc = ir.regpool.makeJTOCOp(ir, s); Offset offset = ((OPT_TIBConstantOperand) use).value.getTibOffset(); OPT_LocationOperand loc = new OPT_LocationOperand(offset); s.insertBefore(Load.create(INT_LOAD, rop, jtoc, new OPT_IntConstantOperand(offset.toInt()), loc)); s.putOperand(idx, rop.copyD2U()); } else if (use instanceof OPT_CodeConstantOperand) { OPT_RegisterOperand rop = ir.regpool.makeTemp(VM_TypeReference.CodeArray); OPT_Operand jtoc = ir.regpool.makeJTOCOp(ir, s); Offset offset = ((OPT_CodeConstantOperand) use).value.findOrCreateJtocOffset(false); OPT_LocationOperand loc = new OPT_LocationOperand(offset); s.insertBefore(Load.create(INT_LOAD, rop, jtoc, new OPT_IntConstantOperand(offset.toInt()), loc)); s.putOperand(idx, rop.copyD2U()); } } } } } } /** * IA32 supports 32 bit int immediates, so nothing to do. */ static OPT_Operand asImmediateOrReg(OPT_Operand addr, OPT_Instruction s, OPT_IR ir) { return addr; } }