1 /*
  2  * Copyright (c) 2019, 2020, 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.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package jdk.internal.foreign.abi;
 24 
 25 import jdk.incubator.foreign.FunctionDescriptor;
 26 
 27 import java.lang.invoke.MethodType;
 28 import java.util.List;
 29 import java.util.stream.IntStream;
 30 import java.util.stream.Stream;
 31 
 32 public class CallingSequence {
 33     private final MethodType mt;
 34     private final FunctionDescriptor desc;
 35 
 36     private final List<Binding> returnBindings;
 37     private final List<List<Binding>> argumentBindings;
 38 
 39     public CallingSequence(MethodType mt, FunctionDescriptor desc,
 40                            List<List<Binding>> argumentBindings, List<Binding> returnBindings) {
 41         this.mt = mt;
 42         this.desc = desc;
 43         this.returnBindings = returnBindings;
 44         this.argumentBindings = argumentBindings;
 45     }
 46 
 47     public Stream<Binding.Move> argMoveBindings() {
 48         return argumentBindings.stream()
 49                 .flatMap(List::stream)
 50                 .filter(Binding.Move.class::isInstance)
 51                 .map(Binding.Move.class::cast);
 52     }
 53 
 54     public Stream<Binding.Move> retMoveBindings() {
 55         return returnBindings()
 56             .stream()
 57             .filter(Binding.Move.class::isInstance)
 58             .map(Binding.Move.class::cast);
 59     }
 60 
 61     public int argumentCount() {
 62         return argumentBindings.size();
 63     }
 64 
 65     public List<Binding> argumentBindings(int i) {
 66         return argumentBindings.get(i);
 67     }
 68 
 69     public Stream<Binding> argumentBindings() {
 70         return argumentBindings.stream().flatMap(List::stream);
 71     }
 72 
 73     public List<Binding> returnBindings() {
 74         return returnBindings;
 75     }
 76 
 77     public String asString() {
 78         StringBuilder sb = new StringBuilder();
 79 
 80         sb.append("CallingSequence: {\n");
 81         sb.append("  MethodType: ").append(mt);
 82         sb.append("  FunctionDescriptor: ").append(desc);
 83         sb.append("  Argument Bindings:\n");
 84         for (int i = 0; i < mt.parameterCount(); i++) {
 85             sb.append("    ").append(i).append(": ").append(argumentBindings.get(i)).append("\n");
 86         }
 87         if (mt.returnType() != void.class) {
 88             sb.append("    ").append("Return: ").append(returnBindings).append("\n");
 89         }
 90         sb.append("}\n");
 91 
 92         return sb.toString();
 93     }
 94 
 95     public MethodType methodType() {
 96         return mt;
 97     }
 98 
 99     public FunctionDescriptor functionDesc() {
100         return desc;
101     }
102 }