001/*
002 * Copyright (c) 2012, 2014, 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.word;
024
025import jdk.internal.jvmci.meta.*;
026
027import com.oracle.graal.compiler.common.type.*;
028import com.oracle.graal.nodes.*;
029import com.oracle.graal.nodes.type.*;
030import com.oracle.graal.word.Word.Operation;
031
032/**
033 * Encapsulates information for Java types representing raw words (as opposed to Objects).
034 */
035public class WordTypes {
036
037    /**
038     * Resolved type for {@link WordBase}.
039     */
040    private final ResolvedJavaType wordBaseType;
041
042    /**
043     * Resolved type for {@link Word}.
044     */
045    private final ResolvedJavaType wordImplType;
046
047    /**
048     * Resolved type for {@link ObjectAccess}.
049     */
050    private final ResolvedJavaType objectAccessType;
051
052    /**
053     * Resolved type for {@link BarrieredAccess}.
054     */
055    private final ResolvedJavaType barrieredAccessType;
056
057    private final Kind wordKind;
058
059    public WordTypes(MetaAccessProvider metaAccess, Kind wordKind) {
060        this.wordKind = wordKind;
061        this.wordBaseType = metaAccess.lookupJavaType(WordBase.class);
062        this.wordImplType = metaAccess.lookupJavaType(Word.class);
063        this.objectAccessType = metaAccess.lookupJavaType(ObjectAccess.class);
064        this.barrieredAccessType = metaAccess.lookupJavaType(BarrieredAccess.class);
065    }
066
067    /**
068     * Determines if a given method denotes a word operation.
069     */
070    public boolean isWordOperation(ResolvedJavaMethod targetMethod) {
071        final boolean isObjectAccess = objectAccessType.equals(targetMethod.getDeclaringClass());
072        final boolean isBarrieredAccess = barrieredAccessType.equals(targetMethod.getDeclaringClass());
073        if (isObjectAccess || isBarrieredAccess) {
074            assert targetMethod.getAnnotation(Operation.class) != null : targetMethod + " should be annotated with @" + Operation.class.getSimpleName();
075            return true;
076        }
077        return isWord(targetMethod.getDeclaringClass());
078    }
079
080    /**
081     * Gets the method annotated with {@link Operation} based on a given method that represents a
082     * word operation (but may not necessarily have the annotation).
083     *
084     * @param callingContextType the {@linkplain ResolvedJavaType type} from which
085     *            {@code targetMethod} is invoked
086     * @return the {@link Operation} method resolved for {@code targetMethod} if any
087     */
088    public ResolvedJavaMethod getWordOperation(ResolvedJavaMethod targetMethod, ResolvedJavaType callingContextType) {
089        final boolean isWordBase = wordBaseType.isAssignableFrom(targetMethod.getDeclaringClass());
090        ResolvedJavaMethod wordMethod = targetMethod;
091        if (isWordBase && !targetMethod.isStatic()) {
092            assert wordImplType.isLinked();
093            wordMethod = wordImplType.resolveConcreteMethod(targetMethod, callingContextType);
094        }
095        assert wordMethod != null : targetMethod;
096        assert wordMethod.getAnnotation(Operation.class) != null : wordMethod;
097        return wordMethod;
098    }
099
100    /**
101     * Determines if a given node has a word type.
102     */
103    public boolean isWord(ValueNode node) {
104        return isWord(StampTool.typeOrNull(node));
105    }
106
107    /**
108     * Determines if a given type is a word type.
109     */
110    public boolean isWord(ResolvedJavaType type) {
111        return type != null && wordBaseType.isAssignableFrom(type);
112    }
113
114    /**
115     * Gets the kind for a given type, returning the {@linkplain #getWordKind() word kind} if
116     * {@code type} is a {@linkplain #isWord(ResolvedJavaType) word type}.
117     */
118    public Kind asKind(JavaType type) {
119        if (type instanceof ResolvedJavaType && isWord((ResolvedJavaType) type)) {
120            return wordKind;
121        } else {
122            return type.getKind();
123        }
124    }
125
126    public Kind getWordKind() {
127        return wordKind;
128    }
129
130    /**
131     * Gets the stamp for a given {@linkplain #isWord(ResolvedJavaType) word type}.
132     */
133    public Stamp getWordStamp(ResolvedJavaType type) {
134        assert isWord(type);
135        return StampFactory.forKind(wordKind);
136    }
137
138    public ResolvedJavaType getWordImplType() {
139        return wordImplType;
140    }
141}