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.lir2mir.ia32; 014 015 import org.jikesrvm.classloader.TypeReference; 016 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 017 import org.jikesrvm.compilers.opt.ir.Binary; 018 import org.jikesrvm.compilers.opt.ir.Load; 019 import org.jikesrvm.compilers.opt.ir.IR; 020 import org.jikesrvm.compilers.opt.ir.Instruction; 021 import org.jikesrvm.compilers.opt.ir.Operators; 022 import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand; 023 import org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand; 024 import org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand; 025 import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand; 026 import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand; 027 import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand; 028 import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 029 import org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand; 030 import org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand; 031 import org.jikesrvm.compilers.opt.ir.operand.Operand; 032 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 033 import org.jikesrvm.compilers.opt.ir.operand.StringConstantOperand; 034 import org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand; 035 import org.jikesrvm.runtime.Magic; 036 import org.jikesrvm.runtime.Statics; 037 import org.vmmagic.unboxed.Offset; 038 039 /** 040 * Normalize the use of constants in the LIR 041 * to match the patterns supported in LIR2MIR.rules 042 */ 043 public abstract class NormalizeConstants implements Operators { 044 045 /** 046 * Only thing we do for IA32 is to restrict the usage of 047 * String, Float, and Double constants. The rules are prepared 048 * to deal with everything else. 049 * 050 * @param ir IR to normalize 051 */ 052 public static void perform(IR ir) { 053 for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) { 054 055 // Get 'large' constants into a form the the BURS rules are 056 // prepared to deal with. 057 // Constants can't appear as defs, so only scan the uses. 058 // 059 int numUses = s.getNumberOfUses(); 060 if (numUses > 0) { 061 int numDefs = s.getNumberOfDefs(); 062 for (int idx = numDefs; idx < numUses + numDefs; idx++) { 063 Operand use = s.getOperand(idx); 064 if (use != null) { 065 if (use instanceof ObjectConstantOperand) { 066 ObjectConstantOperand oc = (ObjectConstantOperand) use; 067 if(oc.isMovableObjectConstant()) { 068 RegisterOperand rop = ir.regpool.makeTemp(use.getType()); 069 Operand jtoc = ir.regpool.makeJTOCOp(ir, s); 070 Offset offset = oc.offset; 071 if (offset.isZero()) { 072 if (use instanceof StringConstantOperand) { 073 throw new OptimizingCompilerException("String constant w/o valid JTOC offset"); 074 } else if (use instanceof ClassConstantOperand) { 075 throw new OptimizingCompilerException("Class constant w/o valid JTOC offset"); 076 } 077 offset = Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(oc.value)); 078 } 079 LocationOperand loc = new LocationOperand(offset); 080 s.insertBefore(Load.create(INT_LOAD, rop, jtoc, new IntConstantOperand(offset.toInt()), loc)); 081 s.putOperand(idx, rop.copyD2U()); 082 } else { 083 // Ensure object is in JTOC to keep it alive 084 Statics.findOrCreateObjectLiteral(oc.value); 085 s.putOperand(idx, new IntConstantOperand(Magic.objectAsAddress(oc.value).toInt())); 086 } 087 } else if (use instanceof DoubleConstantOperand) { 088 RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Double); 089 Operand jtoc = ir.regpool.makeJTOCOp(ir, s); 090 DoubleConstantOperand dc = (DoubleConstantOperand) use.copy(); 091 if (dc.offset.isZero()) { 092 dc.offset = 093 Offset.fromIntSignExtend(Statics.findOrCreateLongSizeLiteral(Double.doubleToLongBits(dc.value))); 094 } 095 s.insertBefore(Binary.create(MATERIALIZE_FP_CONSTANT, rop, jtoc, dc)); 096 s.putOperand(idx, rop.copyD2U()); 097 } else if (use instanceof FloatConstantOperand) { 098 RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Float); 099 Operand jtoc = ir.regpool.makeJTOCOp(ir, s); 100 FloatConstantOperand fc = (FloatConstantOperand) use.copy(); 101 if (fc.offset.isZero()) { 102 fc.offset = 103 Offset.fromIntSignExtend(Statics.findOrCreateIntSizeLiteral(Float.floatToIntBits(fc.value))); 104 } 105 s.insertBefore(Binary.create(MATERIALIZE_FP_CONSTANT, rop, jtoc, fc)); 106 s.putOperand(idx, rop.copyD2U()); 107 } else if (use instanceof NullConstantOperand) { 108 s.putOperand(idx, new IntConstantOperand(0)); 109 } else if (use instanceof AddressConstantOperand) { 110 int v = ((AddressConstantOperand) use).value.toInt(); 111 s.putOperand(idx, new IntConstantOperand(v)); 112 } else if (use instanceof TIBConstantOperand) { 113 RegisterOperand rop = ir.regpool.makeTemp(TypeReference.TIB); 114 Operand jtoc = ir.regpool.makeJTOCOp(ir, s); 115 Offset offset = ((TIBConstantOperand) use).value.getTibOffset(); 116 LocationOperand loc = new LocationOperand(offset); 117 s.insertBefore(Load.create(INT_LOAD, rop, jtoc, new IntConstantOperand(offset.toInt()), loc)); 118 s.putOperand(idx, rop.copyD2U()); 119 } else if (use instanceof CodeConstantOperand) { 120 RegisterOperand rop = ir.regpool.makeTemp(TypeReference.CodeArray); 121 Operand jtoc = ir.regpool.makeJTOCOp(ir, s); 122 Offset offset = ((CodeConstantOperand) use).value.findOrCreateJtocOffset(); 123 LocationOperand loc = new LocationOperand(offset); 124 s.insertBefore(Load.create(INT_LOAD, rop, jtoc, new IntConstantOperand(offset.toInt()), loc)); 125 s.putOperand(idx, rop.copyD2U()); 126 } 127 } 128 } 129 } 130 } 131 } 132 133 /** 134 * IA32 supports 32 bit int immediates, so nothing to do. 135 */ 136 static Operand asImmediateOrReg(Operand addr, Instruction s, IR ir) { 137 return addr; 138 } 139 140 }