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  Address EmitVAArg(CodeGenFunction &CGF,
31                    Address VAListAddr, QualType Ty) const override;
32};
33
34class PNaClTargetCodeGenInfo : public TargetCodeGenInfo {
35 public:
36   PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
37       : TargetCodeGenInfo(std::make_unique<PNaClABIInfo>(CGT)) {}
38};
39
40void 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
48Address 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.
60ABIArgInfo 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
83ABIArgInfo 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
106std::unique_ptr<TargetCodeGenInfo>
107CodeGen::createPNaClTargetCodeGenInfo(CodeGenModule &CGM) {
108  return std::make_unique<PNaClTargetCodeGenInfo>(CGM.getTypes());
109}
110