xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Targets/PNaCl.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===- PNaCl.cpp ----------------------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #include "ABIInfoImpl.h"
1006c3fb27SDimitry Andric #include "TargetInfo.h"
1106c3fb27SDimitry Andric 
1206c3fb27SDimitry Andric using namespace clang;
1306c3fb27SDimitry Andric using namespace clang::CodeGen;
1406c3fb27SDimitry Andric 
1506c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1606c3fb27SDimitry Andric // le32/PNaCl bitcode ABI Implementation
1706c3fb27SDimitry Andric //
1806c3fb27SDimitry Andric // This is a simplified version of the x86_32 ABI.  Arguments and return values
1906c3fb27SDimitry Andric // are always passed on the stack.
2006c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
2106c3fb27SDimitry Andric 
2206c3fb27SDimitry Andric class PNaClABIInfo : public ABIInfo {
2306c3fb27SDimitry Andric  public:
2406c3fb27SDimitry Andric   PNaClABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
2506c3fb27SDimitry Andric 
2606c3fb27SDimitry Andric   ABIArgInfo classifyReturnType(QualType RetTy) const;
2706c3fb27SDimitry Andric   ABIArgInfo classifyArgumentType(QualType RetTy) const;
2806c3fb27SDimitry Andric 
2906c3fb27SDimitry Andric   void computeInfo(CGFunctionInfo &FI) const override;
30*0fca6ea1SDimitry Andric   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
31*0fca6ea1SDimitry Andric                    AggValueSlot Slot) const override;
3206c3fb27SDimitry Andric };
3306c3fb27SDimitry Andric 
3406c3fb27SDimitry Andric class PNaClTargetCodeGenInfo : public TargetCodeGenInfo {
3506c3fb27SDimitry Andric  public:
3606c3fb27SDimitry Andric    PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
3706c3fb27SDimitry Andric        : TargetCodeGenInfo(std::make_unique<PNaClABIInfo>(CGT)) {}
3806c3fb27SDimitry Andric };
3906c3fb27SDimitry Andric 
4006c3fb27SDimitry Andric void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const {
4106c3fb27SDimitry Andric   if (!getCXXABI().classifyReturnType(FI))
4206c3fb27SDimitry Andric     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
4306c3fb27SDimitry Andric 
4406c3fb27SDimitry Andric   for (auto &I : FI.arguments())
4506c3fb27SDimitry Andric     I.info = classifyArgumentType(I.type);
4606c3fb27SDimitry Andric }
4706c3fb27SDimitry Andric 
48*0fca6ea1SDimitry Andric RValue PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
49*0fca6ea1SDimitry Andric                                QualType Ty, AggValueSlot Slot) const {
5006c3fb27SDimitry Andric   // The PNaCL ABI is a bit odd, in that varargs don't use normal
5106c3fb27SDimitry Andric   // function classification. Structs get passed directly for varargs
5206c3fb27SDimitry Andric   // functions, through a rewriting transform in
5306c3fb27SDimitry Andric   // pnacl-llvm/lib/Transforms/NaCl/ExpandVarArgs.cpp, which allows
5406c3fb27SDimitry Andric   // this target to actually support a va_arg instructions with an
5506c3fb27SDimitry Andric   // aggregate type, unlike other targets.
56*0fca6ea1SDimitry Andric   return CGF.EmitLoadOfAnyValue(
57*0fca6ea1SDimitry Andric       CGF.MakeAddrLValue(
58*0fca6ea1SDimitry Andric           EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()), Ty),
59*0fca6ea1SDimitry Andric       Slot);
6006c3fb27SDimitry Andric }
6106c3fb27SDimitry Andric 
6206c3fb27SDimitry Andric /// Classify argument of given type \p Ty.
6306c3fb27SDimitry Andric ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
6406c3fb27SDimitry Andric   if (isAggregateTypeForABI(Ty)) {
6506c3fb27SDimitry Andric     if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
6606c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
6706c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty);
6806c3fb27SDimitry Andric   } else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
6906c3fb27SDimitry Andric     // Treat an enum type as its underlying type.
7006c3fb27SDimitry Andric     Ty = EnumTy->getDecl()->getIntegerType();
7106c3fb27SDimitry Andric   } else if (Ty->isFloatingType()) {
7206c3fb27SDimitry Andric     // Floating-point types don't go inreg.
7306c3fb27SDimitry Andric     return ABIArgInfo::getDirect();
7406c3fb27SDimitry Andric   } else if (const auto *EIT = Ty->getAs<BitIntType>()) {
7506c3fb27SDimitry Andric     // Treat bit-precise integers as integers if <= 64, otherwise pass
7606c3fb27SDimitry Andric     // indirectly.
7706c3fb27SDimitry Andric     if (EIT->getNumBits() > 64)
7806c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty);
7906c3fb27SDimitry Andric     return ABIArgInfo::getDirect();
8006c3fb27SDimitry Andric   }
8106c3fb27SDimitry Andric 
8206c3fb27SDimitry Andric   return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
8306c3fb27SDimitry Andric                                             : ABIArgInfo::getDirect());
8406c3fb27SDimitry Andric }
8506c3fb27SDimitry Andric 
8606c3fb27SDimitry Andric ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
8706c3fb27SDimitry Andric   if (RetTy->isVoidType())
8806c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
8906c3fb27SDimitry Andric 
9006c3fb27SDimitry Andric   // In the PNaCl ABI we always return records/structures on the stack.
9106c3fb27SDimitry Andric   if (isAggregateTypeForABI(RetTy))
9206c3fb27SDimitry Andric     return getNaturalAlignIndirect(RetTy);
9306c3fb27SDimitry Andric 
9406c3fb27SDimitry Andric   // Treat bit-precise integers as integers if <= 64, otherwise pass indirectly.
9506c3fb27SDimitry Andric   if (const auto *EIT = RetTy->getAs<BitIntType>()) {
9606c3fb27SDimitry Andric     if (EIT->getNumBits() > 64)
9706c3fb27SDimitry Andric       return getNaturalAlignIndirect(RetTy);
9806c3fb27SDimitry Andric     return ABIArgInfo::getDirect();
9906c3fb27SDimitry Andric   }
10006c3fb27SDimitry Andric 
10106c3fb27SDimitry Andric   // Treat an enum type as its underlying type.
10206c3fb27SDimitry Andric   if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
10306c3fb27SDimitry Andric     RetTy = EnumTy->getDecl()->getIntegerType();
10406c3fb27SDimitry Andric 
10506c3fb27SDimitry Andric   return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
10606c3fb27SDimitry Andric                                                : ABIArgInfo::getDirect());
10706c3fb27SDimitry Andric }
10806c3fb27SDimitry Andric 
10906c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
11006c3fb27SDimitry Andric CodeGen::createPNaClTargetCodeGenInfo(CodeGenModule &CGM) {
11106c3fb27SDimitry Andric   return std::make_unique<PNaClTargetCodeGenInfo>(CGM.getTypes());
11206c3fb27SDimitry Andric }
113