001/* 002 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.compiler.common.type; 024 025import jdk.internal.jvmci.meta.*; 026 027import com.oracle.graal.compiler.common.spi.*; 028 029/** 030 * A stamp is the basis for a type system. 031 */ 032public abstract class Stamp { 033 034 protected Stamp() { 035 } 036 037 /** 038 * Returns the type of the stamp, guaranteed to be non-null. In some cases, this requires the 039 * lookup of class meta data, therefore the {@link MetaAccessProvider} is mandatory. 040 */ 041 public abstract ResolvedJavaType javaType(MetaAccessProvider metaAccess); 042 043 public boolean alwaysDistinct(Stamp other) { 044 return join(other).isEmpty(); 045 } 046 047 /** 048 * Gets a Java {@link Kind} that can be used to store a value of this stamp on the Java bytecode 049 * stack. Returns {@link Kind#Illegal} if a value of this stamp can not be stored on the 050 * bytecode stack. 051 */ 052 public abstract Kind getStackKind(); 053 054 /** 055 * Gets a platform dependent {@link LIRKind} that can be used to store a value of this stamp. 056 */ 057 public abstract LIRKind getLIRKind(LIRKindTool tool); 058 059 /** 060 * Returns the union of this stamp and the given stamp. Typically used to create stamps for phi 061 * nodes. 062 * 063 * @param other The stamp that will enlarge this stamp. 064 * @return The union of this stamp and the given stamp. 065 */ 066 public abstract Stamp meet(Stamp other); 067 068 /** 069 * Returns the intersection of this stamp and the given stamp. 070 * 071 * @param other The stamp that will tighten this stamp. 072 * @return The intersection of this stamp and the given stamp. 073 */ 074 public abstract Stamp join(Stamp other); 075 076 /** 077 * Returns a stamp of the same kind, but allowing the full value range of the kind. 078 * 079 * {@link #unrestricted()} is the neutral element of the {@link #join(Stamp)} operation. 080 */ 081 public abstract Stamp unrestricted(); 082 083 /** 084 * Returns a stamp of the same kind, but with no allowed values. 085 * 086 * {@link #empty()} is the neutral element of the {@link #meet(Stamp)} operation. 087 */ 088 public abstract Stamp empty(); 089 090 /** 091 * If it is possible to represent single value stamps of this kind, this method returns the 092 * stamp representing the single value c. stamp.constant(c).asConstant() should be equal to c. 093 * <p> 094 * If it is not possible to represent single value stamps, this method returns a stamp that 095 * includes c, and is otherwise as narrow as possible. 096 */ 097 public abstract Stamp constant(Constant c, MetaAccessProvider meta); 098 099 /** 100 * Test whether two stamps have the same base type. 101 */ 102 public abstract boolean isCompatible(Stamp other); 103 104 /** 105 * Test whether this stamp has legal values. 106 */ 107 public abstract boolean hasValues(); 108 109 /** 110 * Tests whether this stamp represents an illegal value. 111 */ 112 public final boolean isEmpty() { 113 return !hasValues(); 114 } 115 116 /** 117 * If this stamp represents a single value, the methods returns this single value. It returns 118 * null otherwise. 119 * 120 * @return the constant corresponding to the single value of this stamp and null if this stamp 121 * can represent less or more than one value. 122 */ 123 public Constant asConstant() { 124 return null; 125 } 126 127 /** 128 * Read a value of this stamp from memory. 129 */ 130 public abstract Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement); 131 132 /** 133 * Tries to improve this stamp with the stamp given as parameter. If successful, returns the new 134 * improved stamp. Otherwise, returns a stamp equal to this. 135 * 136 * @param other the stamp that should be used to improve this stamp 137 * @return the newly improved stamp or a stamp equal to {@code this} if an improvement was not 138 * possible 139 */ 140 public abstract Stamp improveWith(Stamp other); 141 142 /** 143 * Tries to improve this stamp with the stamp given as parameter. If successful, returns the new 144 * improved stamp. Otherwise, returns null. 145 * 146 * @param other the stamp that should be used to improve this stamp 147 * @return the newly improved stamp or {@code null} if an improvement was not possible 148 */ 149 public final Stamp tryImproveWith(Stamp other) { 150 Stamp improved = improveWith(other); 151 if (improved.equals(this)) { 152 return null; 153 } 154 return improved; 155 } 156 157 public boolean neverDistinct(Stamp other) { 158 Constant constant = this.asConstant(); 159 if (constant != null) { 160 Constant otherConstant = other.asConstant(); 161 return otherConstant != null && constant.equals(otherConstant); 162 } 163 return false; 164 } 165}