/* * 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.listeners; import java.math.BigInteger; import java.util.List; import com.oracle.truffle.llvm.parser.model.generators.ConstantGenerator; import com.oracle.truffle.llvm.parser.records.ConstantsRecord; import com.oracle.truffle.llvm.parser.records.Records; import com.oracle.truffle.llvm.runtime.types.Type; public final class Constants implements ParserListener { private static final BigInteger WIDE_INTEGER_MASK = BigInteger.ONE.shiftLeft(Long.SIZE).subtract(BigInteger.ONE); private final Types types; private final List<Type> symbols; private final ConstantGenerator generator; private Type type; Constants(Types types, List<Type> symbols, ConstantGenerator generator) { this.types = types; this.symbols = symbols; this.generator = generator; } @Override public void record(long id, long[] args) { ConstantsRecord record = ConstantsRecord.decode(id); switch (record) { case SETTYPE: type = types.get(args[0]); return; case NULL: generator.createNull(type); if (Type.isIntegerType(type)) { symbols.add(Type.createConstantForType(type, 0)); return; } break; case UNDEF: generator.createUndefined(type); break; case INTEGER: { long value = Records.toSignedValue(args[0]); generator.createInteger(type, value); symbols.add(Type.createConstantForType(type, value)); return; } case WIDE_INTEGER: { BigInteger value = BigInteger.ZERO; for (int i = 0; i < args.length; i++) { BigInteger temp = BigInteger.valueOf(Records.toSignedValue(args[i])); temp = temp.and(WIDE_INTEGER_MASK); temp = temp.shiftLeft(i * Long.SIZE); value = value.add(temp); } generator.createInteger(type, value); symbols.add(Type.createConstantForType(type, value)); return; } case FLOAT: generator.createFloatingPoint(type, args); break; case AGGREGATE: { generator.createFromValues(type, Records.toIntegers(args)); break; } case STRING: generator.creatFromString(type, Records.toString(args), false); break; case CSTRING: generator.creatFromString(type, Records.toString(args), true); break; case CE_BINOP: generator.createBinaryOperationExpression(type, (int) args[0], (int) args[1], (int) args[2]); break; case CE_CAST: generator.createCastExpression(type, (int) args[0], (int) args[2]); break; case CE_CMP: { int i = 1; int lhs = (int) args[i++]; int rhs = (int) args[i++]; int opcode = (int) args[i]; generator.createCompareExpression(type, opcode, lhs, rhs); break; } case BLOCKADDRESS: generator.createBlockAddress(type, (int) args[1], (int) args[2]); break; case DATA: generator.createFromData(type, args); break; case INLINEASM: generator.createInlineASM(type, args); break; case CE_GEP: case CE_INBOUNDS_GEP: case CE_GEP_WITH_INRANGE_INDEX: createGetElementPointerExpression(args, record); break; default: throw new UnsupportedOperationException("Unsupported Constant Record: " + record); } symbols.add(type); } private void createGetElementPointerExpression(long[] args, ConstantsRecord record) { int i = 0; if (record == ConstantsRecord.CE_GEP_WITH_INRANGE_INDEX || args.length % 2 != 0) { i++; // type of pointee } boolean isInbounds; if (record == ConstantsRecord.CE_GEP_WITH_INRANGE_INDEX) { final long op = args[i++]; isInbounds = (op & 0x1) != 0; } else { isInbounds = record == ConstantsRecord.CE_INBOUNDS_GEP; } i++; // type of pointer int pointer = (int) args[i++]; final int[] indices = new int[(args.length - i) >> 1]; for (int j = 0; j < indices.length; j++) { i++; // index type indices[j] = (int) args[i++]; } generator.createGetElementPointerExpression(type, pointer, indices, isInbounds); } }