1//===---- IRTypeMapper.cpp - Maps LLVM ABI Types to LLVM IR Types -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ABI/IRTypeMapper.h"
10#include "llvm/ABI/Types.h"
11#include "llvm/ADT/APFloat.h"
12#include "llvm/ADT/SmallVector.h"
13#include "llvm/IR/DataLayout.h"
14#include "llvm/IR/DerivedTypes.h"
15#include "llvm/IR/Type.h"
16
17using namespace llvm::abi;
18
19llvm::Type *IRTypeMapper::convertType(const abi::Type *ABIType) {
20 assert(ABIType && "convertType requires a non-null ABI type");
21
22 auto It = TypeCache.find(Val: ABIType);
23 if (It != TypeCache.end())
24 return It->second;
25
26 llvm::Type *Result = nullptr;
27
28 switch (ABIType->getKind()) {
29 case abi::TypeKind::Void:
30 Result = llvm::Type::getVoidTy(C&: Context);
31 break;
32 case abi::TypeKind::Integer: {
33 const auto *IT = cast<abi::IntegerType>(Val: ABIType);
34 Result =
35 llvm::IntegerType::get(C&: Context, NumBits: IT->getSizeInBits().getFixedValue());
36 break;
37 }
38 case abi::TypeKind::Float: {
39 const llvm::fltSemantics *Semantics =
40 cast<abi::FloatType>(Val: ABIType)->getSemantics();
41 Result = llvm::Type::getFloatingPointTy(C&: Context, S: *Semantics);
42 break;
43 }
44 case abi::TypeKind::Pointer:
45 Result = llvm::PointerType::get(
46 C&: Context, AddressSpace: cast<abi::PointerType>(Val: ABIType)->getAddrSpace());
47 break;
48 case abi::TypeKind::Array:
49 Result = convertArrayType(AT: cast<abi::ArrayType>(Val: ABIType));
50 break;
51 case abi::TypeKind::Vector:
52 Result = convertVectorType(VT: cast<abi::VectorType>(Val: ABIType));
53 break;
54 case abi::TypeKind::Record:
55 Result = convertRecordType(RT: cast<abi::RecordType>(Val: ABIType));
56 break;
57 case abi::TypeKind::Complex:
58 Result = convertComplexType(CT: cast<abi::ComplexType>(Val: ABIType));
59 break;
60 case abi::TypeKind::MemberPointer:
61 Result = convertMemberPointerType(MPT: cast<abi::MemberPointerType>(Val: ABIType));
62 break;
63 }
64
65 TypeCache[ABIType] = Result;
66 return Result;
67}
68
69llvm::Type *IRTypeMapper::convertArrayType(const abi::ArrayType *AT) {
70 llvm::Type *ElementType = convertType(ABIType: AT->getElementType());
71 uint64_t NumElements = AT->getNumElements();
72 if (AT->isMatrixType())
73 return llvm::VectorType::get(ElementType,
74 EC: ElementCount::getFixed(MinVal: NumElements));
75 return llvm::ArrayType::get(ElementType, NumElements);
76}
77
78llvm::Type *IRTypeMapper::convertVectorType(const abi::VectorType *VT) {
79 llvm::Type *ElementType = convertType(ABIType: VT->getElementType());
80 return llvm::VectorType::get(ElementType, EC: VT->getNumElements());
81}
82
83llvm::Type *IRTypeMapper::convertRecordType(const abi::RecordType *RT) {
84 return createStructFromFields(Fields: RT->getFields(), Size: RT->getSizeInBits(),
85 Alignment: RT->getAlignment(), IsUnion: RT->isUnion());
86}
87
88llvm::Type *IRTypeMapper::convertComplexType(const abi::ComplexType *CT) {
89 llvm::Type *ElementType = convertType(ABIType: CT->getElementType());
90 llvm::Type *Fields[] = {ElementType, ElementType};
91 return llvm::StructType::get(Context, Elements: Fields, /*isPacked=*/false);
92}
93
94llvm::Type *
95IRTypeMapper::convertMemberPointerType(const abi::MemberPointerType *MPT) {
96 llvm::Type *IntPtrTy = DL.getIntPtrType(C&: Context);
97 if (MPT->isFunctionPointer()) {
98 llvm::Type *Fields[] = {IntPtrTy, IntPtrTy};
99 return llvm::StructType::get(Context, Elements: Fields, /*isPacked=*/false);
100 }
101 return IntPtrTy;
102}
103
104llvm::Type *IRTypeMapper::createPaddingType(uint64_t PaddingBits) {
105 if (PaddingBits == 0)
106 return nullptr;
107 assert(PaddingBits % 8 == 0 &&
108 "sub-byte padding cannot be expressed as an llvm::Type");
109 return llvm::ArrayType::get(ElementType: llvm::IntegerType::get(C&: Context, NumBits: 8),
110 NumElements: PaddingBits / 8);
111}
112
113llvm::StructType *
114IRTypeMapper::createStructFromFields(ArrayRef<abi::FieldInfo> Fields,
115 TypeSize Size, Align Alignment,
116 bool IsUnion) {
117 SmallVector<llvm::Type *, 16> FieldTypes;
118
119 if (IsUnion) {
120 llvm::Type *LargestFieldType = nullptr;
121 uint64_t LargestFieldSize = 0;
122 for (const auto &Field : Fields) {
123 llvm::Type *FieldType = convertType(ABIType: Field.FieldType);
124 uint64_t FieldSize = Field.FieldType->getSizeInBits().getFixedValue();
125 if (FieldSize > LargestFieldSize) {
126 LargestFieldSize = FieldSize;
127 LargestFieldType = FieldType;
128 }
129 }
130 if (LargestFieldType) {
131 FieldTypes.push_back(Elt: LargestFieldType);
132 uint64_t UnionSizeBits = Size.getFixedValue();
133 if (LargestFieldSize < UnionSizeBits) {
134 if (llvm::Type *PaddingType =
135 createPaddingType(PaddingBits: UnionSizeBits - LargestFieldSize))
136 FieldTypes.push_back(Elt: PaddingType);
137 }
138 }
139 } else {
140 uint64_t CurrentOffset = 0;
141 for (const auto &Field : Fields) {
142 if (Field.OffsetInBits > CurrentOffset) {
143 if (llvm::Type *PaddingType =
144 createPaddingType(PaddingBits: Field.OffsetInBits - CurrentOffset))
145 FieldTypes.push_back(Elt: PaddingType);
146 CurrentOffset = Field.OffsetInBits;
147 }
148 assert(!Field.IsBitField && "bitfields should not reach IR type mapping");
149 llvm::Type *FieldType = convertType(ABIType: Field.FieldType);
150 FieldTypes.push_back(Elt: FieldType);
151 CurrentOffset += Field.FieldType->getSizeInBits().getFixedValue();
152 }
153 uint64_t TotalSizeBits = Size.getFixedValue();
154 if (CurrentOffset < TotalSizeBits) {
155 if (llvm::Type *PaddingType =
156 createPaddingType(PaddingBits: TotalSizeBits - CurrentOffset))
157 FieldTypes.push_back(Elt: PaddingType);
158 }
159 }
160
161 return StructType::get(Context, Elements: FieldTypes, /*isPacked=*/false);
162}
163