/* * Copyright (c) 2016, Oracle and/or its affiliates. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials provided * with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.oracle.truffle.llvm.parser.factories; import java.util.Arrays; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.llvm.nodes.func.LLVMGlobalRootNode; import com.oracle.truffle.llvm.parser.LLVMParserRuntime; import com.oracle.truffle.llvm.runtime.LLVMAddress; import com.oracle.truffle.llvm.runtime.LLVMLanguage; import com.oracle.truffle.llvm.runtime.memory.LLVMHeap; import com.oracle.truffle.llvm.runtime.memory.LLVMMemory; import com.oracle.truffle.llvm.runtime.types.Type; class LLVMRootNodeFactory { static LLVMGlobalRootNode createGlobalRootNode( LLVMParserRuntime runtime, RootCallTarget mainCallTarget, Object[] args, Source sourceFile, Type[] mainTypes) { return createGlobalRootNode( runtime.getLanguage(), runtime.getGlobalFrameDescriptor(), mainCallTarget, args, sourceFile, mainTypes); } private static LLVMGlobalRootNode createGlobalRootNode( LLVMLanguage language, FrameDescriptor frame, RootCallTarget mainCallTarget, Object[] args, Source sourceFile, Type[] mainTypes) { Object[] arguments = createArgs(sourceFile, args, mainTypes); return new LLVMGlobalRootNode(language, frame, mainCallTarget, arguments); } private static Object[] createArgs(Source sourceFile, Object[] mainArgs, Type[] llvmRuntimeTypes) { int mainArgsCount = mainArgs == null ? 0 : mainArgs.length; int argsCount = mainArgsCount + 1; if (llvmRuntimeTypes.length == 0) { return new Object[0]; } else if (llvmRuntimeTypes.length == 1) { return new Object[]{argsCount}; } else { Object[] args = new Object[argsCount]; args[0] = sourceFile.getPath() == null ? "" : sourceFile.getPath(); if (mainArgsCount > 0) { System.arraycopy(mainArgs, 0, args, 1, mainArgsCount); } LLVMAddress allocatedArgsStartAddress = getArgsAsStringArray(args); // Checkstyle: stop magic number check if (llvmRuntimeTypes.length == 2) { return new Object[]{argsCount, allocatedArgsStartAddress}; } else if (llvmRuntimeTypes.length == 3) { LLVMAddress posixEnvPointer = LLVMAddress.nullPointer(); return new Object[]{argsCount, allocatedArgsStartAddress, posixEnvPointer}; } else { throw new AssertionError(sourceFile + " " + Arrays.toString(mainArgs) + " " + Arrays.toString(llvmRuntimeTypes)); } // Checkstyle: resume magic number check } } private static LLVMAddress getArgsAsStringArray(Object[] args) { String[] stringArgs = getStringArgs(args); int argsMemory = stringArgs.length * LLVMAddress.WORD_LENGTH_BIT / Byte.SIZE; LLVMAddress allocatedArgsStartAddress = LLVMMemory.allocateMemory(argsMemory); long allocatedArgsPtr = allocatedArgsStartAddress.getVal(); for (int i = 0; i < stringArgs.length; i++) { String string = stringArgs[i]; LLVMAddress allocatedCString = LLVMHeap.allocateCString(string); LLVMMemory.putAddress(allocatedArgsPtr, allocatedCString); allocatedArgsPtr += LLVMAddress.WORD_LENGTH_BIT / Byte.SIZE; } return allocatedArgsStartAddress; } private static String[] getStringArgs(Object[] args) { String[] stringArgs = new String[args.length]; for (int i = 0; i < args.length; i++) { stringArgs[i] = args[i].toString(); } return stringArgs; } }