1 /* 2 * Copyright (c) 2013, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package com.oracle.graal.compiler.hsail; 24 25 import static com.oracle.graal.api.code.CallingConvention.Type.*; 26 27 import static com.oracle.graal.api.code.ValueUtil.*; 28 29 import com.oracle.graal.api.code.*; 30 import com.oracle.graal.api.meta.*; 31 import com.oracle.graal.asm.*; 32 import com.oracle.graal.asm.hsail.*; 33 import com.oracle.graal.compiler.gen.*; 34 import com.oracle.graal.compiler.target.*; 35 import com.oracle.graal.debug.*; 36 import com.oracle.graal.lir.*; 37 import com.oracle.graal.lir.asm.*; 38 import com.oracle.graal.nodes.*; 39 import com.oracle.graal.hsail.*; 40 41 import java.util.Map; 42 import java.util.HashMap; 43 import java.lang.reflect.Modifier; 44 import java.util.Arrays; 45 46 /** 47 * HSAIL specific backend. 48 */ 49 public class HSAILBackend extends Backend { 50 51 private Map<String, String> paramTypeMap = new HashMap<>(); 52 private Buffer codeBuffer; 53 54 public HSAILBackend(CodeCacheProvider runtime, TargetDescription target) { 55 super(runtime, target); 56 paramTypeMap.put("HotSpotResolvedPrimitiveType<int>", "s32"); 57 paramTypeMap.put("HotSpotResolvedPrimitiveType<float>", "f32"); 58 paramTypeMap.put("HotSpotResolvedPrimitiveType<double>", "f64"); 59 paramTypeMap.put("HotSpotResolvedPrimitiveType<long>", "s64"); 60 } 61 62 @Override 63 public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) { 64 return new HSAILLIRGenerator(graph, runtime(), target, frameMap, cc, lir); 65 } 66 67 public String getPartialCodeString() { 68 return (codeBuffer == null ? "" : new String(codeBuffer.copyData(0, codeBuffer.position()))); 69 } 70 71 class HotSpotFrameContext implements FrameContext { 72 73 @Override 74 public void enter(TargetMethodAssembler tasm) { 75 Debug.log("Nothing to do here"); 76 } 77 78 @Override 79 public void leave(TargetMethodAssembler tasm) { 80 Debug.log("Nothing to do here"); 81 } 82 } 83 84 @Override 85 protected AbstractAssembler createAssembler(FrameMap frameMap) { 86 return new HSAILAssembler(target); 87 } 88 89 @Override 90 public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { 91 FrameMap frameMap = lirGen.frameMap; 92 AbstractAssembler masm = new HSAILAssembler(target); 93 HotSpotFrameContext frameContext = new HotSpotFrameContext(); 94 TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult); 95 tasm.setFrameSize(frameMap.frameSize()); 96 return tasm; 97 } 98 99 @Override 100 public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod method) { 101 assert method != null : lirGen.getGraph() + " is not associated with a method"; 102 // Emit the prologue. 103 codeBuffer = tasm.asm.codeBuffer; 104 codeBuffer.emitString0("version 0:95: $full : $large;"); 105 codeBuffer.emitString(""); 106 Signature signature = method.getSignature(); 107 int sigParamCount = signature.getParameterCount(false); 108 // We're subtracting 1 because we're not making the final gid as a parameter. 109 int nonConstantParamCount = sigParamCount - 1; 110 boolean isStatic = (Modifier.isStatic(method.getModifiers())); 111 // Determine if this is an object lambda. 112 boolean isObjectLambda = true; 113 if (signature.getParameterType(nonConstantParamCount, null).getKind() == Kind.Int) { 114 isObjectLambda = false; 115 } else { 116 // Add space for gid int reg. 117 nonConstantParamCount++; 118 } 119 120 // If this is an instance method, include mappings for the "this" parameter 121 // as the first parameter. 122 if (!isStatic) { 123 nonConstantParamCount++; 124 } 125 // Add in any "constant" parameters (currently none). 126 int totalParamCount = nonConstantParamCount; 127 JavaType[] paramtypes = new JavaType[totalParamCount]; 128 String[] paramNames = new String[totalParamCount]; 129 int pidx = 0; 130 for (int i = 0; i < totalParamCount; i++) { 131 if (i == 0 && !isStatic) { 132 paramtypes[i] = runtime().lookupJavaType(Object.class); 133 paramNames[i] = "%_this"; 134 } else if (i < nonConstantParamCount) { 135 if (isObjectLambda && (i == (nonConstantParamCount))) { 136 // Set up the gid register mapping. 137 paramtypes[i] = runtime().lookupJavaType(int.class); 138 paramNames[i] = "%_gid"; 139 } else { 140 paramtypes[i] = signature.getParameterType(pidx++, null); 141 paramNames[i] = "%_arg" + i; 142 } 143 } 144 } 145 codeBuffer.emitString0("// " + (isStatic ? "static" : "instance") + " method " + method); 146 codeBuffer.emitString(""); 147 codeBuffer.emitString0("kernel &run ("); 148 codeBuffer.emitString(""); 149 FrameMap frameMap = tasm.frameMap; 150 RegisterConfig regConfig = frameMap.registerConfig; 151 // Build list of param types which does include the gid (for cc register mapping query). 152 JavaType[] ccParamTypes = new JavaType[nonConstantParamCount + 1]; 153 // Include the gid. 154 System.arraycopy(paramtypes, 0, ccParamTypes, 0, nonConstantParamCount); 155 // Last entry comes from the signature. 156 ccParamTypes[ccParamTypes.length - 1] = signature.getParameterType(sigParamCount - 1, null); 157 CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, ccParamTypes, target, false); 158 /** 159 * Compute the hsail size mappings up to but not including the last non-constant parameter 160 * (which is the gid). 161 * 162 */ 163 String[] paramHsailSizes = new String[totalParamCount]; 164 for (int i = 0; i < totalParamCount; i++) { 165 String paramtypeStr = paramtypes[i].toString(); 166 String sizeStr = paramTypeMap.get(paramtypeStr); 167 // Catch all for any unmapped paramtype that is u64 (address of an object). 168 paramHsailSizes[i] = (sizeStr != null ? sizeStr : "u64"); 169 } 170 // Emit the kernel function parameters. 171 for (int i = 0; i < totalParamCount; i++) { 172 String str = "kernarg_" + paramHsailSizes[i] + " " + paramNames[i]; 173 if (i != totalParamCount - 1) { 174 str += ","; 175 } 176 codeBuffer.emitString(str); 177 } 178 codeBuffer.emitString(") {"); 179 180 /* 181 * End of parameters start of prolog code. Emit the load instructions for loading of the 182 * kernel non-constant parameters into registers. The constant class parameters will not be 183 * loaded up front but will be loaded as needed. 184 */ 185 for (int i = 0; i < nonConstantParamCount; i++) { 186 codeBuffer.emitString("ld_kernarg_" + paramHsailSizes[i] + " " + HSAIL.mapRegister(cc.getArgument(i)) + ", [" + paramNames[i] + "];"); 187 } 188 189 /* 190 * Emit the workitemaid instruction for loading the hidden gid parameter. This is assigned 191 * the register as if it were the last of the nonConstant parameters. 192 */ 193 String workItemReg = "$s" + Integer.toString(asRegister(cc.getArgument(nonConstantParamCount)).encoding()); 194 codeBuffer.emitString("workitemabsid_u32 " + workItemReg + ", 0;"); 195 196 /* 197 * Note the logic used for this spillseg size is to leave space and then go back and patch 198 * in the correct size once we have generated all the instructions. This should probably be 199 * done in a more robust way by implementing something like codeBuffer.insertString. 200 */ 201 int spillsegDeclarationPosition = codeBuffer.position() + 1; 202 String spillsegTemplate = "align 4 spill_u8 %spillseg[123456];"; 203 codeBuffer.emitString(spillsegTemplate); 204 // Emit object array load prologue here. 205 if (isObjectLambda) { 206 final int arrayElementsOffset = 24; 207 String iterationObjArgReg = HSAIL.mapRegister(cc.getArgument(nonConstantParamCount - 1)); 208 String tmpReg = workItemReg.replace("s", "d"); // "$d1"; 209 // Convert gid to long. 210 codeBuffer.emitString("cvt_u64_s32 " + tmpReg + ", " + workItemReg + "; // Convert gid to long"); 211 // Adjust index for sizeof ref. 212 codeBuffer.emitString("mul_u64 " + tmpReg + ", " + tmpReg + ", " + 8 + "; // Adjust index for sizeof ref"); 213 // Adjust for actual data start. 214 codeBuffer.emitString("add_u64 " + tmpReg + ", " + tmpReg + ", " + arrayElementsOffset + "; // Adjust for actual elements data start"); 215 // Add to array ref ptr. 216 codeBuffer.emitString("add_u64 " + tmpReg + ", " + tmpReg + ", " + iterationObjArgReg + "; // Add to array ref ptr"); 217 // Load the object into the parameter reg. 218 codeBuffer.emitString("ld_global_u64 " + iterationObjArgReg + ", " + "[" + tmpReg + "]" + "; // Load from array element into parameter reg"); 219 } 220 // Prologue done, Emit code for the LIR. 221 lirGen.lir.emitCode(tasm); 222 // Now that code is emitted go back and figure out what the upper Bound stack size was. 223 long maxStackSize = ((HSAILAssembler) tasm.asm).upperBoundStackSize(); 224 String spillsegStringFinal; 225 if (maxStackSize == 0) { 226 // If no spilling, get rid of spillseg declaration. 227 char[] array = new char[spillsegTemplate.length()]; 228 Arrays.fill(array, ' '); 229 spillsegStringFinal = new String(array); 230 } else { 231 spillsegStringFinal = spillsegTemplate.replace("123456", String.format("%6d", maxStackSize)); 232 } 233 codeBuffer.emitString(spillsegStringFinal, spillsegDeclarationPosition); 234 // Emit the epilogue. 235 codeBuffer.emitString0("};"); 236 codeBuffer.emitString(""); 237 } 238 }