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    }