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 package org.graalvm.compiler.lir.gen;
  24 
  25 import org.graalvm.compiler.core.common.LIRKind;
  26 import org.graalvm.compiler.lir.Variable;
  27 
  28 import jdk.vm.ci.meta.AllocatableValue;
  29 import jdk.vm.ci.meta.PlatformKind;
  30 import jdk.vm.ci.meta.Value;
  31 
  32 /**
  33  * This class traverses the HIR instructions and generates LIR instructions from them.
  34  */
  35 public abstract class ArithmeticLIRGenerator implements ArithmeticLIRGeneratorTool {
  36 
  37     LIRGenerator lirGen;
  38 
  39     public LIRGenerator getLIRGen() {
  40         return lirGen;
  41     }
  42 
  43     // automatic derived reference handling
  44 
  45     protected abstract boolean isNumericInteger(PlatformKind kind);
  46 
  47     protected abstract Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags);
  48 
  49     @Override
  50     public final Variable emitAdd(Value aVal, Value bVal, boolean setFlags) {
  51         LIRKind resultKind;
  52         Value a = aVal;
  53         Value b = bVal;
  54 
  55         if (isNumericInteger(a.getPlatformKind())) {
  56             LIRKind aKind = a.getValueKind(LIRKind.class);
  57             LIRKind bKind = b.getValueKind(LIRKind.class);
  58             assert a.getPlatformKind() == b.getPlatformKind();
  59 
  60             if (aKind.isUnknownReference()) {
  61                 resultKind = aKind;
  62             } else if (bKind.isUnknownReference()) {
  63                 resultKind = bKind;
  64             } else if (aKind.isValue() && bKind.isValue()) {
  65                 resultKind = aKind;
  66             } else if (aKind.isValue()) {
  67                 if (bKind.isDerivedReference()) {
  68                     resultKind = bKind;
  69                 } else {
  70                     AllocatableValue allocatable = getLIRGen().asAllocatable(b);
  71                     resultKind = bKind.makeDerivedReference(allocatable);
  72                     b = allocatable;
  73                 }
  74             } else if (bKind.isValue()) {
  75                 if (aKind.isDerivedReference()) {
  76                     resultKind = aKind;
  77                 } else {
  78                     AllocatableValue allocatable = getLIRGen().asAllocatable(a);
  79                     resultKind = aKind.makeDerivedReference(allocatable);
  80                     a = allocatable;
  81                 }
  82             } else {
  83                 resultKind = aKind.makeUnknownReference();
  84             }
  85         } else {
  86             resultKind = LIRKind.combine(a, b);
  87         }
  88 
  89         return emitAdd(resultKind, a, b, setFlags);
  90     }
  91 
  92     protected abstract Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags);
  93 
  94     @Override
  95     public final Variable emitSub(Value aVal, Value bVal, boolean setFlags) {
  96         LIRKind resultKind;
  97         Value a = aVal;
  98         Value b = bVal;
  99 
 100         if (isNumericInteger(a.getPlatformKind())) {
 101             LIRKind aKind = a.getValueKind(LIRKind.class);
 102             LIRKind bKind = b.getValueKind(LIRKind.class);
 103             assert a.getPlatformKind() == b.getPlatformKind();
 104 
 105             if (aKind.isUnknownReference()) {
 106                 resultKind = aKind;
 107             } else if (bKind.isUnknownReference()) {
 108                 resultKind = bKind;
 109             }
 110 
 111             if (aKind.isValue() && bKind.isValue()) {
 112                 resultKind = aKind;
 113             } else if (bKind.isValue()) {
 114                 if (aKind.isDerivedReference()) {
 115                     resultKind = aKind;
 116                 } else {
 117                     AllocatableValue allocatable = getLIRGen().asAllocatable(a);
 118                     resultKind = aKind.makeDerivedReference(allocatable);
 119                     a = allocatable;
 120                 }
 121             } else if (aKind.isDerivedReference() && bKind.isDerivedReference() && aKind.getDerivedReferenceBase().equals(bKind.getDerivedReferenceBase())) {
 122                 resultKind = LIRKind.value(a.getPlatformKind());
 123             } else {
 124                 resultKind = aKind.makeUnknownReference();
 125             }
 126         } else {
 127             resultKind = LIRKind.combine(a, b);
 128         }
 129 
 130         return emitSub(resultKind, a, b, setFlags);
 131     }
 132 }