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