Home | History | Annotate | Download | only in code
      1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
      2 // for details. All rights reserved. Use of this source code is governed by a
      3 // BSD-style license that can be found in the LICENSE file.
      4 package com.android.tools.r8.ir.code;
      5 
      6 import com.android.tools.r8.code.NegDouble;
      7 import com.android.tools.r8.code.NegFloat;
      8 import com.android.tools.r8.code.NegInt;
      9 import com.android.tools.r8.code.NegLong;
     10 import com.android.tools.r8.errors.Unreachable;
     11 import com.android.tools.r8.ir.conversion.DexBuilder;
     12 
     13 public class Neg extends Unop {
     14 
     15   public final NumericType type;
     16 
     17   public Neg(NumericType type, Value dest, Value source) {
     18     super(dest, source);
     19     this.type = type;
     20   }
     21 
     22   @Override
     23   public boolean canBeFolded() {
     24     return (type == NumericType.INT || type == NumericType.LONG || type == NumericType.FLOAT
     25             || type == NumericType.DOUBLE)
     26         && source().isConstant();
     27   }
     28 
     29   @Override
     30   public ConstInstruction fold(IRCode code) {
     31     assert canBeFolded();
     32     if (type == NumericType.INT) {
     33       int result = -source().getConstInstruction().asConstNumber().getIntValue();
     34       Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
     35       return new ConstNumber(ConstType.INT, value, result);
     36     } else if (type == NumericType.LONG) {
     37       long result = -source().getConstInstruction().asConstNumber().getLongValue();
     38       Value value = code.createValue(MoveType.WIDE, getDebugInfo());
     39       return new ConstNumber(ConstType.LONG, value, result);
     40     } else if (type == NumericType.FLOAT) {
     41       float result = -source().getConstInstruction().asConstNumber().getFloatValue();
     42       Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
     43       return new ConstNumber(ConstType.FLOAT, value, Float.floatToIntBits(result));
     44     } else {
     45       assert type == NumericType.DOUBLE;
     46       double result = -source().getConstInstruction().asConstNumber().getDoubleValue();
     47       Value value = code.createValue(MoveType.WIDE, getDebugInfo());
     48       return new ConstNumber(ConstType.DOUBLE, value, Double.doubleToLongBits(result));
     49     }
     50   }
     51 
     52   @Override
     53   public boolean identicalNonValueParts(Instruction other) {
     54     return other.asNeg().type == type;
     55   }
     56 
     57   @Override
     58   public int compareNonValueParts(Instruction other) {
     59     return type.ordinal() - other.asNeg().type.ordinal();
     60   }
     61 
     62   @Override
     63   public void buildDex(DexBuilder builder) {
     64     com.android.tools.r8.code.Instruction instruction;
     65     int dest = builder.allocatedRegister(dest(), getNumber());
     66     int src = builder.allocatedRegister(source(), getNumber());
     67     switch (type) {
     68       case INT:
     69         instruction = new NegInt(dest, src);
     70         break;
     71       case LONG:
     72         instruction = new NegLong(dest, src);
     73         break;
     74       case FLOAT:
     75         instruction = new NegFloat(dest, src);
     76         break;
     77       case DOUBLE:
     78         instruction = new NegDouble(dest, src);
     79         break;
     80       default:
     81         throw new Unreachable("Unexpected type " + type);
     82     }
     83     builder.add(this, instruction);
     84   }
     85 
     86   @Override
     87   public boolean isNeg() {
     88     return true;
     89   }
     90 
     91   @Override
     92   public Neg asNeg() {
     93     return this;
     94   }
     95 }
     96