mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-17 00:16:06 +00:00

This commit breaks up CodeGen/TargetInfo.cpp into a set of *.cpp files, one file per target. There are no functional changes, mostly just code moving. Non-code-moving changes are: * A virtual destructor has been added to DefaultABIInfo to pin the vtable to a cpp file. * A few methods of ABIInfo and DefaultABIInfo were split into declaration + definition in order to reduce the number of transitive includes. * Several functions that used to be static have been placed in clang::CodeGen namespace so that they can be accessed from other cpp files. RFC: https://discourse.llvm.org/t/rfc-splitting-clangs-targetinfo-cpp/69883 Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D148094
159 lines
5.3 KiB
C++
159 lines
5.3 KiB
C++
//===- ARC.cpp ------------------------------------------------------------===//
|
|
//
|
|
// 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 "ABIInfoImpl.h"
|
|
#include "TargetInfo.h"
|
|
|
|
using namespace clang;
|
|
using namespace clang::CodeGen;
|
|
|
|
// ARC ABI implementation.
|
|
namespace {
|
|
|
|
class ARCABIInfo : public DefaultABIInfo {
|
|
struct CCState {
|
|
unsigned FreeRegs;
|
|
};
|
|
|
|
public:
|
|
using DefaultABIInfo::DefaultABIInfo;
|
|
|
|
private:
|
|
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
|
|
QualType Ty) const override;
|
|
|
|
void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const {
|
|
if (!State.FreeRegs)
|
|
return;
|
|
if (Info.isIndirect() && Info.getInReg())
|
|
State.FreeRegs--;
|
|
else if (Info.isDirect() && Info.getInReg()) {
|
|
unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32;
|
|
if (sz < State.FreeRegs)
|
|
State.FreeRegs -= sz;
|
|
else
|
|
State.FreeRegs = 0;
|
|
}
|
|
}
|
|
|
|
void computeInfo(CGFunctionInfo &FI) const override {
|
|
CCState State;
|
|
// ARC uses 8 registers to pass arguments.
|
|
State.FreeRegs = 8;
|
|
|
|
if (!getCXXABI().classifyReturnType(FI))
|
|
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
|
|
updateState(FI.getReturnInfo(), FI.getReturnType(), State);
|
|
for (auto &I : FI.arguments()) {
|
|
I.info = classifyArgumentType(I.type, State.FreeRegs);
|
|
updateState(I.info, I.type, State);
|
|
}
|
|
}
|
|
|
|
ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const;
|
|
ABIArgInfo getIndirectByValue(QualType Ty) const;
|
|
ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const;
|
|
ABIArgInfo classifyReturnType(QualType RetTy) const;
|
|
};
|
|
|
|
class ARCTargetCodeGenInfo : public TargetCodeGenInfo {
|
|
public:
|
|
ARCTargetCodeGenInfo(CodeGenTypes &CGT)
|
|
: TargetCodeGenInfo(std::make_unique<ARCABIInfo>(CGT)) {}
|
|
};
|
|
|
|
|
|
ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {
|
|
return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) :
|
|
getNaturalAlignIndirect(Ty, false);
|
|
}
|
|
|
|
ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {
|
|
// Compute the byval alignment.
|
|
const unsigned MinABIStackAlignInBytes = 4;
|
|
unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
|
|
return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
|
|
TypeAlign > MinABIStackAlignInBytes);
|
|
}
|
|
|
|
Address ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
|
|
QualType Ty) const {
|
|
return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
|
|
getContext().getTypeInfoInChars(Ty),
|
|
CharUnits::fromQuantity(4), true);
|
|
}
|
|
|
|
ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
|
|
uint8_t FreeRegs) const {
|
|
// Handle the generic C++ ABI.
|
|
const RecordType *RT = Ty->getAs<RecordType>();
|
|
if (RT) {
|
|
CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
|
|
if (RAA == CGCXXABI::RAA_Indirect)
|
|
return getIndirectByRef(Ty, FreeRegs > 0);
|
|
|
|
if (RAA == CGCXXABI::RAA_DirectInMemory)
|
|
return getIndirectByValue(Ty);
|
|
}
|
|
|
|
// Treat an enum type as its underlying type.
|
|
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
|
|
Ty = EnumTy->getDecl()->getIntegerType();
|
|
|
|
auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
|
|
|
|
if (isAggregateTypeForABI(Ty)) {
|
|
// Structures with flexible arrays are always indirect.
|
|
if (RT && RT->getDecl()->hasFlexibleArrayMember())
|
|
return getIndirectByValue(Ty);
|
|
|
|
// Ignore empty structs/unions.
|
|
if (isEmptyRecord(getContext(), Ty, true))
|
|
return ABIArgInfo::getIgnore();
|
|
|
|
llvm::LLVMContext &LLVMContext = getVMContext();
|
|
|
|
llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
|
|
SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
|
|
llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
|
|
|
|
return FreeRegs >= SizeInRegs ?
|
|
ABIArgInfo::getDirectInReg(Result) :
|
|
ABIArgInfo::getDirect(Result, 0, nullptr, false);
|
|
}
|
|
|
|
if (const auto *EIT = Ty->getAs<BitIntType>())
|
|
if (EIT->getNumBits() > 64)
|
|
return getIndirectByValue(Ty);
|
|
|
|
return isPromotableIntegerTypeForABI(Ty)
|
|
? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty)
|
|
: ABIArgInfo::getExtend(Ty))
|
|
: (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg()
|
|
: ABIArgInfo::getDirect());
|
|
}
|
|
|
|
ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {
|
|
if (RetTy->isAnyComplexType())
|
|
return ABIArgInfo::getDirectInReg();
|
|
|
|
// Arguments of size > 4 registers are indirect.
|
|
auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
|
|
if (RetSize > 4)
|
|
return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);
|
|
|
|
return DefaultABIInfo::classifyReturnType(RetTy);
|
|
}
|
|
|
|
} // End anonymous namespace.
|
|
|
|
std::unique_ptr<TargetCodeGenInfo>
|
|
CodeGen::createARCTargetCodeGenInfo(CodeGenModule &CGM) {
|
|
return std::make_unique<ARCTargetCodeGenInfo>(CGM.getTypes());
|
|
}
|