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 }