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
12using namespace clang;
13using 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
22class PNaClABIInfo : public ABIInfo {
23 public:
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 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
31 AggValueSlot Slot) const override;
32};
33
34class PNaClTargetCodeGenInfo : public TargetCodeGenInfo {
35 public:
36 PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
37 : TargetCodeGenInfo(std::make_unique<PNaClABIInfo>(args&: CGT)) {}
38};
39
40void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const {
41 if (!getCXXABI().classifyReturnType(FI))
42 FI.getReturnInfo() = classifyReturnType(RetTy: FI.getReturnType());
43
44 for (auto &I : FI.arguments())
45 I.info = classifyArgumentType(RetTy: I.type);
46}
47
48RValue PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
49 QualType Ty, AggValueSlot Slot) 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 CGF.EmitLoadOfAnyValue(
57 V: CGF.MakeAddrLValue(
58 Addr: EmitVAArgInstr(CGF, VAListAddr, Ty, AI: ABIArgInfo::getDirect()), T: Ty),
59 Slot);
60}
61
62/// Classify argument of given type \p Ty.
63ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
64 if (isAggregateTypeForABI(T: Ty)) {
65 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(T: Ty, CXXABI&: getCXXABI()))
66 return getNaturalAlignIndirect(Ty, ByVal: RAA == CGCXXABI::RAA_DirectInMemory);
67 return getNaturalAlignIndirect(Ty);
68 } else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
69 // Treat an enum type as its underlying type.
70 Ty = EnumTy->getDecl()->getIntegerType();
71 } else if (Ty->isFloatingType()) {
72 // Floating-point types don't go inreg.
73 return ABIArgInfo::getDirect();
74 } else if (const auto *EIT = Ty->getAs<BitIntType>()) {
75 // Treat bit-precise integers as integers if <= 64, otherwise pass
76 // indirectly.
77 if (EIT->getNumBits() > 64)
78 return getNaturalAlignIndirect(Ty);
79 return ABIArgInfo::getDirect();
80 }
81
82 return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
83 : ABIArgInfo::getDirect());
84}
85
86ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
87 if (RetTy->isVoidType())
88 return ABIArgInfo::getIgnore();
89
90 // In the PNaCl ABI we always return records/structures on the stack.
91 if (isAggregateTypeForABI(T: RetTy))
92 return getNaturalAlignIndirect(Ty: RetTy);
93
94 // Treat bit-precise integers as integers if <= 64, otherwise pass indirectly.
95 if (const auto *EIT = RetTy->getAs<BitIntType>()) {
96 if (EIT->getNumBits() > 64)
97 return getNaturalAlignIndirect(Ty: RetTy);
98 return ABIArgInfo::getDirect();
99 }
100
101 // Treat an enum type as its underlying type.
102 if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
103 RetTy = EnumTy->getDecl()->getIntegerType();
104
105 return (isPromotableIntegerTypeForABI(Ty: RetTy) ? ABIArgInfo::getExtend(Ty: RetTy)
106 : ABIArgInfo::getDirect());
107}
108
109std::unique_ptr<TargetCodeGenInfo>
110CodeGen::createPNaClTargetCodeGenInfo(CodeGenModule &CGM) {
111 return std::make_unique<PNaClTargetCodeGenInfo>(args&: CGM.getTypes());
112}
113