1 /*
  2  * Copyright (c) 2024, 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 hat.optools;
 26 
 27 import hat.util.BiMap;
 28 import jdk.incubator.code.Block;
 29 import jdk.incubator.code.Op;
 30 import jdk.incubator.code.dialect.core.CoreOp;
 31 import jdk.incubator.code.dialect.java.JavaOp;
 32 import jdk.incubator.code.dialect.java.JavaType;
 33 import jdk.incubator.code.dialect.java.PrimitiveType;
 34 
 35 import java.lang.foreign.GroupLayout;
 36 import java.util.ArrayList;
 37 import java.util.LinkedHashMap;
 38 import java.util.List;
 39 import java.util.Map;
 40 import java.util.Optional;
 41 import java.util.stream.Stream;
 42 
 43 public class FuncOpParams {
 44     public static class Info {
 45         public final int idx;
 46         public final Block.Parameter parameter;
 47         public final JavaType javaType;
 48         public final CoreOp.VarOp varOp;
 49         public Class<?> clazz = null;
 50 
 51         Info(int idx, Block.Parameter parameter, CoreOp.VarOp varOp) {
 52             this.idx = idx;
 53             this.parameter = parameter;
 54             this.javaType = (JavaType) parameter.type();
 55             this.varOp = varOp;
 56         }
 57 
 58         public boolean isPrimitive() {
 59             return javaType instanceof PrimitiveType;
 60         }
 61 
 62         public void setClass(Class<?> clazz) {
 63             this.clazz = clazz;
 64         }
 65     }
 66 
 67     final public BiMap<Block.Parameter, CoreOp.VarOp> parameterVarOpMap = new BiMap<>();
 68     final public BiMap<Block.Parameter, JavaOp.InvokeOp> parameterInvokeOpMap = new BiMap<>();
 69 
 70     final private Map<Block.Parameter, Info> parameterToInfo = new LinkedHashMap<>();
 71     final private Map<CoreOp.VarOp, Info> varOpToInfo = new LinkedHashMap<>();
 72 
 73     final private List<Info> list = new ArrayList<>();
 74 
 75     public Info info(Block.Parameter parameter) {
 76         return parameterToInfo.get(parameter);
 77     }
 78 
 79     void add(Map.Entry<Block.Parameter, CoreOp.VarOp> parameterToVarOp) {
 80         //We add a new ParameterInfo to both maps using parameter and varOp as keys
 81         varOpToInfo.put(parameterToVarOp.getValue(),
 82                 // always called but convenient because computeIfAbsent returns what we added :)
 83                 parameterToInfo.computeIfAbsent(parameterToVarOp.getKey(), (parameterKey) -> {
 84                     var info = new Info(list.size(), parameterKey, parameterToVarOp.getValue());
 85                     list.add(info);
 86                     return info;
 87                 })
 88         );
 89     }
 90 
 91     public List<Info> list() {
 92         return list;
 93     }
 94 
 95     public Stream<Info> stream() {
 96         return list.stream();
 97     }
 98 
 99     final public CoreOp funcOp;
100 
101     public FuncOpParams(CoreOp.FuncOp funcOp) {
102         this.funcOp = funcOp;
103         funcOp.parameters().forEach(parameter -> {
104             Optional<Op.Result> optionalResult = parameter.uses().stream().findFirst();
105             optionalResult.ifPresentOrElse(result -> {
106                 if (result.op() instanceof CoreOp.VarOp varOp) {
107                     parameterVarOpMap.add(parameter, varOp);
108                     add(Map.entry(parameter, varOp));
109                 } else if (result.op() instanceof JavaOp.InvokeOp invokeOp) {
110                     parameterInvokeOpMap.add(parameter, invokeOp);
111                 }
112             }, () -> {
113                 throw new IllegalStateException("FuncOp has unused params ");
114             });
115         });
116     }
117 }