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.MemoryLayout;
 30 import jdk.incubator.foreign.SequenceLayout;
 31 import jdk.incubator.foreign.ValueLayout;
 32 import jdk.internal.foreign.PlatformLayouts;
 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         return switch (PlatformLayouts.getKind(type)) {
 46             case CHAR, SHORT, INT, LONG, LONG_LONG -> INTEGER;
 47             case POINTER -> POINTER;
 48             case FLOAT, DOUBLE -> FLOAT;
 49         };
 50     }
 51 
 52     static boolean isRegisterAggregate(MemoryLayout type) {
 53         return type.bitSize() <= MAX_AGGREGATE_REGS_SIZE * 64;
 54     }
 55 
 56     static boolean isHomogeneousFloatAggregate(MemoryLayout type) {
 57         if (!(type instanceof GroupLayout))
 58             return false;
 59 
 60         GroupLayout groupLayout = (GroupLayout)type;
 61 
 62         final int numElements = groupLayout.memberLayouts().size();
 63         if (numElements > 4 || numElements == 0)
 64             return false;
 65 
 66         MemoryLayout baseType = groupLayout.memberLayouts().get(0);
 67 
 68         if (!(baseType instanceof ValueLayout))
 69             return false;
 70 
 71         TypeClass baseArgClass = classifyValueType((ValueLayout) baseType);
 72         if (baseArgClass != FLOAT)
 73            return false;
 74 
 75         for (MemoryLayout elem : groupLayout.memberLayouts()) {
 76             if (!(elem instanceof ValueLayout))
 77                 return false;
 78 
 79             TypeClass argClass = classifyValueType((ValueLayout) elem);
 80             if (elem.bitSize() != baseType.bitSize() ||
 81                     elem.bitAlignment() != baseType.bitAlignment() ||
 82                     baseArgClass != argClass) {
 83                 return false;
 84             }
 85         }
 86 
 87         return true;
 88     }
 89 
 90     private static TypeClass classifyStructType(MemoryLayout layout) {
 91         if (isHomogeneousFloatAggregate(layout)) {
 92             return TypeClass.STRUCT_HFA;
 93         } else if (isRegisterAggregate(layout)) {
 94             return TypeClass.STRUCT_REGISTER;
 95         }
 96         return TypeClass.STRUCT_REFERENCE;
 97     }
 98 
 99     public static TypeClass classifyLayout(MemoryLayout type) {
100         if (type instanceof ValueLayout) {
101             return classifyValueType((ValueLayout) type);
102         } else if (type instanceof GroupLayout) {
103             return classifyStructType(type);
104         } else if (type instanceof SequenceLayout) {
105             return TypeClass.INTEGER;
106         } else {
107             throw new IllegalArgumentException("Unhandled type " + type);
108         }
109     }
110 }