1 /*
2 * Copyright (c) 2024, 2025, 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 import java.lang.classfile.TypeKind;
27
28 import jdk.incubator.code.*;
29 import jdk.incubator.code.extern.ExternalizedOp;
30 import jdk.incubator.code.dialect.java.JavaType;
31 import jdk.incubator.code.dialect.java.PrimitiveType;
32 import jdk.incubator.code.internal.OpDeclaration;
33
34 import java.util.List;
35 import java.util.Map;
36
37 sealed abstract class SlotOp extends Op {
38 public static final String ATTRIBUTE_SLOT = "slot";
39
40 public static SlotLoadOp load(int slot, TypeKind tk) {
41 return new SlotLoadOp(slot, switch (tk) {
42 case INT -> UnresolvedType.unresolvedInt();
43 case REFERENCE -> UnresolvedType.unresolvedRef();
44 case LONG -> JavaType.LONG;
45 case DOUBLE -> JavaType.DOUBLE;
46 case FLOAT -> JavaType.FLOAT;
47 default -> throw new IllegalStateException("Unexpected load instruction type: " + tk);
48 });
49 }
50
51 public static SlotStoreOp store(int slot, Value v) {
52 return new SlotStoreOp(slot, v);
53 }
54
55 final int slot;
56
57 protected SlotOp(SlotOp that, CopyContext cc) {
58 super(that, cc);
59 this.slot = that.slot;
60 }
61
62 protected SlotOp(List<? extends Value> operands, int slot) {
63 super(operands);
64 this.slot = slot;
65 }
66
67 public int slot() {
68 return slot;
69 }
70
71 public abstract TypeKind typeKind();
72
73 @Override
74 public Map<String, Object> externalize() {
75 return Map.of("", slot);
76 }
77
78 @OpDeclaration(SlotLoadOp.NAME)
79 public static final class SlotLoadOp extends SlotOp {
80 public static final String NAME = "slot.load";
81
82 @Override
83 public String externalizeOpName() {
84 return NAME;
85 }
86
87 final TypeElement resultType;
88
89 public SlotLoadOp(ExternalizedOp def) {
90 int slot = def.extractAttributeValue(ATTRIBUTE_SLOT, true,
91 v -> switch (v) {
92 case String s -> Integer.parseInt(s);
93 case Integer i -> i;
94 default -> throw new UnsupportedOperationException("Unsupported slot value:" + v);
95 });
96 this(slot, def.resultType());
97 }
98
99 SlotLoadOp(SlotLoadOp that, CopyContext cc) {
100 super(that, cc);
101 this.resultType = that.resultType;
102 }
103
104 @Override
105 public SlotLoadOp transform(CopyContext cc, OpTransformer ot) {
106 return new SlotLoadOp(this, cc);
107 }
108
109 SlotLoadOp(int slot, TypeElement resultType) {
110 super(List.of(), slot);
111 this.resultType = resultType;
112 }
113
114 @Override
115 public TypeElement resultType() {
116 return resultType;
117 }
118
119 @Override
120 public TypeKind typeKind() {
121 return toTypeKind(resultType);
122 }
123
124 @Override
125 public String toString() {
126 return "block_" + ancestorBlock().index() + " " + ancestorBlock().ops().indexOf(this) + ": #" + slot + " LOAD " + typeKind();
127 }
128 }
129
130 @OpDeclaration(SlotStoreOp.NAME)
131 public static final class SlotStoreOp extends SlotOp {
132 public static final String NAME = "slot.store";
133
134 @Override
135 public String externalizeOpName() {
136 return NAME;
137 }
138
139 public SlotStoreOp(ExternalizedOp def) {
140 int slot = def.extractAttributeValue(ATTRIBUTE_SLOT, true,
141 v -> switch (v) {
142 case String s -> Integer.parseInt(s);
143 case Integer i -> i;
144 default -> throw new UnsupportedOperationException("Unsupported slot value:" + v);
145 });
146 this(slot, def.operands().getFirst());
147 }
148
149 SlotStoreOp(SlotStoreOp that, CopyContext cc) {
150 super(that, cc);
151 }
152
153 @Override
154 public SlotStoreOp transform(CopyContext cc, OpTransformer ot) {
155 return new SlotStoreOp(this, cc);
156 }
157
158 SlotStoreOp(int slot, Value v) {
159 super(List.of(v), slot);
160 }
161
162 @Override
163 public TypeElement resultType() {
164 return JavaType.VOID;
165 }
166
167 @Override
168 public TypeKind typeKind() {
169 return toTypeKind(operands().getFirst().type());
170 }
171
172 @Override
173 public String toString() {
174 return "block_" + ancestorBlock().index() + " " + ancestorBlock().ops().indexOf(this) + ": #" + slot + " STORE " + typeKind();
175 }
176 }
177
178 private static TypeKind toTypeKind(TypeElement type) {
179 return switch (type) {
180 case UnresolvedType.Int _ ->
181 TypeKind.INT;
182 case PrimitiveType pt ->
183 TypeKind.from(pt.toNominalDescriptor()).asLoadable();
184 default ->
185 TypeKind.REFERENCE;
186 };
187 }
188 }