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