/* * 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.model.blocks; import java.util.ArrayList; import java.util.List; import com.oracle.truffle.llvm.parser.model.functions.FunctionDefinition; import com.oracle.truffle.llvm.parser.model.symbols.Symbols; import com.oracle.truffle.llvm.parser.model.symbols.instructions.AllocateInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.BinaryOperationInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.BranchInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.CallInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.CastInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.CompareExchangeInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.CompareInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ConditionalBranchInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ExtractElementInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ExtractValueInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.GetElementPointerInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.IndirectBranchInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.InsertElementInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.InsertValueInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.Instruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.InvokeInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.LandingpadInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.LoadInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.PhiInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ResumeInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ReturnInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.SelectInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ShuffleVectorInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.StoreInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.SwitchInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.SwitchOldInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.UnreachableInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ValueInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.VoidCallInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.VoidInvokeInstruction; import com.oracle.truffle.llvm.parser.model.visitors.InstructionVisitor; import com.oracle.truffle.llvm.runtime.types.Type; import com.oracle.truffle.llvm.runtime.types.VoidType; import com.oracle.truffle.llvm.runtime.types.symbols.LLVMIdentifier; import com.oracle.truffle.llvm.runtime.types.symbols.ValueSymbol; public final class InstructionBlock implements ValueSymbol { private final FunctionDefinition function; private final int blockIndex; private final List<Instruction> instructions = new ArrayList<>(); private String name = LLVMIdentifier.UNKNOWN; public InstructionBlock(FunctionDefinition function, int index) { this.function = function; this.blockIndex = index; } public void accept(InstructionVisitor visitor) { for (Instruction instruction : instructions) { instruction.accept(visitor); } } private void addInstruction(Instruction element) { if (element instanceof ValueInstruction) { function.getSymbols().addSymbol(element); } instructions.add(element); } public void createAllocation(Type type, int count, int align) { addInstruction(AllocateInstruction.fromSymbols(function.getSymbols(), type, count, align)); } public void createAtomicLoad(Type type, int source, int align, boolean isVolatile, long atomicOrdering, long synchronizationScope) { addInstruction(LoadInstruction.fromSymbols(function.getSymbols(), type, source, align, isVolatile, atomicOrdering, synchronizationScope)); } public void createAtomicStore(int destination, int source, int align, boolean isVolatile, long atomicOrdering, long synchronizationScope) { addInstruction(StoreInstruction.fromSymbols(function.getSymbols(), destination, source, align, isVolatile, atomicOrdering, synchronizationScope)); } public void createBinaryOperation(Type type, int opcode, int flags, int lhs, int rhs) { addInstruction(BinaryOperationInstruction.fromSymbols(function.getSymbols(), type, opcode, flags, lhs, rhs)); } public void createBranch(int block) { addInstruction(BranchInstruction.fromTarget(function.getBlock(block))); } public void createBranch(int condition, int blockTrue, int blockFalse) { addInstruction(ConditionalBranchInstruction.fromSymbols(function.getSymbols(), condition, function.getBlock(blockTrue), function.getBlock(blockFalse))); } public void createCall(Type type, int target, int[] arguments) { if (type == VoidType.INSTANCE) { addInstruction(VoidCallInstruction.fromSymbols(function.getSymbols(), target, arguments)); } else { addInstruction(CallInstruction.fromSymbols(function.getSymbols(), type, target, arguments)); } } public void createCompareExchange(Type type, int ptr, int cmp, int replace, boolean isVolatile, long successOrdering, long synchronizationScope, long failureOrdering, boolean isWeak) { addInstruction(CompareExchangeInstruction.fromSymbols(function.getSymbols(), type, ptr, cmp, replace, isVolatile, successOrdering, synchronizationScope, failureOrdering, isWeak)); } public void createInvoke(Type type, int target, int[] arguments, int regularSuccessorBlock, int unwindSuccessorBlock) { if (type instanceof VoidType) { addInstruction(VoidInvokeInstruction.fromSymbols(function.getSymbols(), target, arguments, function.getBlock(regularSuccessorBlock), function.getBlock(unwindSuccessorBlock))); } else { addInstruction(InvokeInstruction.fromSymbols(function.getSymbols(), type, target, arguments, function.getBlock(regularSuccessorBlock), function.getBlock(unwindSuccessorBlock))); } } public void createLandingpad(Type type, boolean isCleanup, long[] clauseTypes, long[] clauseTODO) { addInstruction(LandingpadInstruction.generate(function.getSymbols(), type, isCleanup, clauseTypes, clauseTODO)); } public void createResume(@SuppressWarnings("unused") Type type) { addInstruction(ResumeInstruction.generate()); } public void createCast(Type type, int opcode, int value) { addInstruction(CastInstruction.fromSymbols(function.getSymbols(), type, opcode, value)); } public void createCompare(Type type, int opcode, int lhs, int rhs) { addInstruction(CompareInstruction.fromSymbols(function.getSymbols(), type, opcode, lhs, rhs)); } public void createExtractElement(Type type, int vector, int index) { addInstruction(ExtractElementInstruction.fromSymbols(function.getSymbols(), type, vector, index)); } public void createExtractValue(Type type, int aggregate, int index) { addInstruction(ExtractValueInstruction.fromSymbols(function.getSymbols(), type, aggregate, index)); } public void createGetElementPointer(Type type, int pointer, int[] indices, boolean isInbounds) { addInstruction(GetElementPointerInstruction.fromSymbols(function.getSymbols(), type, pointer, indices, isInbounds)); } public void createIndirectBranch(int address, int[] successors) { addInstruction(IndirectBranchInstruction.generate(function, address, successors)); } public void createInsertElement(Type type, int vector, int index, int value) { addInstruction(InsertElementInstruction.fromSymbols(function.getSymbols(), type, vector, index, value)); } public void createInsertValue(Type type, int aggregate, int index, int value) { addInstruction(InsertValueInstruction.fromSymbols(function.getSymbols(), type, aggregate, index, value)); } public void createLoad(Type type, int source, int align, boolean isVolatile) { addInstruction(LoadInstruction.fromSymbols(function.getSymbols(), type, source, align, isVolatile)); } public void createPhi(Type type, int[] values, int[] blocks) { addInstruction(PhiInstruction.generate(function, type, values, blocks)); } public void createReturn() { addInstruction(ReturnInstruction.generate()); } public void createReturn(int value) { addInstruction(ReturnInstruction.generate(function.getSymbols(), value)); } public void createSelect(Type type, int condition, int trueValue, int falseValue) { addInstruction(SelectInstruction.fromSymbols(function.getSymbols(), type, condition, trueValue, falseValue)); } public void createShuffleVector(Type type, int vector1, int vector2, int mask) { addInstruction(ShuffleVectorInstruction.fromSymbols(function.getSymbols(), type, vector1, vector2, mask)); } public void createStore(int destination, int source, int align, boolean isVolatile) { addInstruction(StoreInstruction.fromSymbols(function.getSymbols(), destination, source, align, isVolatile)); } public void createSwitch(int condition, int defaultBlock, int[] caseValues, int[] caseBlocks) { addInstruction(SwitchInstruction.generate(function, condition, defaultBlock, caseValues, caseBlocks)); } public void createSwitchOld(int condition, int defaultBlock, long[] caseConstants, int[] caseBlocks) { addInstruction(SwitchOldInstruction.generate(function, condition, defaultBlock, caseConstants, caseBlocks)); } public void createUnreachable() { addInstruction(UnreachableInstruction.generate()); } public int getBlockIndex() { return blockIndex; } @Override public String getName() { return name; } public Instruction getInstruction(int index) { return instructions.get(index); } public Symbols getFunctionSymbols() { return function.getSymbols(); } public int getInstructionCount() { return instructions.size(); } @Override public Type getType() { return VoidType.INSTANCE; } @Override public void setName(String name) { this.name = LLVMIdentifier.toBlockName(name); } public void setImplicitName(int label) { this.name = LLVMIdentifier.toImplicitBlockName(label); } @Override public String toString() { return "InstructionBlock [function=" + function.getName() + ", blockIndex=" + blockIndex + ", instructionCount=" + instructions.size() + ", name=" + name + "]"; } }