1992cb984SSergei Barannikov //===- PNaCl.cpp ----------------------------------------------------------===//
2992cb984SSergei Barannikov //
3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information.
5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6992cb984SSergei Barannikov //
7992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
8992cb984SSergei Barannikov
9992cb984SSergei Barannikov #include "ABIInfoImpl.h"
10992cb984SSergei Barannikov #include "TargetInfo.h"
11992cb984SSergei Barannikov
12992cb984SSergei Barannikov using namespace clang;
13992cb984SSergei Barannikov using namespace clang::CodeGen;
14992cb984SSergei Barannikov
15992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
16992cb984SSergei Barannikov // le32/PNaCl bitcode ABI Implementation
17992cb984SSergei Barannikov //
18992cb984SSergei Barannikov // This is a simplified version of the x86_32 ABI. Arguments and return values
19992cb984SSergei Barannikov // are always passed on the stack.
20992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
21992cb984SSergei Barannikov
22992cb984SSergei Barannikov class PNaClABIInfo : public ABIInfo {
23992cb984SSergei Barannikov public:
PNaClABIInfo(CodeGen::CodeGenTypes & CGT)24992cb984SSergei Barannikov PNaClABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
25992cb984SSergei Barannikov
26992cb984SSergei Barannikov ABIArgInfo classifyReturnType(QualType RetTy) const;
27992cb984SSergei Barannikov ABIArgInfo classifyArgumentType(QualType RetTy) const;
28992cb984SSergei Barannikov
29992cb984SSergei Barannikov void computeInfo(CGFunctionInfo &FI) const override;
30*6d973b45SMariya Podchishchaeva RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
31*6d973b45SMariya Podchishchaeva AggValueSlot Slot) const override;
32992cb984SSergei Barannikov };
33992cb984SSergei Barannikov
34992cb984SSergei Barannikov class PNaClTargetCodeGenInfo : public TargetCodeGenInfo {
35992cb984SSergei Barannikov public:
PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes & CGT)36992cb984SSergei Barannikov PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
37992cb984SSergei Barannikov : TargetCodeGenInfo(std::make_unique<PNaClABIInfo>(CGT)) {}
38992cb984SSergei Barannikov };
39992cb984SSergei Barannikov
computeInfo(CGFunctionInfo & FI) const40992cb984SSergei Barannikov void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const {
41992cb984SSergei Barannikov if (!getCXXABI().classifyReturnType(FI))
42992cb984SSergei Barannikov FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
43992cb984SSergei Barannikov
44992cb984SSergei Barannikov for (auto &I : FI.arguments())
45992cb984SSergei Barannikov I.info = classifyArgumentType(I.type);
46992cb984SSergei Barannikov }
47992cb984SSergei Barannikov
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const48*6d973b45SMariya Podchishchaeva RValue PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
49*6d973b45SMariya Podchishchaeva QualType Ty, AggValueSlot Slot) const {
50992cb984SSergei Barannikov // The PNaCL ABI is a bit odd, in that varargs don't use normal
51992cb984SSergei Barannikov // function classification. Structs get passed directly for varargs
52992cb984SSergei Barannikov // functions, through a rewriting transform in
53992cb984SSergei Barannikov // pnacl-llvm/lib/Transforms/NaCl/ExpandVarArgs.cpp, which allows
54992cb984SSergei Barannikov // this target to actually support a va_arg instructions with an
55992cb984SSergei Barannikov // aggregate type, unlike other targets.
56*6d973b45SMariya Podchishchaeva return CGF.EmitLoadOfAnyValue(
57*6d973b45SMariya Podchishchaeva CGF.MakeAddrLValue(
58*6d973b45SMariya Podchishchaeva EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()), Ty),
59*6d973b45SMariya Podchishchaeva Slot);
60992cb984SSergei Barannikov }
61992cb984SSergei Barannikov
62992cb984SSergei Barannikov /// Classify argument of given type \p Ty.
classifyArgumentType(QualType Ty) const63992cb984SSergei Barannikov ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
64992cb984SSergei Barannikov if (isAggregateTypeForABI(Ty)) {
65992cb984SSergei Barannikov if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
66992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
67992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty);
68992cb984SSergei Barannikov } else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
69992cb984SSergei Barannikov // Treat an enum type as its underlying type.
70992cb984SSergei Barannikov Ty = EnumTy->getDecl()->getIntegerType();
71992cb984SSergei Barannikov } else if (Ty->isFloatingType()) {
72992cb984SSergei Barannikov // Floating-point types don't go inreg.
73992cb984SSergei Barannikov return ABIArgInfo::getDirect();
74992cb984SSergei Barannikov } else if (const auto *EIT = Ty->getAs<BitIntType>()) {
75992cb984SSergei Barannikov // Treat bit-precise integers as integers if <= 64, otherwise pass
76992cb984SSergei Barannikov // indirectly.
77992cb984SSergei Barannikov if (EIT->getNumBits() > 64)
78992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty);
79992cb984SSergei Barannikov return ABIArgInfo::getDirect();
80992cb984SSergei Barannikov }
81992cb984SSergei Barannikov
82992cb984SSergei Barannikov return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
83992cb984SSergei Barannikov : ABIArgInfo::getDirect());
84992cb984SSergei Barannikov }
85992cb984SSergei Barannikov
classifyReturnType(QualType RetTy) const86992cb984SSergei Barannikov ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
87992cb984SSergei Barannikov if (RetTy->isVoidType())
88992cb984SSergei Barannikov return ABIArgInfo::getIgnore();
89992cb984SSergei Barannikov
90992cb984SSergei Barannikov // In the PNaCl ABI we always return records/structures on the stack.
91992cb984SSergei Barannikov if (isAggregateTypeForABI(RetTy))
92992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy);
93992cb984SSergei Barannikov
94992cb984SSergei Barannikov // Treat bit-precise integers as integers if <= 64, otherwise pass indirectly.
95992cb984SSergei Barannikov if (const auto *EIT = RetTy->getAs<BitIntType>()) {
96992cb984SSergei Barannikov if (EIT->getNumBits() > 64)
97992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy);
98992cb984SSergei Barannikov return ABIArgInfo::getDirect();
99992cb984SSergei Barannikov }
100992cb984SSergei Barannikov
101992cb984SSergei Barannikov // Treat an enum type as its underlying type.
102992cb984SSergei Barannikov if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
103992cb984SSergei Barannikov RetTy = EnumTy->getDecl()->getIntegerType();
104992cb984SSergei Barannikov
105992cb984SSergei Barannikov return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
106992cb984SSergei Barannikov : ABIArgInfo::getDirect());
107992cb984SSergei Barannikov }
108992cb984SSergei Barannikov
109992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
createPNaClTargetCodeGenInfo(CodeGenModule & CGM)110992cb984SSergei Barannikov CodeGen::createPNaClTargetCodeGenInfo(CodeGenModule &CGM) {
111992cb984SSergei Barannikov return std::make_unique<PNaClTargetCodeGenInfo>(CGM.getTypes());
112992cb984SSergei Barannikov }
113