================ @@ -0,0 +1,244 @@ +//===---- ABITypeMapper.cpp - Maps LLVM ABI Types to LLVM IR Types ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Maps LLVM ABI type representations back to corresponding LLVM IR types. +/// This reverse mapper translates low-level ABI-specific types back into +/// LLVM IR types suitable for code generation and optimization passes. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/ABI/ABITypeMapper.h" +#include "llvm/ABI/Types.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Type.h" + +using namespace llvm; + +Type *ABITypeMapper::convertType(const abi::Type *ABIType) { + if (!ABIType) + return nullptr; + + auto It = TypeCache.find(ABIType); + if (It != TypeCache.end()) + return It->second; + + Type *Result = nullptr; + + switch (ABIType->getKind()) { + case abi::TypeKind::Integer: { + const auto *IT = cast<abi::IntegerType>(ABIType); + unsigned Bitwidth = IT->getSizeInBits().getFixedValue(); + Result = IntegerType::get(Context, Bitwidth); + break; + } + case abi::TypeKind::Float: + Result = convertFloatType(cast<abi::FloatType>(ABIType)); + break; + case abi::TypeKind::Pointer: + Result = PointerType::get(Context, + cast<abi::PointerType>(ABIType)->getAddrSpace()); + break; + case abi::TypeKind::Array: + Result = convertArrayType(cast<abi::ArrayType>(ABIType)); + break; + case abi::TypeKind::Vector: + Result = convertVectorType(cast<abi::VectorType>(ABIType)); + break; + case abi::TypeKind::Struct: + Result = convertStructType(cast<abi::StructType>(ABIType)); + break; + case abi::TypeKind::Void: + Result = Type::getVoidTy(Context); + break; + case abi::TypeKind::Complex: + Result = convertComplexType(cast<abi::ComplexType>(ABIType)); + break; + case abi::TypeKind::MemberPointer: + Result = convertMemberPointerType(cast<abi::MemberPointerType>(ABIType)); + break; + } + + if (Result) + TypeCache[ABIType] = Result; + + return Result; +} + +Type *ABITypeMapper::convertFloatType(const abi::FloatType *FT) { + const fltSemantics *Semantics = + const_cast<abi::FloatType *>(FT)->getSemantics(); + return Type::getFloatingPointTy(Context, *Semantics); +} + +Type *ABITypeMapper::convertArrayType(const abi::ArrayType *AT) { + Type *ElementType = convertType(AT->getElementType()); + if (!ElementType) + return nullptr; + + uint64_t NumElements = AT->getNumElements(); + if (AT->isMatrixType()) + return VectorType::get(ElementType, ElementCount::getFixed(NumElements)); + + return ArrayType::get(ElementType, NumElements); +} + +Type *ABITypeMapper::convertVectorType(const abi::VectorType *VT) { + Type *ElementType = convertType(VT->getElementType()); + if (!ElementType) + return nullptr; + + ElementCount EC = VT->getNumElements(); + + if (EC.isScalable()) + return ScalableVectorType::get(ElementType, EC.getKnownMinValue()); + return VectorType::get(ElementType, EC); +} + +Type *ABITypeMapper::convertStructType(const abi::StructType *ST) { + ArrayRef<abi::FieldInfo> FieldsArray = ST->getFields(); + return createStructFromFields(FieldsArray, ST->getNumFields(), + ST->getSizeInBits(), ST->getAlignment(), + ST->isUnion(), ST->isCoercedStruct()); +} + +Type *ABITypeMapper::convertComplexType(const abi::ComplexType *CT) { + // Complex types are represented as structs with two elements: {real, imag} + Type *ElementType = convertType(CT->getElementType()); + if (!ElementType) + return nullptr; + + SmallVector<Type *, 2> Fields = {ElementType, ElementType}; + return StructType::get(Context, Fields, /*isPacked=*/false); +} + +Type * +ABITypeMapper::convertMemberPointerType(const abi::MemberPointerType *MPT) { + + bool Has64BitPointers = DL.getPointerSizeInBits() == 64; + if (MPT->isFunctionPointer()) { + + if (Has64BitPointers) { + // {i64, i64} for function pointer + adjustment + Type *I64 = IntegerType::get(Context, 64); + SmallVector<Type *, 2> Fields = {I64, I64}; + return StructType::get(Context, Fields, /*isPacked=*/false); + } // {i32, i32} for 32-bit systems + Type *I32 = IntegerType::get(Context, 32); + SmallVector<Type *, 2> Fields = {I32, I32}; + return StructType::get(Context, Fields, /*isPacked=*/false); + + } // Data member pointer - single offset value + if (Has64BitPointers) + return IntegerType::get(Context, 64); + return IntegerType::get(Context, 32); +} + +StructType *ABITypeMapper::createStructFromFields( + ArrayRef<abi::FieldInfo> Fields, uint32_t NumFields, TypeSize Size, + Align Alignment, bool IsUnion, bool IsCoercedStr) { + SmallVector<Type *, 16> FieldTypes; + + if (IsUnion) { + Type *LargestFieldType = nullptr; + uint64_t LargestFieldSize = 0; + + for (const auto &Field : Fields) { + Type *FieldType = convertType(Field.FieldType); + if (!FieldType) + continue; + + uint64_t FieldSize = 0; + if (auto *IntTy = dyn_cast<IntegerType>(FieldType)) { + FieldSize = IntTy->getBitWidth(); + } else if (FieldType->isFloatingPointTy()) { + FieldSize = FieldType->getPrimitiveSizeInBits(); + } else if (FieldType->isPointerTy()) { + FieldSize = Field.FieldType->getSizeInBits(); + } + + if (FieldSize > LargestFieldSize) { + LargestFieldSize = FieldSize; + LargestFieldType = FieldType; + } + } + + if (LargestFieldType) { + FieldTypes.push_back(LargestFieldType); + + uint64_t UnionSizeBits = Size.getFixedValue(); + if (LargestFieldSize < UnionSizeBits) { + uint64_t PaddingBits = UnionSizeBits - LargestFieldSize; + if (PaddingBits % 8 == 0) { + Type *ByteType = IntegerType::get(Context, 8); + Type *PaddingType = ArrayType::get(ByteType, PaddingBits / 8); + FieldTypes.push_back(PaddingType); + } else { + Type *PaddingType = IntegerType::get(Context, PaddingBits); + FieldTypes.push_back(PaddingType); + } + } + } + } else { + uint64_t CurrentOffset = 0; + + for (const auto &Field : Fields) { + if (!IsCoercedStr && Field.OffsetInBits > CurrentOffset) { + uint64_t PaddingBits = Field.OffsetInBits - CurrentOffset; + if (PaddingBits % 8 == 0 && PaddingBits >= 8) { + Type *ByteType = IntegerType::get(Context, 8); + Type *PaddingType = ArrayType::get(ByteType, PaddingBits / 8); + FieldTypes.push_back(PaddingType); + } else if (PaddingBits > 0) { + Type *PaddingType = IntegerType::get(Context, PaddingBits); + FieldTypes.push_back(PaddingType); + } + CurrentOffset = Field.OffsetInBits; + } + + Type *FieldType = convertType(Field.FieldType); + if (!FieldType) + continue; + + if (Field.IsBitField && Field.BitFieldWidth > 0) { ---------------- nikic wrote:
Looking at this code, I doubt it does something correct for bit fields. Bit field layout is complicated. For what kind of structs does ABITypeMapper actually get used? Does it only ever get used on "coerced structs" in practice, or also other ones? https://github.com/llvm/llvm-project/pull/140112 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits