1418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
2418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// for details. All rights reserved. Use of this source code is governed by a
3418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// BSD-style license that can be found in the LICENSE file.
4418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerpackage com.android.tools.r8.ir.code;
5418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
6418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.code.NegDouble;
7418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.code.NegFloat;
8418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.code.NegInt;
9418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.code.NegLong;
10418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.errors.Unreachable;
11418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.ir.conversion.DexBuilder;
12418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
13418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerpublic class Neg extends Unop {
14418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
15418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public final NumericType type;
16418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
17418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public Neg(NumericType type, Value dest, Value source) {
18418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    super(dest, source);
19418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    this.type = type;
20418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
21418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
22418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  @Override
23418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public boolean canBeFolded() {
24418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return (type == NumericType.INT || type == NumericType.LONG || type == NumericType.FLOAT
25418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager            || type == NumericType.DOUBLE)
26418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        && source().isConstant();
27418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
28418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
29418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  @Override
30fda18f74bf4e484a70c0dff0ef04d4571ee6cd8fSøren Gjesse  public ConstInstruction fold(IRCode code) {
31418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    assert canBeFolded();
32418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    if (type == NumericType.INT) {
33418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      int result = -source().getConstInstruction().asConstNumber().getIntValue();
34fda18f74bf4e484a70c0dff0ef04d4571ee6cd8fSøren Gjesse      Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
35418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      return new ConstNumber(ConstType.INT, value, result);
36418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    } else if (type == NumericType.LONG) {
37418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      long result = -source().getConstInstruction().asConstNumber().getLongValue();
38fda18f74bf4e484a70c0dff0ef04d4571ee6cd8fSøren Gjesse      Value value = code.createValue(MoveType.WIDE, getDebugInfo());
39418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      return new ConstNumber(ConstType.LONG, value, result);
40418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    } else if (type == NumericType.FLOAT) {
41418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      float result = -source().getConstInstruction().asConstNumber().getFloatValue();
42fda18f74bf4e484a70c0dff0ef04d4571ee6cd8fSøren Gjesse      Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
43418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      return new ConstNumber(ConstType.FLOAT, value, Float.floatToIntBits(result));
44418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    } else {
45418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      assert type == NumericType.DOUBLE;
46418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      double result = -source().getConstInstruction().asConstNumber().getDoubleValue();
47fda18f74bf4e484a70c0dff0ef04d4571ee6cd8fSøren Gjesse      Value value = code.createValue(MoveType.WIDE, getDebugInfo());
48418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      return new ConstNumber(ConstType.DOUBLE, value, Double.doubleToLongBits(result));
49418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
50418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
51418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
52418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  @Override
53418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public boolean identicalNonValueParts(Instruction other) {
54418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return other.asNeg().type == type;
55418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
56418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
57418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  @Override
58418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public int compareNonValueParts(Instruction other) {
59418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return type.ordinal() - other.asNeg().type.ordinal();
60418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
61418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
62418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  @Override
63418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public void buildDex(DexBuilder builder) {
64418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    com.android.tools.r8.code.Instruction instruction;
65418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    int dest = builder.allocatedRegister(dest(), getNumber());
66418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    int src = builder.allocatedRegister(source(), getNumber());
67418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    switch (type) {
68418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      case INT:
69418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        instruction = new NegInt(dest, src);
70418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        break;
71418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      case LONG:
72418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        instruction = new NegLong(dest, src);
73418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        break;
74418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      case FLOAT:
75418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        instruction = new NegFloat(dest, src);
76418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        break;
77418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      case DOUBLE:
78418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        instruction = new NegDouble(dest, src);
79418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        break;
80418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      default:
81418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        throw new Unreachable("Unexpected type " + type);
82418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
83418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    builder.add(this, instruction);
84418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
85418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
86418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  @Override
87418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public boolean isNeg() {
88418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return true;
89418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
90418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
91418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  @Override
92418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public Neg asNeg() {
93418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return this;
94418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
95418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager}
96