Author: Narayan Date: 2026-05-07T16:28:10+05:30 New Revision: 07b5dfe9473c6f864027855b68fa5775d0adf2d9
URL: https://github.com/llvm/llvm-project/commit/07b5dfe9473c6f864027855b68fa5775d0adf2d9 DIFF: https://github.com/llvm/llvm-project/commit/07b5dfe9473c6f864027855b68fa5775d0adf2d9.diff LOG: [clang] Integrate LLVMABI for function call ABI lowering (#194460) This PR wires the LLVM ABI library (prototyped in https://github.com/llvm/llvm-project/pull/140112) into Clang's function call ABI lowering pipeline, behind a new `-fexperimental-abi-lowering` cc1 flag. When the flag is enabled and the active target has an LLVMABI implementation, `CodeGenTypes::arrangeLLVMFunctionInfo` constructs an `llvm::abi::FunctionInfo` from the call's argument and result types (using QualTypeMapper(https://github.com/llvm/llvm-project/pull/174634) to translate Clang QualTypes into ABI types). Asks the target's `llvm::abi::TargetInfo` to classify it, and then translates each `llvm::abi::ArgInfo` back into the ABIArgInfo consumed by the rest of CodeGen. The translation is handled by a new `convertABIArgInfo` helper covering the Direct, Extend, Indirect, and Ignore kinds, with coerce-to types lifted back into LLVM IR via a new IRTypeMapper. The integration is intentionally narrow and existing code paths are untouched. `CodeGenModule::shouldUseLLVMABILowering` only opts in for targets explicitly wired to the new library(currently only BPF). Added: llvm/include/llvm/ABI/IRTypeMapper.h llvm/lib/ABI/IRTypeMapper.cpp Modified: clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Options/Options.td clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CMakeLists.txt clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenModule.h clang/lib/CodeGen/QualTypeMapper.h clang/test/CodeGen/bpf-abiinfo.c clang/test/CodeGen/bpf-struct-argument.c clang/test/CodeGen/bpf-union-argument.c llvm/lib/ABI/CMakeLists.txt Removed: ################################################################################ diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 0d1bf83eaec9f..fd0b6d9096f50 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -28,6 +28,10 @@ CODEGENOPT(Name, Bits, Default, Compatibility) #endif CODEGENOPT(DisableIntegratedAS, 1, 0, Benign) ///< -no-integrated-as +CODEGENOPT(ExperimentalABILowering, 1, 0, Benign) ///< -fexperimental-abi-lowering: + ///< route function ABI lowering + ///< through the in-tree LLVMABI + ///< library where supported. CODEGENOPT(Crel, 1, 0, Benign) ///< -Wa,--crel ENUM_CODEGENOPT(RelocSectionSym, RelocSectionSymType, 2, RelocSectionSymType::All, Benign) ///< -Wa,--reloc-section-sym= diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 863e6b3d0871f..38cd7d4b86a0b 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -3578,6 +3578,10 @@ defm modules_reduced_bmi : BoolOption<"f", "modules-reduced-bmi", def experimental_modules_reduced_bmi : Flag<["-"], "fexperimental-modules-reduced-bmi">, Group<f_Group>, Visibility<[ClangOption, CC1Option]>, Alias<fmodules_reduced_bmi>; +def fexperimental_abi_lowering : Flag<["-"], "fexperimental-abi-lowering">, + Group<f_Group>, Visibility<[CC1Option]>, + MarshallingInfoFlag<CodeGenOpts<"ExperimentalABILowering">>; + def fmodules_embed_all_files : Joined<["-"], "fmodules-embed-all-files">, Visibility<[ClangOption, CC1Option, CLOption]>, HelpText<"Embed the contents of all files read by this compilation into " diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index c584f2eeef937..1cafe364c4c42 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -22,6 +22,7 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "CodeGenPGO.h" +#include "QualTypeMapper.h" #include "TargetInfo.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" @@ -32,6 +33,10 @@ #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/CodeGen/SwiftCallingConv.h" +#include "llvm/ABI/FunctionInfo.h" +#include "llvm/ABI/IRTypeMapper.h" +#include "llvm/ABI/TargetInfo.h" +#include "llvm/ABI/Types.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/ValueTracking.h" @@ -824,9 +829,70 @@ const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature, namespace clang { namespace CodeGen { void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); -} +} // namespace CodeGen } // namespace clang +void CodeGenModule::computeABIInfoUsingLib(CGFunctionInfo &FI) { + SmallVector<const llvm::abi::Type *> MappedArgTypes; + MappedArgTypes.reserve(FI.arg_size()); + for (const auto &Arg : FI.arguments()) + MappedArgTypes.push_back(AbiMapper->convertType(Arg.type)); + + std::optional<unsigned> NumRequired; + RequiredArgs Required = FI.getRequiredArgs(); + if (Required.allowsOptionalArgs()) + NumRequired = Required.getNumRequiredArgs(); + + llvm::abi::FunctionInfo *AbiFI = llvm::abi::FunctionInfo::create( + FI.getCallingConvention(), AbiMapper->convertType(FI.getReturnType()), + MappedArgTypes, NumRequired); + + getLLVMABITargetInfo(AbiMapper->getTypeBuilder()).computeInfo(*AbiFI); + + FI.getReturnInfo() = + convertABIArgInfo(AbiFI->getReturnInfo(), FI.getReturnType()); + + for (auto [CGArg, AbiArg] : + llvm::zip_equal(FI.arguments(), AbiFI->arguments())) + CGArg.info = convertABIArgInfo(AbiArg.Info, CGArg.type); +} + +ABIArgInfo CodeGenModule::convertABIArgInfo(const llvm::abi::ArgInfo &AbiInfo, + QualType Type) { + switch (AbiInfo.getKind()) { + case llvm::abi::ArgInfo::Direct: { + llvm::Type *CoercedType = nullptr; + if (AbiInfo.getCoerceToType()) + CoercedType = AbiReverseMapper->convertType(AbiInfo.getCoerceToType()); + if (!CoercedType) + CoercedType = getTypes().ConvertType(Type); + return ABIArgInfo::getDirect(CoercedType, AbiInfo.getDirectOffset()); + } + case llvm::abi::ArgInfo::Extend: { + llvm::Type *CoercedType = nullptr; + if (AbiInfo.getCoerceToType()) + CoercedType = AbiReverseMapper->convertType(AbiInfo.getCoerceToType()); + if (!CoercedType) + CoercedType = getTypes().ConvertType(Type); + if (AbiInfo.isSignExt()) + return ABIArgInfo::getSignExtend(Type, CoercedType); + if (AbiInfo.isZeroExt()) + return ABIArgInfo::getZeroExtend(Type, CoercedType); + return ABIArgInfo::getExtend(Type, CoercedType); + } + case llvm::abi::ArgInfo::Indirect: { + CharUnits Alignment = + CharUnits::fromQuantity(AbiInfo.getIndirectAlign().value()); + return ABIArgInfo::getIndirect(Alignment, AbiInfo.getIndirectAddrSpace(), + AbiInfo.getIndirectByVal(), + AbiInfo.getIndirectRealign()); + } + case llvm::abi::ArgInfo::Ignore: + return ABIArgInfo::getIgnore(); + } + llvm_unreachable("Unexpected llvm::abi::ArgInfo kind"); +} + /// Arrange the argument and result information for an abstract value /// of a given function type. This is the method which all of the /// above functions ultimately defer to. @@ -876,6 +942,8 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo( computeSPIRKernelABIInfo(CGM, *FI); } else if (info.getCC() == CC_Swift || info.getCC() == CC_SwiftAsync) { swiftcall::computeABIInfo(CGM, *FI); + } else if (CGM.shouldUseLLVMABILowering()) { + CGM.computeABIInfoUsingLib(*FI); } else { CGM.getABIInfo().computeInfo(*FI); } diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 434781b3c4f02..117438c616ab5 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + ABI AggressiveInstCombine Analysis BitReader diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e88fed1296667..106f1e63cd904 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -26,6 +26,7 @@ #include "CodeGenPGO.h" #include "ConstantEmitter.h" #include "CoverageMappingGen.h" +#include "QualTypeMapper.h" #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" @@ -47,6 +48,8 @@ #include "clang/Basic/Version.h" #include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/ConstantInitBuilder.h" +#include "llvm/ABI/IRTypeMapper.h" +#include "llvm/ABI/TargetInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -336,6 +339,25 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { return *TheTargetCodeGenInfo; } +bool CodeGenModule::shouldUseLLVMABILowering() const { + if (!CodeGenOpts.ExperimentalABILowering) + return false; + // Only opt in for targets that have an LLVMABI implementation; others + // continue through the legacy ABIInfo path. + return getTriple().isBPF(); +} + +const llvm::abi::TargetInfo & +CodeGenModule::getLLVMABITargetInfo(llvm::abi::TypeBuilder &TB) { + if (TheLLVMABITargetInfo) + return *TheLLVMABITargetInfo; + + assert(getTriple().isBPF() && + "LLVMABI lowering requested for an unsupported target"); + TheLLVMABITargetInfo = llvm::abi::createBPFTargetInfo(TB); + return *TheLLVMABITargetInfo; +} + static void checkDataLayoutConsistency(const TargetInfo &Target, llvm::LLVMContext &Context, const LangOptions &Opts) { @@ -420,6 +442,10 @@ CodeGenModule::CodeGenModule(ASTContext &C, SanitizerMD(new SanitizerMetadata(*this)), AtomicOpts(Target.getAtomicOpts()) { + AbiMapper = std::make_unique<QualTypeMapper>(C, M.getDataLayout(), AbiAlloc); + AbiReverseMapper = std::make_unique<llvm::abi::IRTypeMapper>( + M.getContext(), M.getDataLayout()); + // Initialize the type cache. Types.reset(new CodeGenTypes(*this)); llvm::LLVMContext &LLVMContext = M.getContext(); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index c7e168433e42c..b7dab4ef583ff 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -38,6 +38,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" +#include "llvm/Support/Allocator.h" #include "llvm/Transforms/Utils/SanitizerStats.h" #include <optional> @@ -55,6 +56,13 @@ class IndexedInstrProfReader; namespace vfs { class FileSystem; } + +namespace abi { +class ArgInfo; +class IRTypeMapper; +class TargetInfo; +class TypeBuilder; +} // namespace abi } namespace clang { @@ -95,7 +103,9 @@ class CGOpenCLRuntime; class CGOpenMPRuntime; class CGCUDARuntime; class CGHLSLRuntime; +class CGFunctionInfo; class CoverageMappingModuleGen; +class QualTypeMapper; class TargetCodeGenInfo; enum ForDefinition_t : bool { @@ -363,6 +373,18 @@ class CodeGenModule : public CodeGenTypeCache { mutable std::unique_ptr<TargetCodeGenInfo> TheTargetCodeGenInfo; + /// Cached LLVMABI target lowering info, lazily constructed when the + /// experimental ABI lowering path is taken. + mutable std::unique_ptr<llvm::abi::TargetInfo> TheLLVMABITargetInfo; + + /// Allocator and mappers used by the experimental LLVMABI-based lowering + /// path (gated on -fexperimental-abi-lowering). Constructed unconditionally + /// so the path can be entered without re-checking initialization, but the + /// caches stay empty when the flag is off. + llvm::BumpPtrAllocator AbiAlloc; + std::unique_ptr<QualTypeMapper> AbiMapper; + std::unique_ptr<llvm::abi::IRTypeMapper> AbiReverseMapper; + // This should not be moved earlier, since its initialization depends on some // of the previous reference members being already initialized and also checks // if TheTargetCodeGenInfo is NULL @@ -877,6 +899,21 @@ class CodeGenModule : public CodeGenTypeCache { void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO); const ABIInfo &getABIInfo(); + + /// Lazily build and return the LLVMABI library's TargetInfo for the current + /// target. Used by the experimental ABI lowering path + /// (-fexperimental-abi-lowering). + const llvm::abi::TargetInfo &getLLVMABITargetInfo(llvm::abi::TypeBuilder &TB); + + /// True when -fexperimental-abi-lowering is in effect AND the active target + /// has an LLVMABI implementation we can route to. + bool shouldUseLLVMABILowering() const; + + /// Drive the experimental LLVMABI-based lowering path: map argument and + /// return types into the LLVMABI library, ask its target lowering to fill + /// in classification, and write the results back into FI. + void computeABIInfoUsingLib(CGFunctionInfo &FI); + CGCXXABI &getCXXABI() const { return *ABI; } llvm::LLVMContext &getLLVMContext() { return VMContext; } @@ -1902,6 +1939,12 @@ class CodeGenModule : public CodeGenTypeCache { llvm::GlobalValue *getPFPDeactivationSymbol(const FieldDecl *FD); private: + /// Translate an llvm::abi::ArgInfo (computed by the LLVMABI library) into + /// the clang ABIArgInfo consumed by the rest of CodeGen. Used by the + /// experimental ABI lowering path. + ABIArgInfo convertABIArgInfo(const llvm::abi::ArgInfo &AbiInfo, + QualType Type); + bool shouldDropDLLAttribute(const Decl *D, const llvm::GlobalValue *GV) const; llvm::Constant *GetOrCreateLLVMFunction( diff --git a/clang/lib/CodeGen/QualTypeMapper.h b/clang/lib/CodeGen/QualTypeMapper.h index 11e8ba86cfcdf..35876f44f3aba 100644 --- a/clang/lib/CodeGen/QualTypeMapper.h +++ b/clang/lib/CodeGen/QualTypeMapper.h @@ -71,7 +71,7 @@ class QualTypeMapper { void clearCache() { TypeCache.clear(); } - llvm::abi::TypeBuilder getTypeBuilder() { return Builder; } + llvm::abi::TypeBuilder &getTypeBuilder() { return Builder; } }; } // namespace CodeGen diff --git a/clang/test/CodeGen/bpf-abiinfo.c b/clang/test/CodeGen/bpf-abiinfo.c index 366e8003f4557..f3f421fcde520 100644 --- a/clang/test/CodeGen/bpf-abiinfo.c +++ b/clang/test/CodeGen/bpf-abiinfo.c @@ -1,5 +1,6 @@ // REQUIRES: bpf-registered-target // RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes -fexperimental-abi-lowering %s -o - | FileCheck %s _Bool bar_bool(void); unsigned char bar_char(void); diff --git a/clang/test/CodeGen/bpf-struct-argument.c b/clang/test/CodeGen/bpf-struct-argument.c index d4fcf16af2e28..bdfdbbb61770f 100644 --- a/clang/test/CodeGen/bpf-struct-argument.c +++ b/clang/test/CodeGen/bpf-struct-argument.c @@ -1,5 +1,6 @@ // REQUIRES: bpf-registered-target // RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes -fexperimental-abi-lowering %s -o - | FileCheck %s struct t1 {}; struct t2 { diff --git a/clang/test/CodeGen/bpf-union-argument.c b/clang/test/CodeGen/bpf-union-argument.c index 5f3a0bc5a9261..7020f2f999d44 100644 --- a/clang/test/CodeGen/bpf-union-argument.c +++ b/clang/test/CodeGen/bpf-union-argument.c @@ -1,5 +1,6 @@ // REQUIRES: bpf-registered-target // RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes -fexperimental-abi-lowering %s -o - | FileCheck %s union t1 {}; union t2 { diff --git a/llvm/include/llvm/ABI/IRTypeMapper.h b/llvm/include/llvm/ABI/IRTypeMapper.h new file mode 100644 index 0000000000000..1a77cfd91bca9 --- /dev/null +++ b/llvm/include/llvm/ABI/IRTypeMapper.h @@ -0,0 +1,60 @@ +//===---- IRTypeMapper.h - 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. +/// Used by frontends after the ABI library has computed argument/return +/// classification: coerce-to types in the ABI representation must be +/// translated to llvm::Type before being handed back to the IR builder. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ABI_IRTYPEMAPPER_H +#define LLVM_ABI_IRTYPEMAPPER_H + +#include "llvm/ABI/Types.h" +#include "llvm/ADT/DenseMap.h" + +namespace llvm { +class LLVMContext; +class Type; +class StructType; +class DataLayout; + +namespace abi { + +class IRTypeMapper { +public: + IRTypeMapper(LLVMContext &Ctx, const DataLayout &DL) : Context(Ctx), DL(DL) {} + + llvm::Type *convertType(const abi::Type *ABIType); + + void clearCache() { TypeCache.clear(); } + +private: + LLVMContext &Context; + const DataLayout &DL; + + llvm::DenseMap<const abi::Type *, llvm::Type *> TypeCache; + + llvm::Type *convertArrayType(const abi::ArrayType *AT); + llvm::Type *convertVectorType(const abi::VectorType *VT); + llvm::Type *convertRecordType(const abi::RecordType *RT); + llvm::Type *convertComplexType(const abi::ComplexType *CT); + llvm::Type *convertMemberPointerType(const abi::MemberPointerType *MPT); + + llvm::StructType *createStructFromFields(ArrayRef<abi::FieldInfo> Fields, + TypeSize Size, Align Alignment, + bool IsUnion); + llvm::Type *createPaddingType(uint64_t PaddingBits); +}; + +} // namespace abi +} // namespace llvm + +#endif // LLVM_ABI_ABITYPEMAPPER_H diff --git a/llvm/lib/ABI/CMakeLists.txt b/llvm/lib/ABI/CMakeLists.txt index eb1d6042a25cd..a5c102b57d074 100644 --- a/llvm/lib/ABI/CMakeLists.txt +++ b/llvm/lib/ABI/CMakeLists.txt @@ -2,6 +2,7 @@ add_llvm_component_library(LLVMABI Types.cpp FunctionInfo.cpp TargetInfo.cpp + IRTypeMapper.cpp Targets/BPF.cpp ADDITIONAL_HEADER_DIRS diff --git a/llvm/lib/ABI/IRTypeMapper.cpp b/llvm/lib/ABI/IRTypeMapper.cpp new file mode 100644 index 0000000000000..3ba4553420375 --- /dev/null +++ b/llvm/lib/ABI/IRTypeMapper.cpp @@ -0,0 +1,162 @@ +//===---- IRTypeMapper.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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/ABI/IRTypeMapper.h" +#include "llvm/ABI/Types.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Type.h" + +using namespace llvm::abi; + +llvm::Type *IRTypeMapper::convertType(const abi::Type *ABIType) { + assert(ABIType && "convertType requires a non-null ABI type"); + + auto It = TypeCache.find(ABIType); + if (It != TypeCache.end()) + return It->second; + + llvm::Type *Result = nullptr; + + switch (ABIType->getKind()) { + case abi::TypeKind::Void: + Result = llvm::Type::getVoidTy(Context); + break; + case abi::TypeKind::Integer: { + const auto *IT = cast<abi::IntegerType>(ABIType); + Result = + llvm::IntegerType::get(Context, IT->getSizeInBits().getFixedValue()); + break; + } + case abi::TypeKind::Float: { + const llvm::fltSemantics *Semantics = + cast<abi::FloatType>(ABIType)->getSemantics(); + Result = llvm::Type::getFloatingPointTy(Context, *Semantics); + break; + } + case abi::TypeKind::Pointer: + Result = llvm::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::Record: + Result = convertRecordType(cast<abi::RecordType>(ABIType)); + break; + case abi::TypeKind::Complex: + Result = convertComplexType(cast<abi::ComplexType>(ABIType)); + break; + case abi::TypeKind::MemberPointer: + Result = convertMemberPointerType(cast<abi::MemberPointerType>(ABIType)); + break; + } + + TypeCache[ABIType] = Result; + return Result; +} + +llvm::Type *IRTypeMapper::convertArrayType(const abi::ArrayType *AT) { + llvm::Type *ElementType = convertType(AT->getElementType()); + uint64_t NumElements = AT->getNumElements(); + if (AT->isMatrixType()) + return llvm::VectorType::get(ElementType, + ElementCount::getFixed(NumElements)); + return llvm::ArrayType::get(ElementType, NumElements); +} + +llvm::Type *IRTypeMapper::convertVectorType(const abi::VectorType *VT) { + llvm::Type *ElementType = convertType(VT->getElementType()); + return llvm::VectorType::get(ElementType, VT->getNumElements()); +} + +llvm::Type *IRTypeMapper::convertRecordType(const abi::RecordType *RT) { + return createStructFromFields(RT->getFields(), RT->getSizeInBits(), + RT->getAlignment(), RT->isUnion()); +} + +llvm::Type *IRTypeMapper::convertComplexType(const abi::ComplexType *CT) { + llvm::Type *ElementType = convertType(CT->getElementType()); + llvm::Type *Fields[] = {ElementType, ElementType}; + return llvm::StructType::get(Context, Fields, /*isPacked=*/false); +} + +llvm::Type * +IRTypeMapper::convertMemberPointerType(const abi::MemberPointerType *MPT) { + llvm::Type *IntPtrTy = DL.getIntPtrType(Context); + if (MPT->isFunctionPointer()) { + llvm::Type *Fields[] = {IntPtrTy, IntPtrTy}; + return llvm::StructType::get(Context, Fields, /*isPacked=*/false); + } + return IntPtrTy; +} + +llvm::Type *IRTypeMapper::createPaddingType(uint64_t PaddingBits) { + if (PaddingBits == 0) + return nullptr; + assert(PaddingBits % 8 == 0 && + "sub-byte padding cannot be expressed as an llvm::Type"); + return llvm::ArrayType::get(llvm::IntegerType::get(Context, 8), + PaddingBits / 8); +} + +llvm::StructType * +IRTypeMapper::createStructFromFields(ArrayRef<abi::FieldInfo> Fields, + TypeSize Size, Align Alignment, + bool IsUnion) { + SmallVector<llvm::Type *, 16> FieldTypes; + + if (IsUnion) { + llvm::Type *LargestFieldType = nullptr; + uint64_t LargestFieldSize = 0; + for (const auto &Field : Fields) { + llvm::Type *FieldType = convertType(Field.FieldType); + uint64_t FieldSize = Field.FieldType->getSizeInBits().getFixedValue(); + if (FieldSize > LargestFieldSize) { + LargestFieldSize = FieldSize; + LargestFieldType = FieldType; + } + } + if (LargestFieldType) { + FieldTypes.push_back(LargestFieldType); + uint64_t UnionSizeBits = Size.getFixedValue(); + if (LargestFieldSize < UnionSizeBits) { + if (llvm::Type *PaddingType = + createPaddingType(UnionSizeBits - LargestFieldSize)) + FieldTypes.push_back(PaddingType); + } + } + } else { + uint64_t CurrentOffset = 0; + for (const auto &Field : Fields) { + if (Field.OffsetInBits > CurrentOffset) { + if (llvm::Type *PaddingType = + createPaddingType(Field.OffsetInBits - CurrentOffset)) + FieldTypes.push_back(PaddingType); + CurrentOffset = Field.OffsetInBits; + } + assert(!Field.IsBitField && "bitfields should not reach IR type mapping"); + llvm::Type *FieldType = convertType(Field.FieldType); + FieldTypes.push_back(FieldType); + CurrentOffset += Field.FieldType->getSizeInBits().getFixedValue(); + } + uint64_t TotalSizeBits = Size.getFixedValue(); + if (CurrentOffset < TotalSizeBits) { + if (llvm::Type *PaddingType = + createPaddingType(TotalSizeBits - CurrentOffset)) + FieldTypes.push_back(PaddingType); + } + } + + return StructType::get(Context, FieldTypes, /*isPacked=*/false); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
