clang  19.0.0git
AVR.cpp
Go to the documentation of this file.
1 //===- AVR.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"
12 
13 using namespace clang;
14 using namespace clang::CodeGen;
15 
16 //===----------------------------------------------------------------------===//
17 // AVR ABI Implementation. Documented at
18 // https://gcc.gnu.org/wiki/avr-gcc#Calling_Convention
19 // https://gcc.gnu.org/wiki/avr-gcc#Reduced_Tiny
20 //===----------------------------------------------------------------------===//
21 
22 namespace {
23 class AVRABIInfo : public DefaultABIInfo {
24 private:
25  // The total amount of registers can be used to pass parameters. It is 18 on
26  // AVR, or 6 on AVRTiny.
27  const unsigned ParamRegs;
28  // The total amount of registers can be used to pass return value. It is 8 on
29  // AVR, or 4 on AVRTiny.
30  const unsigned RetRegs;
31 
32 public:
33  AVRABIInfo(CodeGenTypes &CGT, unsigned NPR, unsigned NRR)
34  : DefaultABIInfo(CGT), ParamRegs(NPR), RetRegs(NRR) {}
35 
36  ABIArgInfo classifyReturnType(QualType Ty, bool &LargeRet) const {
37  // On AVR, a return struct with size less than or equals to 8 bytes is
38  // returned directly via registers R18-R25. On AVRTiny, a return struct
39  // with size less than or equals to 4 bytes is returned directly via
40  // registers R22-R25.
41  if (isAggregateTypeForABI(Ty) &&
42  getContext().getTypeSize(Ty) <= RetRegs * 8)
43  return ABIArgInfo::getDirect();
44  // A return value (struct or scalar) with larger size is returned via a
45  // stack slot, along with a pointer as the function's implicit argument.
46  if (getContext().getTypeSize(Ty) > RetRegs * 8) {
47  LargeRet = true;
48  return getNaturalAlignIndirect(Ty);
49  }
50  // An i8 return value should not be extended to i16, since AVR has 8-bit
51  // registers.
52  if (Ty->isIntegralOrEnumerationType() && getContext().getTypeSize(Ty) <= 8)
53  return ABIArgInfo::getDirect();
54  // Otherwise we follow the default way which is compatible.
56  }
57 
58  ABIArgInfo classifyArgumentType(QualType Ty, unsigned &NumRegs) const {
59  unsigned TySize = getContext().getTypeSize(Ty);
60 
61  // An int8 type argument always costs two registers like an int16.
62  if (TySize == 8 && NumRegs >= 2) {
63  NumRegs -= 2;
64  return ABIArgInfo::getExtend(Ty);
65  }
66 
67  // If the argument size is an odd number of bytes, round up the size
68  // to the next even number.
69  TySize = llvm::alignTo(TySize, 16);
70 
71  // Any type including an array/struct type can be passed in rgisters,
72  // if there are enough registers left.
73  if (TySize <= NumRegs * 8) {
74  NumRegs -= TySize / 8;
75  return ABIArgInfo::getDirect();
76  }
77 
78  // An argument is passed either completely in registers or completely in
79  // memory. Since there are not enough registers left, current argument
80  // and all other unprocessed arguments should be passed in memory.
81  // However we still need to return `ABIArgInfo::getDirect()` other than
82  // `ABIInfo::getNaturalAlignIndirect(Ty)`, otherwise an extra stack slot
83  // will be allocated, so the stack frame layout will be incompatible with
84  // avr-gcc.
85  NumRegs = 0;
86  return ABIArgInfo::getDirect();
87  }
88 
89  void computeInfo(CGFunctionInfo &FI) const override {
90  // Decide the return type.
91  bool LargeRet = false;
92  if (!getCXXABI().classifyReturnType(FI))
93  FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), LargeRet);
94 
95  // Decide each argument type. The total number of registers can be used for
96  // arguments depends on several factors:
97  // 1. Arguments of varargs functions are passed on the stack. This applies
98  // even to the named arguments. So no register can be used.
99  // 2. Total 18 registers can be used on avr and 6 ones on avrtiny.
100  // 3. If the return type is a struct with too large size, two registers
101  // (out of 18/6) will be cost as an implicit pointer argument.
102  unsigned NumRegs = ParamRegs;
103  if (FI.isVariadic())
104  NumRegs = 0;
105  else if (LargeRet)
106  NumRegs -= 2;
107  for (auto &I : FI.arguments())
108  I.info = classifyArgumentType(I.type, NumRegs);
109  }
110 };
111 
112 class AVRTargetCodeGenInfo : public TargetCodeGenInfo {
113 public:
114  AVRTargetCodeGenInfo(CodeGenTypes &CGT, unsigned NPR, unsigned NRR)
115  : TargetCodeGenInfo(std::make_unique<AVRABIInfo>(CGT, NPR, NRR)) {}
116 
117  LangAS getGlobalVarAddressSpace(CodeGenModule &CGM,
118  const VarDecl *D) const override {
119  // Check if global/static variable is defined in address space
120  // 1~6 (__flash, __flash1, __flash2, __flash3, __flash4, __flash5)
121  // but not constant.
122  if (D) {
123  LangAS AS = D->getType().getAddressSpace();
124  if (isTargetAddressSpace(AS) && 1 <= toTargetAddressSpace(AS) &&
125  toTargetAddressSpace(AS) <= 6 && !D->getType().isConstQualified())
126  CGM.getDiags().Report(D->getLocation(),
127  diag::err_verify_nonconst_addrspace)
128  << "__flash*";
129  }
131  }
132 
133  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
134  CodeGen::CodeGenModule &CGM) const override {
135  if (GV->isDeclaration())
136  return;
137  const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
138  if (!FD) return;
139  auto *Fn = cast<llvm::Function>(GV);
140 
141  if (FD->getAttr<AVRInterruptAttr>())
142  Fn->addFnAttr("interrupt");
143 
144  if (FD->getAttr<AVRSignalAttr>())
145  Fn->addFnAttr("signal");
146  }
147 };
148 }
149 
150 std::unique_ptr<TargetCodeGenInfo>
152  unsigned NRR) {
153  return std::make_unique<AVRTargetCodeGenInfo>(CGM.getTypes(), NPR, NRR);
154 }
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr)
CGFunctionInfo - Class to encapsulate the information about a function definition.
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
This class organizes the cross-function state that is used while generating LLVM code.
DiagnosticsEngine & getDiags() const
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
Definition: CodeGenTypes.h:54
DefaultABIInfo - The default implementation for ABI specific details.
Definition: ABIInfoImpl.h:21
ABIArgInfo classifyReturnType(QualType RetTy) const
Definition: ABIInfoImpl.cpp:45
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
Definition: TargetInfo.h:46
virtual LangAS getGlobalVarAddressSpace(CodeGenModule &CGM, const VarDecl *D) const
Get target favored AST address space of a global variable for languages other than OpenCL and CUDA.
Definition: TargetInfo.cpp:124
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
SourceLocation getLocation() const
Definition: DeclBase.h:445
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1553
A (possibly-)qualified type.
Definition: Type.h:940
LangAS getAddressSpace() const
Return the address space of this type.
Definition: Type.h:7497
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:7444
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:8054
QualType getType() const
Definition: Decl.h:718
Represents a variable declaration or definition.
Definition: Decl.h:919
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
bool isAggregateTypeForABI(QualType T)
std::unique_ptr< TargetCodeGenInfo > createAVRTargetCodeGenInfo(CodeGenModule &CGM, unsigned NPR, unsigned NRR)
Definition: AVR.cpp:151
The JSON file list parser is used to communicate input to InstallAPI.
bool isTargetAddressSpace(LangAS AS)
Definition: AddressSpaces.h:77
unsigned toTargetAddressSpace(LangAS AS)
Definition: AddressSpaces.h:81
LangAS
Defines the address space values used by the address space qualifier of QualType.
Definition: AddressSpaces.h:25
Definition: Format.h:5433