479 lines · cpp
1//===- ABIInfoImpl.cpp ----------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "ABIInfoImpl.h"10 11using namespace clang;12using namespace clang::CodeGen;13 14// Pin the vtable to this file.15DefaultABIInfo::~DefaultABIInfo() = default;16 17ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {18 Ty = useFirstFieldIfTransparentUnion(Ty);19 20 if (isAggregateTypeForABI(Ty)) {21 // Records with non-trivial destructors/copy-constructors should not be22 // passed by value.23 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))24 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),25 RAA == CGCXXABI::RAA_DirectInMemory);26 27 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());28 }29 30 // Treat an enum type as its underlying type.31 if (const auto *ED = Ty->getAsEnumDecl())32 Ty = ED->getIntegerType();33 34 ASTContext &Context = getContext();35 if (const auto *EIT = Ty->getAs<BitIntType>())36 if (EIT->getNumBits() >37 Context.getTypeSize(Context.getTargetInfo().hasInt128Type()38 ? Context.Int128Ty39 : Context.LongLongTy))40 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());41 42 return (isPromotableIntegerTypeForABI(Ty)43 ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty))44 : ABIArgInfo::getDirect());45}46 47ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {48 if (RetTy->isVoidType())49 return ABIArgInfo::getIgnore();50 51 if (isAggregateTypeForABI(RetTy))52 return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());53 54 // Treat an enum type as its underlying type.55 if (const auto *ED = RetTy->getAsEnumDecl())56 RetTy = ED->getIntegerType();57 58 if (const auto *EIT = RetTy->getAs<BitIntType>())59 if (EIT->getNumBits() >60 getContext().getTypeSize(getContext().getTargetInfo().hasInt128Type()61 ? getContext().Int128Ty62 : getContext().LongLongTy))63 return getNaturalAlignIndirect(RetTy,64 getDataLayout().getAllocaAddrSpace());65 66 return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)67 : ABIArgInfo::getDirect());68}69 70void DefaultABIInfo::computeInfo(CGFunctionInfo &FI) const {71 if (!getCXXABI().classifyReturnType(FI))72 FI.getReturnInfo() = classifyReturnType(FI.getReturnType());73 for (auto &I : FI.arguments())74 I.info = classifyArgumentType(I.type);75}76 77RValue DefaultABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,78 QualType Ty, AggValueSlot Slot) const {79 return CGF.EmitLoadOfAnyValue(80 CGF.MakeAddrLValue(81 EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty)), Ty),82 Slot);83}84 85void CodeGen::AssignToArrayRange(CodeGen::CGBuilderTy &Builder,86 llvm::Value *Array, llvm::Value *Value,87 unsigned FirstIndex, unsigned LastIndex) {88 // Alternatively, we could emit this as a loop in the source.89 for (unsigned I = FirstIndex; I <= LastIndex; ++I) {90 llvm::Value *Cell =91 Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(), Array, I);92 Builder.CreateAlignedStore(Value, Cell, CharUnits::One());93 }94}95 96bool CodeGen::isAggregateTypeForABI(QualType T) {97 return !CodeGenFunction::hasScalarEvaluationKind(T) ||98 T->isMemberFunctionPointerType();99}100 101llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) {102 return CGF.ConvertTypeForMem(103 CGF.getContext().getBuiltinVaListType()->getPointeeType());104}105 106CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT,107 CGCXXABI &CXXABI) {108 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();109 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))110 return CXXABI.getRecordArgABI(CXXRD);111 if (!RD->canPassInRegisters())112 return CGCXXABI::RAA_Indirect;113 return CGCXXABI::RAA_Default;114}115 116CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(QualType T, CGCXXABI &CXXABI) {117 const RecordType *RT = T->getAsCanonical<RecordType>();118 if (!RT)119 return CGCXXABI::RAA_Default;120 return getRecordArgABI(RT, CXXABI);121}122 123bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI,124 const ABIInfo &Info) {125 QualType Ty = FI.getReturnType();126 127 if (const auto *RD = Ty->getAsRecordDecl();128 RD && !isa<CXXRecordDecl>(RD) && !RD->canPassInRegisters()) {129 FI.getReturnInfo() = Info.getNaturalAlignIndirect(130 Ty, Info.getDataLayout().getAllocaAddrSpace());131 return true;132 }133 134 return CXXABI.classifyReturnType(FI);135}136 137QualType CodeGen::useFirstFieldIfTransparentUnion(QualType Ty) {138 if (const RecordType *UT = Ty->getAsUnionType()) {139 const RecordDecl *UD = UT->getDecl()->getDefinitionOrSelf();140 if (UD->hasAttr<TransparentUnionAttr>()) {141 assert(!UD->field_empty() && "sema created an empty transparent union");142 return UD->field_begin()->getType();143 }144 }145 return Ty;146}147 148llvm::Value *CodeGen::emitRoundPointerUpToAlignment(CodeGenFunction &CGF,149 llvm::Value *Ptr,150 CharUnits Align) {151 // OverflowArgArea = (OverflowArgArea + Align - 1) & -Align;152 llvm::Value *RoundUp = CGF.Builder.CreateConstInBoundsGEP1_32(153 CGF.Builder.getInt8Ty(), Ptr, Align.getQuantity() - 1);154 return CGF.Builder.CreateIntrinsic(155 llvm::Intrinsic::ptrmask, {Ptr->getType(), CGF.IntPtrTy},156 {RoundUp, llvm::ConstantInt::get(CGF.IntPtrTy, -Align.getQuantity())},157 nullptr, Ptr->getName() + ".aligned");158}159 160Address161CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr,162 llvm::Type *DirectTy, CharUnits DirectSize,163 CharUnits DirectAlign, CharUnits SlotSize,164 bool AllowHigherAlign, bool ForceRightAdjust) {165 // Cast the element type to i8* if necessary. Some platforms define166 // va_list as a struct containing an i8* instead of just an i8*.167 if (VAListAddr.getElementType() != CGF.Int8PtrTy)168 VAListAddr = VAListAddr.withElementType(CGF.Int8PtrTy);169 170 llvm::Value *Ptr = CGF.Builder.CreateLoad(VAListAddr, "argp.cur");171 172 // If the CC aligns values higher than the slot size, do so if needed.173 Address Addr = Address::invalid();174 if (AllowHigherAlign && DirectAlign > SlotSize) {175 Addr = Address(emitRoundPointerUpToAlignment(CGF, Ptr, DirectAlign),176 CGF.Int8Ty, DirectAlign);177 } else {178 Addr = Address(Ptr, CGF.Int8Ty, SlotSize);179 }180 181 // Advance the pointer past the argument, then store that back.182 CharUnits FullDirectSize = DirectSize.alignTo(SlotSize);183 Address NextPtr =184 CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next");185 CGF.Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr);186 187 // If the argument is smaller than a slot, and this is a big-endian188 // target, the argument will be right-adjusted in its slot.189 if (DirectSize < SlotSize && CGF.CGM.getDataLayout().isBigEndian() &&190 (!DirectTy->isStructTy() || ForceRightAdjust)) {191 Addr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, SlotSize - DirectSize);192 }193 194 return Addr.withElementType(DirectTy);195}196 197RValue CodeGen::emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,198 QualType ValueTy, bool IsIndirect,199 TypeInfoChars ValueInfo,200 CharUnits SlotSizeAndAlign,201 bool AllowHigherAlign, AggValueSlot Slot,202 bool ForceRightAdjust) {203 // The size and alignment of the value that was passed directly.204 CharUnits DirectSize, DirectAlign;205 if (IsIndirect) {206 DirectSize = CGF.getPointerSize();207 DirectAlign = CGF.getPointerAlign();208 } else {209 DirectSize = ValueInfo.Width;210 DirectAlign = ValueInfo.Align;211 }212 213 // Cast the address we've calculated to the right type.214 llvm::Type *DirectTy = CGF.ConvertTypeForMem(ValueTy), *ElementTy = DirectTy;215 if (IsIndirect) {216 unsigned AllocaAS = CGF.CGM.getDataLayout().getAllocaAddrSpace();217 DirectTy = llvm::PointerType::get(CGF.getLLVMContext(), AllocaAS);218 }219 220 Address Addr = emitVoidPtrDirectVAArg(CGF, VAListAddr, DirectTy, DirectSize,221 DirectAlign, SlotSizeAndAlign,222 AllowHigherAlign, ForceRightAdjust);223 224 if (IsIndirect) {225 Addr = Address(CGF.Builder.CreateLoad(Addr), ElementTy, ValueInfo.Align);226 }227 228 return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(Addr, ValueTy), Slot);229}230 231Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1,232 llvm::BasicBlock *Block1, Address Addr2,233 llvm::BasicBlock *Block2,234 const llvm::Twine &Name) {235 assert(Addr1.getType() == Addr2.getType());236 llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name);237 PHI->addIncoming(Addr1.emitRawPointer(CGF), Block1);238 PHI->addIncoming(Addr2.emitRawPointer(CGF), Block2);239 CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment());240 return Address(PHI, Addr1.getElementType(), Align);241}242 243bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD,244 bool AllowArrays, bool AsIfNoUniqueAddr) {245 if (FD->isUnnamedBitField())246 return true;247 248 QualType FT = FD->getType();249 250 // Constant arrays of empty records count as empty, strip them off.251 // Constant arrays of zero length always count as empty.252 bool WasArray = false;253 if (AllowArrays)254 while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {255 if (AT->isZeroSize())256 return true;257 FT = AT->getElementType();258 // The [[no_unique_address]] special case below does not apply to259 // arrays of C++ empty records, so we need to remember this fact.260 WasArray = true;261 }262 263 const RecordType *RT = FT->getAsCanonical<RecordType>();264 if (!RT)265 return false;266 267 // C++ record fields are never empty, at least in the Itanium ABI.268 //269 // FIXME: We should use a predicate for whether this behavior is true in the270 // current ABI.271 //272 // The exception to the above rule are fields marked with the273 // [[no_unique_address]] attribute (since C++20). Those do count as empty274 // according to the Itanium ABI. The exception applies only to records,275 // not arrays of records, so we must also check whether we stripped off an276 // array type above.277 if (isa<CXXRecordDecl>(RT->getDecl()) &&278 (WasArray || (!AsIfNoUniqueAddr && !FD->hasAttr<NoUniqueAddressAttr>())))279 return false;280 281 return isEmptyRecord(Context, FT, AllowArrays, AsIfNoUniqueAddr);282}283 284bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,285 bool AsIfNoUniqueAddr) {286 const auto *RD = T->getAsRecordDecl();287 if (!RD)288 return false;289 if (RD->hasFlexibleArrayMember())290 return false;291 292 // If this is a C++ record, check the bases first.293 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))294 for (const auto &I : CXXRD->bases())295 if (!isEmptyRecord(Context, I.getType(), true, AsIfNoUniqueAddr))296 return false;297 298 for (const auto *I : RD->fields())299 if (!isEmptyField(Context, I, AllowArrays, AsIfNoUniqueAddr))300 return false;301 return true;302}303 304bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context,305 const FieldDecl *FD) {306 if (FD->isZeroLengthBitField())307 return true;308 309 if (FD->isUnnamedBitField())310 return false;311 312 return isEmptyRecordForLayout(Context, FD->getType());313}314 315bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) {316 const auto *RD = T->getAsRecordDecl();317 if (!RD)318 return false;319 320 // If this is a C++ record, check the bases first.321 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {322 if (CXXRD->isDynamicClass())323 return false;324 325 for (const auto &I : CXXRD->bases())326 if (!isEmptyRecordForLayout(Context, I.getType()))327 return false;328 }329 330 for (const auto *I : RD->fields())331 if (!isEmptyFieldForLayout(Context, I))332 return false;333 334 return true;335}336 337const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {338 const auto *RD = T->getAsRecordDecl();339 if (!RD)340 return nullptr;341 342 if (RD->hasFlexibleArrayMember())343 return nullptr;344 345 const Type *Found = nullptr;346 347 // If this is a C++ record, check the bases first.348 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {349 for (const auto &I : CXXRD->bases()) {350 // Ignore empty records.351 if (isEmptyRecord(Context, I.getType(), true))352 continue;353 354 // If we already found an element then this isn't a single-element struct.355 if (Found)356 return nullptr;357 358 // If this is non-empty and not a single element struct, the composite359 // cannot be a single element struct.360 Found = isSingleElementStruct(I.getType(), Context);361 if (!Found)362 return nullptr;363 }364 }365 366 // Check for single element.367 for (const auto *FD : RD->fields()) {368 QualType FT = FD->getType();369 370 // Ignore empty fields.371 if (isEmptyField(Context, FD, true))372 continue;373 374 // If we already found an element then this isn't a single-element375 // struct.376 if (Found)377 return nullptr;378 379 // Treat single element arrays as the element.380 while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {381 if (AT->getZExtSize() != 1)382 break;383 FT = AT->getElementType();384 }385 386 if (!isAggregateTypeForABI(FT)) {387 Found = FT.getTypePtr();388 } else {389 Found = isSingleElementStruct(FT, Context);390 if (!Found)391 return nullptr;392 }393 }394 395 // We don't consider a struct a single-element struct if it has396 // padding beyond the element type.397 if (Found && Context.getTypeSize(Found) != Context.getTypeSize(T))398 return nullptr;399 400 return Found;401}402 403Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr,404 QualType Ty, const ABIArgInfo &AI) {405 // This default implementation defers to the llvm backend's va_arg406 // instruction. It can handle only passing arguments directly407 // (typically only handled in the backend for primitive types), or408 // aggregates passed indirectly by pointer (NOTE: if the "byval"409 // flag has ABI impact in the callee, this implementation cannot410 // work.)411 412 // Only a few cases are covered here at the moment -- those needed413 // by the default abi.414 llvm::Value *Val;415 416 if (AI.isIndirect()) {417 assert(!AI.getPaddingType() &&418 "Unexpected PaddingType seen in arginfo in generic VAArg emitter!");419 assert(420 !AI.getIndirectRealign() &&421 "Unexpected IndirectRealign seen in arginfo in generic VAArg emitter!");422 423 auto TyInfo = CGF.getContext().getTypeInfoInChars(Ty);424 CharUnits TyAlignForABI = TyInfo.Align;425 426 llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty);427 llvm::Type *BaseTy = llvm::PointerType::getUnqual(CGF.getLLVMContext());428 llvm::Value *Addr =429 CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), BaseTy);430 return Address(Addr, ElementTy, TyAlignForABI);431 } else {432 assert((AI.isDirect() || AI.isExtend()) &&433 "Unexpected ArgInfo Kind in generic VAArg emitter!");434 435 assert(!AI.getInReg() &&436 "Unexpected InReg seen in arginfo in generic VAArg emitter!");437 assert(!AI.getPaddingType() &&438 "Unexpected PaddingType seen in arginfo in generic VAArg emitter!");439 assert(!AI.getDirectOffset() &&440 "Unexpected DirectOffset seen in arginfo in generic VAArg emitter!");441 assert(!AI.getCoerceToType() &&442 "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!");443 444 Address Temp = CGF.CreateMemTemp(Ty, "varet");445 Val = CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF),446 CGF.ConvertTypeForMem(Ty));447 CGF.Builder.CreateStore(Val, Temp);448 return Temp;449 }450}451 452bool CodeGen::isSIMDVectorType(ASTContext &Context, QualType Ty) {453 return Ty->getAs<VectorType>() && Context.getTypeSize(Ty) == 128;454}455 456bool CodeGen::isRecordWithSIMDVectorType(ASTContext &Context, QualType Ty) {457 const auto *RD = Ty->getAsRecordDecl();458 if (!RD)459 return false;460 461 // If this is a C++ record, check the bases first.462 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))463 for (const auto &I : CXXRD->bases())464 if (!isRecordWithSIMDVectorType(Context, I.getType()))465 return false;466 467 for (const auto *i : RD->fields()) {468 QualType FT = i->getType();469 470 if (isSIMDVectorType(Context, FT))471 return true;472 473 if (isRecordWithSIMDVectorType(Context, FT))474 return true;475 }476 477 return false;478}479