1 /*
  2  * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2020, 2021, Arm Limited. All rights reserved.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.  Oracle designates this
  9  * particular file as subject to the "Classpath" exception as provided
 10  * by Oracle in the LICENSE file that accompanied this code.
 11  *
 12  * This code is distributed in the hope that it will be useful, but WITHOUT
 13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 15  * version 2 for more details (a copy is included in the LICENSE file that
 16  * accompanied this code).
 17  *
 18  * You should have received a copy of the GNU General Public License version
 19  * 2 along with this work; if not, write to the Free Software Foundation,
 20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 21  *
 22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 23  * or visit www.oracle.com if you need additional information or have any
 24  * questions.
 25  */
 26 package jdk.internal.foreign.abi.aarch64;
 27 
 28 import jdk.incubator.foreign.GroupLayout;
 29 import jdk.incubator.foreign.MemoryAddress;
 30 import jdk.incubator.foreign.MemoryLayout;
 31 import jdk.incubator.foreign.SequenceLayout;
 32 import jdk.incubator.foreign.ValueLayout;
 33 
 34 public enum TypeClass {
 35     STRUCT_REGISTER,
 36     STRUCT_REFERENCE,
 37     STRUCT_HFA,
 38     POINTER,
 39     INTEGER,
 40     FLOAT;
 41 
 42     private static final int MAX_AGGREGATE_REGS_SIZE = 2;
 43 
 44     private static TypeClass classifyValueType(ValueLayout type) {
 45         Class<?> carrier = type.carrier();
 46         if (carrier == boolean.class || carrier == byte.class || carrier == char.class ||
 47                 carrier == short.class || carrier == int.class || carrier == long.class) {
 48             return INTEGER;
 49         } else if (carrier == float.class || carrier == double.class) {
 50             return FLOAT;
 51         } else if (carrier == MemoryAddress.class) {
 52             return POINTER;
 53         } else {
 54             throw new IllegalStateException("Cannot get here: " + carrier.getName());
 55         }
 56     }
 57 
 58     static boolean isRegisterAggregate(MemoryLayout type) {
 59         return type.bitSize() <= MAX_AGGREGATE_REGS_SIZE * 64;
 60     }
 61 
 62     static boolean isHomogeneousFloatAggregate(MemoryLayout type) {
 63         if (!(type instanceof GroupLayout))
 64             return false;
 65 
 66         GroupLayout groupLayout = (GroupLayout)type;
 67 
 68         final int numElements = groupLayout.memberLayouts().size();
 69         if (numElements > 4 || numElements == 0)
 70             return false;
 71 
 72         MemoryLayout baseType = groupLayout.memberLayouts().get(0);
 73 
 74         if (!(baseType instanceof ValueLayout))
 75             return false;
 76 
 77         TypeClass baseArgClass = classifyValueType((ValueLayout) baseType);
 78         if (baseArgClass != FLOAT)
 79            return false;
 80 
 81         for (MemoryLayout elem : groupLayout.memberLayouts()) {
 82             if (!(elem instanceof ValueLayout))
 83                 return false;
 84 
 85             TypeClass argClass = classifyValueType((ValueLayout) elem);
 86             if (elem.bitSize() != baseType.bitSize() ||
 87                     elem.bitAlignment() != baseType.bitAlignment() ||
 88                     baseArgClass != argClass) {
 89                 return false;
 90             }
 91         }
 92 
 93         return true;
 94     }
 95 
 96     private static TypeClass classifyStructType(MemoryLayout layout) {
 97         if (isHomogeneousFloatAggregate(layout)) {
 98             return TypeClass.STRUCT_HFA;
 99         } else if (isRegisterAggregate(layout)) {
100             return TypeClass.STRUCT_REGISTER;
101         }
102         return TypeClass.STRUCT_REFERENCE;
103     }
104 
105     public static TypeClass classifyLayout(MemoryLayout type) {
106         if (type instanceof ValueLayout) {
107             return classifyValueType((ValueLayout) type);
108         } else if (type instanceof GroupLayout) {
109             return classifyStructType(type);
110         } else if (type instanceof SequenceLayout) {
111             return TypeClass.INTEGER;
112         } else {
113             throw new IllegalArgumentException("Unhandled type " + type);
114         }
115     }
116 }