xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/Targets/PNaCl.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
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:
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 
34 class PNaClTargetCodeGenInfo : public TargetCodeGenInfo {
35  public:
36    PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
37        : TargetCodeGenInfo(std::make_unique<PNaClABIInfo>(CGT)) {}
38 };
39 
40 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 
48 RValue 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       CGF.MakeAddrLValue(
58           EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()), Ty),
59       Slot);
60 }
61 
62 /// Classify argument of given type \p Ty.
63 ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
64   if (isAggregateTypeForABI(Ty)) {
65     if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
66       return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
67                                      RAA == CGCXXABI::RAA_DirectInMemory);
68     return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
69   } else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
70     // Treat an enum type as its underlying type.
71     Ty = EnumTy->getDecl()->getIntegerType();
72   } else if (Ty->isFloatingType()) {
73     // Floating-point types don't go inreg.
74     return ABIArgInfo::getDirect();
75   } else if (const auto *EIT = Ty->getAs<BitIntType>()) {
76     // Treat bit-precise integers as integers if <= 64, otherwise pass
77     // indirectly.
78     if (EIT->getNumBits() > 64)
79       return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
80     return ABIArgInfo::getDirect();
81   }
82 
83   return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
84                                             : ABIArgInfo::getDirect());
85 }
86 
87 ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
88   if (RetTy->isVoidType())
89     return ABIArgInfo::getIgnore();
90 
91   // In the PNaCl ABI we always return records/structures on the stack.
92   if (isAggregateTypeForABI(RetTy))
93     return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());
94 
95   // Treat bit-precise integers as integers if <= 64, otherwise pass indirectly.
96   if (const auto *EIT = RetTy->getAs<BitIntType>()) {
97     if (EIT->getNumBits() > 64)
98       return getNaturalAlignIndirect(RetTy,
99                                      getDataLayout().getAllocaAddrSpace());
100     return ABIArgInfo::getDirect();
101   }
102 
103   // Treat an enum type as its underlying type.
104   if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
105     RetTy = EnumTy->getDecl()->getIntegerType();
106 
107   return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
108                                                : ABIArgInfo::getDirect());
109 }
110 
111 std::unique_ptr<TargetCodeGenInfo>
112 CodeGen::createPNaClTargetCodeGenInfo(CodeGenModule &CGM) {
113   return std::make_unique<PNaClTargetCodeGenInfo>(CGM.getTypes());
114 }
115