/*
* 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.datalayout;
import java.util.Arrays;
import java.util.List;
import com.oracle.truffle.llvm.parser.datalayout.DataLayoutParser.DataTypeSpecification;
import com.oracle.truffle.llvm.runtime.types.DataSpecConverter;
import com.oracle.truffle.llvm.runtime.types.FunctionType;
import com.oracle.truffle.llvm.runtime.types.PointerType;
import com.oracle.truffle.llvm.runtime.types.PrimitiveType;
import com.oracle.truffle.llvm.runtime.types.Type;
import com.oracle.truffle.llvm.runtime.types.VariableBitWidthType;
public final class DataLayoutConverter {
public static final class DataSpecConverterImpl implements DataSpecConverter {
private final List<DataTypeSpecification> dataLayout;
private DataSpecConverterImpl(List<DataTypeSpecification> dataLayout) {
this.dataLayout = dataLayout;
}
@Override
public int getSize(Type type) {
return Math.max(1, getBitAlignment(type) / Byte.SIZE);
}
@Override
public int getBitAlignment(Type baseType) {
if (baseType instanceof VariableBitWidthType) {
/*
* Handling of integer datatypes when the exact match not found
* http://releases.llvm.org/3.9.0/docs/LangRef.html#data-layout
*/
DataTypeSpecification integerLayout = dataLayout.stream().filter(d -> d.getType() == DataLayoutType.INTEGER_WIDTHS).findFirst().orElseThrow(IllegalStateException::new);
int minPossibleSize = Arrays.stream(integerLayout.getValues()).max().orElseThrow(IllegalStateException::new);
int size = ((VariableBitWidthType) baseType).getBitSize();
for (int value : integerLayout.getValues()) {
if (size < value && minPossibleSize > value) {
minPossibleSize = value;
}
}
if (minPossibleSize >= size) {
return minPossibleSize;
} else {
// is that correct?
return ((size + 7) / 8) * 8;
}
} else {
return getDataTypeSpecification(baseType).getValues()[1];
}
}
private DataTypeSpecification getDataTypeSpecification(Type baseType) {
if (baseType instanceof PointerType) {
return locateDataTypeSpecification(DataLayoutType.POINTER);
} else if (baseType instanceof FunctionType) {
return locateDataTypeSpecification(DataLayoutType.POINTER);
} else if (baseType instanceof PrimitiveType) {
PrimitiveType primitiveType = (PrimitiveType) baseType;
switch (primitiveType.getPrimitiveKind()) {
case I1:
return locateDataTypeSpecification(DataLayoutType.INTEGER, 8); // 1 is
// rounded
// up to
// 8
case I8:
return locateDataTypeSpecification(DataLayoutType.INTEGER, 8);
case I16:
return locateDataTypeSpecification(DataLayoutType.INTEGER, 16);
case I32:
return locateDataTypeSpecification(DataLayoutType.INTEGER, 32);
case I64:
return locateDataTypeSpecification(DataLayoutType.INTEGER, 64);
case HALF:
return locateDataTypeSpecification(DataLayoutType.FLOAT, 16);
case FLOAT:
return locateDataTypeSpecification(DataLayoutType.FLOAT, 32);
case DOUBLE:
return locateDataTypeSpecification(DataLayoutType.FLOAT, 64);
case X86_FP80:
return locateDataTypeSpecification(DataLayoutType.FLOAT, 80);
}
}
throw new AssertionError(baseType);
}
private DataTypeSpecification locateDataTypeSpecification(DataLayoutType dataLayoutType) {
for (DataTypeSpecification spec : dataLayout) {
if (spec.getType().equals(dataLayoutType)) {
return spec;
}
}
throw new AssertionError(dataLayoutType);
}
private DataTypeSpecification locateDataTypeSpecification(DataLayoutType dataLayoutType, int size) {
for (DataTypeSpecification spec : dataLayout) {
if (spec.getType().equals(dataLayoutType) && size == spec.getValues()[0]) {
return spec;
}
}
throw new AssertionError(dataLayoutType + " size: " + size);
}
}
public static DataSpecConverterImpl getConverter(String layout) {
final List<DataTypeSpecification> dataLayout = DataLayoutParser.parseDataLayout(layout);
return new DataSpecConverterImpl(dataLayout);
}
}