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