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(String name, List<? extends Value> operands, int slot) { 64 super(name, 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 final TypeElement resultType; 84 85 public SlotLoadOp(ExternalizedOp def) { 86 int slot = def.extractAttributeValue(ATTRIBUTE_SLOT, true, 87 v -> switch (v) { 88 case String s -> Integer.parseInt(s); 89 case Integer i -> i; 90 default -> throw new UnsupportedOperationException("Unsupported slot value:" + v); 91 }); 92 this(slot, def.resultType()); 93 } 94 95 SlotLoadOp(SlotLoadOp that, CopyContext cc) { 96 super(that, cc); 97 this.resultType = that.resultType; 98 } 99 100 @Override 101 public SlotLoadOp transform(CopyContext cc, OpTransformer ot) { 102 return new SlotLoadOp(this, cc); 103 } 104 105 SlotLoadOp(int slot, TypeElement resultType) { 106 super(NAME, List.of(), slot); 107 this.resultType = resultType; 108 } 109 110 @Override 111 public TypeElement resultType() { 112 return resultType; 113 } 114 115 @Override 116 public TypeKind typeKind() { 117 return toTypeKind(resultType); 118 } 119 120 @Override 121 public String toString() { 122 return "block_" + parentBlock().index() + " " + parentBlock().ops().indexOf(this) + ": #" + slot + " LOAD " + typeKind(); 123 } 124 } 125 126 @OpDeclaration(SlotStoreOp.NAME) 127 public static final class SlotStoreOp extends SlotOp { 128 public static final String NAME = "slot.store"; 129 130 public SlotStoreOp(ExternalizedOp def) { 131 int slot = def.extractAttributeValue(ATTRIBUTE_SLOT, true, 132 v -> switch (v) { 133 case String s -> Integer.parseInt(s); 134 case Integer i -> i; 135 default -> throw new UnsupportedOperationException("Unsupported slot value:" + v); 136 }); 137 this(slot, def.operands().getFirst()); 138 } 139 140 SlotStoreOp(SlotStoreOp that, CopyContext cc) { 141 super(that, cc); 142 } 143 144 @Override 145 public SlotStoreOp transform(CopyContext cc, OpTransformer ot) { 146 return new SlotStoreOp(this, cc); 147 } 148 149 SlotStoreOp(int slot, Value v) { 150 super(NAME, List.of(v), slot); 151 } 152 153 @Override 154 public TypeElement resultType() { 155 return JavaType.VOID; 156 } 157 158 @Override 159 public TypeKind typeKind() { 160 return toTypeKind(operands().getFirst().type()); 161 } 162 163 @Override 164 public String toString() { 165 return "block_" + parentBlock().index() + " " + parentBlock().ops().indexOf(this) + ": #" + slot + " STORE " + typeKind(); 166 } 167 } 168 169 private static TypeKind toTypeKind(TypeElement type) { 170 return switch (type) { 171 case UnresolvedType.Int _ -> 172 TypeKind.INT; 173 case PrimitiveType pt -> 174 TypeKind.from(pt.toNominalDescriptor()).asLoadable(); 175 default -> 176 TypeKind.REFERENCE; 177 }; 178 } 179 }