1 /*
2  * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 
25 package org.graalvm.compiler.lir.gen;
26 
27 import org.graalvm.compiler.core.common.LIRKind;
28 import org.graalvm.compiler.lir.Variable;
29 import org.graalvm.compiler.options.OptionValues;
30 
31 import jdk.vm.ci.meta.AllocatableValue;
32 import jdk.vm.ci.meta.PlatformKind;
33 import jdk.vm.ci.meta.Value;
34 
35 /**
36  * This class traverses the HIR instructions and generates LIR instructions from them.
37  */
38 public abstract class ArithmeticLIRGenerator implements ArithmeticLIRGeneratorTool {
39 
40     LIRGenerator lirGen;
41 
getLIRGen()42     public LIRGenerator getLIRGen() {
43         return lirGen;
44     }
45 
asAllocatable(Value value)46     protected final AllocatableValue asAllocatable(Value value) {
47         return lirGen.asAllocatable(value);
48     }
49 
getOptions()50     public OptionValues getOptions() {
51         return getLIRGen().getResult().getLIR().getOptions();
52     }
53     // automatic derived reference handling
54 
isNumericInteger(PlatformKind kind)55     protected abstract boolean isNumericInteger(PlatformKind kind);
56 
emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags)57     protected abstract Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags);
58 
emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags)59     protected abstract Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags);
60 
61     @Override
emitAdd(Value aVal, Value bVal, boolean setFlags)62     public final Variable emitAdd(Value aVal, Value bVal, boolean setFlags) {
63         return emitAddOrSub(aVal, bVal, setFlags, true);
64     }
65 
66     @Override
emitSub(Value aVal, Value bVal, boolean setFlags)67     public final Variable emitSub(Value aVal, Value bVal, boolean setFlags) {
68         return emitAddOrSub(aVal, bVal, setFlags, false);
69     }
70 
emitAddOrSub(Value aVal, Value bVal, boolean setFlags, boolean isAdd)71     private Variable emitAddOrSub(Value aVal, Value bVal, boolean setFlags, boolean isAdd) {
72         LIRKind resultKind;
73         Value a = aVal;
74         Value b = bVal;
75 
76         if (isNumericInteger(a.getPlatformKind())) {
77             LIRKind aKind = a.getValueKind(LIRKind.class);
78             LIRKind bKind = b.getValueKind(LIRKind.class);
79             assert a.getPlatformKind() == b.getPlatformKind() : a.getPlatformKind() + " vs. " + b.getPlatformKind();
80 
81             if (aKind.isUnknownReference()) {
82                 resultKind = aKind;
83             } else if (bKind.isUnknownReference()) {
84                 resultKind = bKind;
85             } else if (aKind.isValue() && bKind.isValue()) {
86                 resultKind = aKind;
87             } else if (aKind.isValue()) {
88                 if (bKind.isDerivedReference()) {
89                     resultKind = bKind;
90                 } else {
91                     AllocatableValue allocatable = asAllocatable(b);
92                     resultKind = bKind.makeDerivedReference(allocatable);
93                     b = allocatable;
94                 }
95             } else if (bKind.isValue()) {
96                 if (aKind.isDerivedReference()) {
97                     resultKind = aKind;
98                 } else {
99                     AllocatableValue allocatable = asAllocatable(a);
100                     resultKind = aKind.makeDerivedReference(allocatable);
101                     a = allocatable;
102                 }
103             } else {
104                 resultKind = aKind.makeUnknownReference();
105             }
106         } else {
107             resultKind = LIRKind.combine(a, b);
108         }
109 
110         return isAdd ? emitAdd(resultKind, a, b, setFlags) : emitSub(resultKind, a, b, setFlags);
111     }
112 
113 }
114