1 /*
   2  * Copyright (c) 2012, 2016, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package org.graalvm.word;
  26 
  27 import java.lang.annotation.ElementType;
  28 import java.lang.annotation.Retention;
  29 import java.lang.annotation.RetentionPolicy;
  30 import java.lang.annotation.Target;
  31 import java.lang.reflect.InvocationTargetException;
  32 
  33 public abstract class WordFactory {
  34 
  35     /**
  36      * Links a method to a canonical operation represented by an {@link FactoryOpcode} val.
  37      */
  38     @Retention(RetentionPolicy.RUNTIME)
  39     @Target(ElementType.METHOD)
  40     protected @interface FactoryOperation {
  41         FactoryOpcode opcode();
  42     }
  43 
  44     /**
  45      * The canonical {@link FactoryOperation} represented by a method in a word type.
  46      */
  47     protected enum FactoryOpcode {
  48         ZERO,
  49         FROM_UNSIGNED,
  50         FROM_SIGNED,
  51     }
  52 
  53     protected interface BoxFactory {
  54         <T extends WordBase> T box(long val);
  55     }
  56 
  57     protected static final BoxFactory boxFactory;
  58 
  59     static {
  60         try {
  61             /*
  62              * We know the implementation class, but cannot reference it statically because we need
  63              * to break the dependency between the interface and the implementation.
  64              */
  65             boxFactory = (BoxFactory) Class.forName("org.graalvm.compiler.word.Word$BoxFactoryImpl").getConstructor().newInstance();
  66         } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
  67             throw new ExceptionInInitializerError("Could not find and initialize the word type factory. The Graal compiler needs to be on the class path to use the word type.");
  68         }
  69     }
  70 
  71     /**
  72      * We allow subclassing, because only subclasses can access the protected inner classes that we
  73      * use to mark the operations.
  74      */
  75     protected WordFactory() {
  76     }
  77 
  78     /**
  79      * The constant 0, i.e., the word with no bits set. There is no difference between a signed and
  80      * unsigned zero.
  81      *
  82      * @return the constant 0.
  83      */
  84     @FactoryOperation(opcode = FactoryOpcode.ZERO)
  85     public static <T extends WordBase> T zero() {
  86         return boxFactory.box(0L);
  87     }
  88 
  89     /**
  90      * The null pointer, i.e., the pointer with no bits set. There is no difference to a signed or
  91      * unsigned {@link #zero}.
  92      *
  93      * @return the null pointer.
  94      */
  95     @FactoryOperation(opcode = FactoryOpcode.ZERO)
  96     public static <T extends PointerBase> T nullPointer() {
  97         return boxFactory.box(0L);
  98     }
  99 
 100     /**
 101      * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned
 102      * 64-bit value (in contrast to the semantics of a Java long).
 103      *
 104      * @param val a 64 bit unsigned value
 105      * @return the value cast to Word
 106      */
 107     @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
 108     public static <T extends Unsigned> T unsigned(long val) {
 109         return boxFactory.box(val);
 110     }
 111 
 112     /**
 113      * Unsafe conversion from a Java long value to a {@link PointerBase pointer}. The parameter is
 114      * treated as an unsigned 64-bit value (in contrast to the semantics of a Java long).
 115      *
 116      * @param val a 64 bit unsigned value
 117      * @return the value cast to PointerBase
 118      */
 119     @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
 120     public static <T extends PointerBase> T pointer(long val) {
 121         return boxFactory.box(val);
 122     }
 123 
 124     /**
 125      * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned
 126      * 32-bit value (in contrast to the semantics of a Java int).
 127      *
 128      * @param val a 32 bit unsigned value
 129      * @return the value cast to Word
 130      */
 131     @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
 132     public static <T extends Unsigned> T unsigned(int val) {
 133         return boxFactory.box(val & 0xffffffffL);
 134     }
 135 
 136     /**
 137      * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed
 138      * 64-bit value (unchanged semantics of a Java long).
 139      *
 140      * @param val a 64 bit signed value
 141      * @return the value cast to Word
 142      */
 143     @FactoryOperation(opcode = FactoryOpcode.FROM_SIGNED)
 144     public static <T extends Signed> T signed(long val) {
 145         return boxFactory.box(val);
 146     }
 147 
 148     /**
 149      * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed
 150      * 32-bit value (unchanged semantics of a Java int).
 151      *
 152      * @param val a 32 bit signed value
 153      * @return the value cast to Word
 154      */
 155     @FactoryOperation(opcode = FactoryOpcode.FROM_SIGNED)
 156     public static <T extends Signed> T signed(int val) {
 157         return boxFactory.box(val);
 158     }
 159 }