1 //===- PNaCl.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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "ABIInfoImpl.h"
10 #include "TargetInfo.h"
11
12 using namespace clang;
13 using namespace clang::CodeGen;
14
15 //===----------------------------------------------------------------------===//
16 // le32/PNaCl bitcode ABI Implementation
17 //
18 // This is a simplified version of the x86_32 ABI. Arguments and return values
19 // are always passed on the stack.
20 //===----------------------------------------------------------------------===//
21
22 class PNaClABIInfo : public ABIInfo {
23 public:
PNaClABIInfo(CodeGen::CodeGenTypes & CGT)24 PNaClABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
25
26 ABIArgInfo classifyReturnType(QualType RetTy) const;
27 ABIArgInfo classifyArgumentType(QualType RetTy) const;
28
29 void computeInfo(CGFunctionInfo &FI) const override;
30 Address EmitVAArg(CodeGenFunction &CGF,
31 Address VAListAddr, QualType Ty) const override;
32 };
33
34 class PNaClTargetCodeGenInfo : public TargetCodeGenInfo {
35 public:
PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes & CGT)36 PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
37 : TargetCodeGenInfo(std::make_unique<PNaClABIInfo>(CGT)) {}
38 };
39
computeInfo(CGFunctionInfo & FI) const40 void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const {
41 if (!getCXXABI().classifyReturnType(FI))
42 FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
43
44 for (auto &I : FI.arguments())
45 I.info = classifyArgumentType(I.type);
46 }
47
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty) const48 Address PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
49 QualType Ty) const {
50 // The PNaCL ABI is a bit odd, in that varargs don't use normal
51 // function classification. Structs get passed directly for varargs
52 // functions, through a rewriting transform in
53 // pnacl-llvm/lib/Transforms/NaCl/ExpandVarArgs.cpp, which allows
54 // this target to actually support a va_arg instructions with an
55 // aggregate type, unlike other targets.
56 return EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect());
57 }
58
59 /// Classify argument of given type \p Ty.
classifyArgumentType(QualType Ty) const60 ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
61 if (isAggregateTypeForABI(Ty)) {
62 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
63 return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
64 return getNaturalAlignIndirect(Ty);
65 } else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
66 // Treat an enum type as its underlying type.
67 Ty = EnumTy->getDecl()->getIntegerType();
68 } else if (Ty->isFloatingType()) {
69 // Floating-point types don't go inreg.
70 return ABIArgInfo::getDirect();
71 } else if (const auto *EIT = Ty->getAs<BitIntType>()) {
72 // Treat bit-precise integers as integers if <= 64, otherwise pass
73 // indirectly.
74 if (EIT->getNumBits() > 64)
75 return getNaturalAlignIndirect(Ty);
76 return ABIArgInfo::getDirect();
77 }
78
79 return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
80 : ABIArgInfo::getDirect());
81 }
82
classifyReturnType(QualType RetTy) const83 ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
84 if (RetTy->isVoidType())
85 return ABIArgInfo::getIgnore();
86
87 // In the PNaCl ABI we always return records/structures on the stack.
88 if (isAggregateTypeForABI(RetTy))
89 return getNaturalAlignIndirect(RetTy);
90
91 // Treat bit-precise integers as integers if <= 64, otherwise pass indirectly.
92 if (const auto *EIT = RetTy->getAs<BitIntType>()) {
93 if (EIT->getNumBits() > 64)
94 return getNaturalAlignIndirect(RetTy);
95 return ABIArgInfo::getDirect();
96 }
97
98 // Treat an enum type as its underlying type.
99 if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
100 RetTy = EnumTy->getDecl()->getIntegerType();
101
102 return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
103 : ABIArgInfo::getDirect());
104 }
105
106 std::unique_ptr<TargetCodeGenInfo>
createPNaClTargetCodeGenInfo(CodeGenModule & CGM)107 CodeGen::createPNaClTargetCodeGenInfo(CodeGenModule &CGM) {
108 return std::make_unique<PNaClTargetCodeGenInfo>(CGM.getTypes());
109 }
110