[clang] [llvm] [WIP] ABI Lowering Library (PR #140112)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 21 09:30:03 PDT 2025


================
@@ -0,0 +1,241 @@
+//===---- 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"
+#include "llvm/Support/ErrorHandling.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:
+    Result = convertIntegerType(cast<abi::IntegerType>(ABIType));
+    break;
+  case abi::TypeKind::Float:
+    Result = convertFloatType(cast<abi::FloatType>(ABIType));
+    break;
+  case abi::TypeKind::Pointer:
+    Result = convertPointerType(cast<abi::PointerType>(ABIType));
+    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::Union:
+    Result = convertUnionType(cast<abi::UnionType>(ABIType));
+    break;
+  case abi::TypeKind::Void:
+    Result = convertVoidType(cast<abi::VoidType>(ABIType));
+    break;
+  default:
+    llvm_unreachable("Unknown ABI type kind");
+  }
+
+  if (Result)
+    TypeCache[ABIType] = Result;
+
+  return Result;
+}
+
+Type *ABITypeMapper::convertIntegerType(const abi::IntegerType *IT) {
+  unsigned BitWidth = IT->getSizeInBits();
+  return IntegerType::get(Context, BitWidth);
+}
+
+Type *ABITypeMapper::convertFloatType(const abi::FloatType *FT) {
+  const fltSemantics *Semantics =
+      const_cast<abi::FloatType *>(FT)->getSemantics();
+  return getFloatTypeForSemantics(*Semantics);
+}
+
+Type *ABITypeMapper::convertPointerType(const abi::PointerType *PT) {
+  return PointerType::get(Context, 0);
+}
+
+Type *ABITypeMapper::convertArrayType(const abi::ArrayType *AT) {
+  Type *ElementType = convertType(AT->getElementType());
+  if (!ElementType)
+    return nullptr;
+
+  uint64_t NumElements = AT->getNumElements();
+
+  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 FixedVectorType::get(ElementType, EC.getFixedValue());
+}
+
+Type *ABITypeMapper::convertStructType(const abi::StructType *ST) {
+  return createStructFromFields(*ST->getFields(), ST->getNumFields(),
+                                ST->getSizeInBits(), ST->getAlignment(), false);
+}
+
+Type *ABITypeMapper::convertUnionType(const abi::UnionType *UT) {
+  return createStructFromFields(*UT->getFields(), UT->getNumFields(),
+                                UT->getSizeInBits(), UT->getAlignment(), true);
+}
+
+Type *ABITypeMapper::convertVoidType(const abi::VoidType *VT) {
+  return Type::getVoidTy(Context);
+}
+
+Type *ABITypeMapper::getFloatTypeForSemantics(const fltSemantics &Semantics) {
+  if (&Semantics == &APFloat::IEEEhalf())
+    return Type::getHalfTy(Context);
+  if (&Semantics == &APFloat::BFloat())
+    return Type::getBFloatTy(Context);
+  if (&Semantics == &APFloat::IEEEsingle())
+    return Type::getFloatTy(Context);
+  if (&Semantics == &APFloat::IEEEdouble())
+    return Type::getDoubleTy(Context);
+  if (&Semantics == &APFloat::x87DoubleExtended())
+    return Type::getX86_FP80Ty(Context);
+  if (&Semantics == &APFloat::IEEEquad())
+    return Type::getFP128Ty(Context);
+  if (&Semantics == &APFloat::PPCDoubleDouble())
+    return Type::getPPC_FP128Ty(Context);
+
+  // Fallback
+  return Type::getDoubleTy(Context);
+}
+
+StructType *
+ABITypeMapper::createStructFromFields(ArrayRef<abi::FieldInfo> Fields,
+                                      uint32_t NumFields, TypeSize Size,
+                                      Align Alignment, bool IsUnion) {
----------------
nikic wrote:

Hmm... this is tricky. I'm not entirely sure what to do here. For the purpose of mapping ABIArgInfo, we should never encounter unions. For the struct case, things are tricky. Mostly, I believe we just want LLVM structs as a means of holding multiple values. E.g. a StructType for Direct arguments will normally get unpacked into individual arguments. In this case, we really don't want any kind of padding fillers in it. I think the only case that cares about that is CoerceAndExpand, which has two struct types, one just with the elements (which will be passed as separate arguments) and one that has the actual layout (with correct alignment etc).

This kind of makes me wonder whether it would make sense to start by storing llvm types in ABIArgInfo to match what clang currently does. abi::Type is conceptually nicer, but also not quite the right representation for everything (e.g. because it can't really represent the "struct without layout" case well).

https://github.com/llvm/llvm-project/pull/140112


More information about the llvm-commits mailing list