1 /* 2 * Copyright (c) 2014, 2016, 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 org.graalvm.compiler.hotspot.amd64; 24 25 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; 26 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; 27 28 import org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder; 29 import org.graalvm.compiler.core.common.type.RawPointerStamp; 30 import org.graalvm.compiler.core.common.type.Stamp; 31 import org.graalvm.compiler.core.common.type.StampFactory; 32 import org.graalvm.compiler.graph.NodeClass; 33 import org.graalvm.compiler.graph.NodeInputList; 34 import org.graalvm.compiler.nodeinfo.NodeInfo; 35 import org.graalvm.compiler.nodes.FixedWithNextNode; 36 import org.graalvm.compiler.nodes.ValueNode; 37 import org.graalvm.compiler.nodes.spi.LIRLowerable; 38 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 39 40 import jdk.vm.ci.code.CallingConvention; 41 import jdk.vm.ci.hotspot.HotSpotCallingConventionType; 42 import jdk.vm.ci.meta.JavaConstant; 43 import jdk.vm.ci.meta.JavaKind; 44 import jdk.vm.ci.meta.JavaType; 45 import jdk.vm.ci.meta.MetaAccessProvider; 46 import jdk.vm.ci.meta.ResolvedJavaType; 47 import jdk.vm.ci.meta.Value; 48 49 @NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = SIZE_20) 50 public final class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { 51 public static final NodeClass<AMD64RawNativeCallNode> TYPE = NodeClass.create(AMD64RawNativeCallNode.class); 52 53 protected final JavaConstant functionPointer; 54 @Input NodeInputList<ValueNode> args; 55 56 public AMD64RawNativeCallNode(JavaKind returnType, JavaConstant functionPointer, ValueNode[] args) { 57 super(TYPE, StampFactory.forKind(returnType)); 58 this.functionPointer = functionPointer; 59 this.args = new NodeInputList<>(this, args); 60 } 61 62 private static class PointerType implements JavaType { 63 64 @Override 65 public String getName() { 66 return "void*"; 67 } 68 69 @Override 70 public JavaType getComponentType() { 71 return null; 72 } 73 74 @Override 75 public JavaType getArrayClass() { 76 return null; 77 } 78 79 @Override 80 public JavaKind getJavaKind() { 81 // native pointers and java objects use the same registers in the calling convention 82 return JavaKind.Object; 83 } 84 85 @Override 86 public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { 87 return null; 88 } 89 } 90 91 private static JavaType toJavaType(Stamp stamp, MetaAccessProvider metaAccess) { 92 if (stamp instanceof RawPointerStamp) { 93 return new PointerType(); 94 } else { 95 return stamp.javaType(metaAccess); 96 } 97 } 98 99 @Override 100 public void generate(NodeLIRBuilderTool generator) { 101 AMD64NodeLIRBuilder gen = (AMD64NodeLIRBuilder) generator; 102 Value[] parameter = new Value[args.count()]; 103 JavaType[] parameterTypes = new JavaType[args.count()]; 104 for (int i = 0; i < args.count(); i++) { 105 parameter[i] = generator.operand(args.get(i)); 106 parameterTypes[i] = toJavaType(args.get(i).stamp(), gen.getLIRGeneratorTool().getMetaAccess()); 107 } 108 JavaType returnType = toJavaType(stamp(), gen.getLIRGeneratorTool().getMetaAccess()); 109 CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.NativeCall, returnType, parameterTypes, 110 generator.getLIRGeneratorTool()); 111 gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args)); 112 if (this.getStackKind() != JavaKind.Void) { 113 generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn())); 114 } 115 } 116 117 private static int countFloatingTypeArguments(NodeInputList<ValueNode> args) { 118 int count = 0; 119 for (ValueNode n : args) { 120 if (n.getStackKind() == JavaKind.Double || n.getStackKind() == JavaKind.Float) { 121 count++; 122 } 123 } 124 if (count > 8) { 125 return 8; 126 } 127 return count; 128 } 129 130 }