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 
 26 package oracle.code.triton;
 27 
 28 import java.lang.reflect.code.*;
 29 import java.lang.reflect.code.op.*;
 30 import java.lang.reflect.code.type.FunctionType;
 31 import java.lang.reflect.code.type.JavaType;
 32 import java.lang.reflect.code.type.TupleType;
 33 import java.util.ArrayList;
 34 import java.util.List;
 35 import java.util.function.Consumer;
 36 
 37 public class SCFOps {
 38 
 39     @OpFactory.OpDeclaration(ForOp.NAME)
 40     public static final class ForOp extends ExternalizableOp implements Op.Loop {
 41 
 42         public static class Builder {
 43             final Body.Builder ancestorBody;
 44             final List<Value> range;
 45             final FunctionType loopType;
 46 
 47             Builder(Body.Builder ancestorBody, List<Value> range, FunctionType loopType) {
 48                 this.ancestorBody = ancestorBody;
 49                 this.range = range;
 50                 this.loopType = loopType;
 51             }
 52 
 53             public ForOp body(Consumer<Block.Builder> c) {
 54                 Body.Builder body = Body.Builder.of(ancestorBody, loopType);
 55                 c.accept(body.entryBlock());
 56                 return new ForOp(range, body);
 57             }
 58 
 59             public ForOp body(CopyContext cc, Consumer<Block.Builder> c) {
 60                 Body.Builder body = Body.Builder.of(ancestorBody, loopType, cc);
 61                 c.accept(body.entryBlock());
 62                 return new ForOp(range, body);
 63             }
 64         }
 65 
 66         public static final String NAME = "scf.for";
 67 
 68         final Body body;
 69 
 70         public ForOp(ExternalizedOp def) {
 71             super(def);
 72 
 73             this.body = def.bodyDefinitions().get(0).build(this);
 74         }
 75 
 76         ForOp(ForOp that, CopyContext cc, OpTransformer ot) {
 77             super(that, cc);
 78 
 79             this.body = that.body.transform(cc, ot).build(this);
 80         }
 81 
 82         @Override
 83         public ForOp transform(CopyContext cc, OpTransformer ot) {
 84             return new ForOp(this, cc, ot);
 85         }
 86 
 87         ForOp(List<Value> range, Body.Builder bodyBuilder) {
 88             super(NAME, range);
 89 
 90             this.body = bodyBuilder.build(this);
 91         }
 92 
 93         @Override
 94         public TypeElement resultType() {
 95             return body.yieldType();
 96         }
 97 
 98         @Override
 99         public List<Body> bodies() {
100             return List.of(body);
101         }
102 
103         @Override
104         public Body loopBody() {
105             return body;
106         }
107     }
108 
109     @OpFactory.OpDeclaration(YieldOp.NAME)
110     public static class YieldOp extends ExternalizableOp implements Op.Terminating {
111         public static final String NAME = "scf.yield";
112 
113         public YieldOp(ExternalizedOp def) {
114             super(def);
115         }
116 
117         YieldOp(YieldOp that, CopyContext cc) {
118             super(that, cc);
119         }
120 
121         @Override
122         public YieldOp transform(CopyContext cc, OpTransformer ot) {
123             return new YieldOp(this, cc);
124         }
125 
126         YieldOp(List<Value> values) {
127             super(NAME, values);
128         }
129 
130         @Override
131         public TypeElement resultType() {
132             return JavaType.VOID;
133         }
134 
135         static TypeElement yieldType(List<Value> values) {
136             if (values.size() == 1) {
137                 return values.get(0).type();
138             } else {
139                 return TupleType.tupleTypeFromValues(values);
140             }
141         }
142     }
143 
144     static public ForOp.Builder for_(Body.Builder ancestorBody,
145                                      Value start, Value end, Value step,
146                                      List<Value> iterValues) {
147         TypeElement yieldType = (iterValues.size() == 1)
148                 ? iterValues.get(0).type()
149                 : TupleType.tupleTypeFromValues(iterValues);
150 
151         List<TypeElement> bodyParameterTypes = new ArrayList<>();
152         bodyParameterTypes.add(start.type());
153         bodyParameterTypes.addAll(iterValues.stream().map(Value::type).toList());
154         FunctionType bodyType = FunctionType.functionType(yieldType, bodyParameterTypes);
155 
156         List<Value> operands = new ArrayList<>();
157         operands.addAll(List.of(start, end, step));
158         operands.addAll(iterValues);
159         return new ForOp.Builder(ancestorBody, operands, bodyType);
160     }
161 
162 
163     public static final OpFactory FACTORY = OpFactory.OP_FACTORY.get(SCFOps.class);
164 
165     static public YieldOp yield_(Value... values) {
166         return yield_(List.of(values));
167     }
168 
169     static public YieldOp yield_(List<Value> values) {
170         return new YieldOp(values);
171     }
172 }