106c3fb27SDimitry Andric //===- PNaCl.cpp ----------------------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric
906c3fb27SDimitry Andric #include "ABIInfoImpl.h"
1006c3fb27SDimitry Andric #include "TargetInfo.h"
1106c3fb27SDimitry Andric
1206c3fb27SDimitry Andric using namespace clang;
1306c3fb27SDimitry Andric using namespace clang::CodeGen;
1406c3fb27SDimitry Andric
1506c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1606c3fb27SDimitry Andric // le32/PNaCl bitcode ABI Implementation
1706c3fb27SDimitry Andric //
1806c3fb27SDimitry Andric // This is a simplified version of the x86_32 ABI. Arguments and return values
1906c3fb27SDimitry Andric // are always passed on the stack.
2006c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
2106c3fb27SDimitry Andric
2206c3fb27SDimitry Andric class PNaClABIInfo : public ABIInfo {
2306c3fb27SDimitry Andric public:
PNaClABIInfo(CodeGen::CodeGenTypes & CGT)2406c3fb27SDimitry Andric PNaClABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
2506c3fb27SDimitry Andric
2606c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy) const;
2706c3fb27SDimitry Andric ABIArgInfo classifyArgumentType(QualType RetTy) const;
2806c3fb27SDimitry Andric
2906c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override;
30*0fca6ea1SDimitry Andric RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
31*0fca6ea1SDimitry Andric AggValueSlot Slot) const override;
3206c3fb27SDimitry Andric };
3306c3fb27SDimitry Andric
3406c3fb27SDimitry Andric class PNaClTargetCodeGenInfo : public TargetCodeGenInfo {
3506c3fb27SDimitry Andric public:
PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes & CGT)3606c3fb27SDimitry Andric PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
3706c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<PNaClABIInfo>(CGT)) {}
3806c3fb27SDimitry Andric };
3906c3fb27SDimitry Andric
computeInfo(CGFunctionInfo & FI) const4006c3fb27SDimitry Andric void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const {
4106c3fb27SDimitry Andric if (!getCXXABI().classifyReturnType(FI))
4206c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
4306c3fb27SDimitry Andric
4406c3fb27SDimitry Andric for (auto &I : FI.arguments())
4506c3fb27SDimitry Andric I.info = classifyArgumentType(I.type);
4606c3fb27SDimitry Andric }
4706c3fb27SDimitry Andric
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const48*0fca6ea1SDimitry Andric RValue PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
49*0fca6ea1SDimitry Andric QualType Ty, AggValueSlot Slot) const {
5006c3fb27SDimitry Andric // The PNaCL ABI is a bit odd, in that varargs don't use normal
5106c3fb27SDimitry Andric // function classification. Structs get passed directly for varargs
5206c3fb27SDimitry Andric // functions, through a rewriting transform in
5306c3fb27SDimitry Andric // pnacl-llvm/lib/Transforms/NaCl/ExpandVarArgs.cpp, which allows
5406c3fb27SDimitry Andric // this target to actually support a va_arg instructions with an
5506c3fb27SDimitry Andric // aggregate type, unlike other targets.
56*0fca6ea1SDimitry Andric return CGF.EmitLoadOfAnyValue(
57*0fca6ea1SDimitry Andric CGF.MakeAddrLValue(
58*0fca6ea1SDimitry Andric EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()), Ty),
59*0fca6ea1SDimitry Andric Slot);
6006c3fb27SDimitry Andric }
6106c3fb27SDimitry Andric
6206c3fb27SDimitry Andric /// Classify argument of given type \p Ty.
classifyArgumentType(QualType Ty) const6306c3fb27SDimitry Andric ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
6406c3fb27SDimitry Andric if (isAggregateTypeForABI(Ty)) {
6506c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
6606c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
6706c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty);
6806c3fb27SDimitry Andric } else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
6906c3fb27SDimitry Andric // Treat an enum type as its underlying type.
7006c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType();
7106c3fb27SDimitry Andric } else if (Ty->isFloatingType()) {
7206c3fb27SDimitry Andric // Floating-point types don't go inreg.
7306c3fb27SDimitry Andric return ABIArgInfo::getDirect();
7406c3fb27SDimitry Andric } else if (const auto *EIT = Ty->getAs<BitIntType>()) {
7506c3fb27SDimitry Andric // Treat bit-precise integers as integers if <= 64, otherwise pass
7606c3fb27SDimitry Andric // indirectly.
7706c3fb27SDimitry Andric if (EIT->getNumBits() > 64)
7806c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty);
7906c3fb27SDimitry Andric return ABIArgInfo::getDirect();
8006c3fb27SDimitry Andric }
8106c3fb27SDimitry Andric
8206c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
8306c3fb27SDimitry Andric : ABIArgInfo::getDirect());
8406c3fb27SDimitry Andric }
8506c3fb27SDimitry Andric
classifyReturnType(QualType RetTy) const8606c3fb27SDimitry Andric ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
8706c3fb27SDimitry Andric if (RetTy->isVoidType())
8806c3fb27SDimitry Andric return ABIArgInfo::getIgnore();
8906c3fb27SDimitry Andric
9006c3fb27SDimitry Andric // In the PNaCl ABI we always return records/structures on the stack.
9106c3fb27SDimitry Andric if (isAggregateTypeForABI(RetTy))
9206c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy);
9306c3fb27SDimitry Andric
9406c3fb27SDimitry Andric // Treat bit-precise integers as integers if <= 64, otherwise pass indirectly.
9506c3fb27SDimitry Andric if (const auto *EIT = RetTy->getAs<BitIntType>()) {
9606c3fb27SDimitry Andric if (EIT->getNumBits() > 64)
9706c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy);
9806c3fb27SDimitry Andric return ABIArgInfo::getDirect();
9906c3fb27SDimitry Andric }
10006c3fb27SDimitry Andric
10106c3fb27SDimitry Andric // Treat an enum type as its underlying type.
10206c3fb27SDimitry Andric if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
10306c3fb27SDimitry Andric RetTy = EnumTy->getDecl()->getIntegerType();
10406c3fb27SDimitry Andric
10506c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
10606c3fb27SDimitry Andric : ABIArgInfo::getDirect());
10706c3fb27SDimitry Andric }
10806c3fb27SDimitry Andric
10906c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
createPNaClTargetCodeGenInfo(CodeGenModule & CGM)11006c3fb27SDimitry Andric CodeGen::createPNaClTargetCodeGenInfo(CodeGenModule &CGM) {
11106c3fb27SDimitry Andric return std::make_unique<PNaClTargetCodeGenInfo>(CGM.getTypes());
11206c3fb27SDimitry Andric }
113