clang 22.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
13using namespace clang;
14using 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
22namespace {
23class AVRABIInfo : public DefaultABIInfo {
24private:
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
32public:
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, getDataLayout().getAllocaAddrSpace());
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 && Ty->isIntegralOrEnumerationType()) {
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
112class AVRTargetCodeGenInfo : public TargetCodeGenInfo {
113public:
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) &&
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
150std::unique_ptr<TargetCodeGenInfo>
152 unsigned NRR) {
153 return std::make_unique<AVRTargetCodeGenInfo>(CGM.getTypes(), NPR, NRR);
154}
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)
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
This class organizes the cross-function state that is used while generating LLVM code.
DiagnosticsEngine & getDiags() const
DefaultABIInfo - The default implementation for ABI specific details.
Definition ABIInfoImpl.h:21
ABIArgInfo classifyReturnType(QualType RetTy) const
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
Definition TargetInfo.h:47
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.
SourceLocation getLocation() const
Definition DeclBase.h:439
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8411
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8358
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:8996
QualType getType() const
Definition Decl.h:722
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:145
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)
unsigned toTargetAddressSpace(LangAS AS)
LangAS
Defines the address space values used by the address space qualifier of QualType.
U cast(CodeGen::Address addr)
Definition Address.h:327