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"
11#include "clang/Basic/DiagnosticFrontend.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(T: Ty) &&
42 getContext().getTypeSize(T: 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(T: 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(T: Ty) <= 8)
53 return ABIArgInfo::getDirect();
54 // Otherwise we follow the default way which is compatible.
55 return DefaultABIInfo::classifyReturnType(RetTy: Ty);
56 }
57
58 ABIArgInfo classifyArgumentType(QualType Ty, unsigned &NumRegs) const {
59 unsigned TySize = getContext().getTypeSize(T: 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(Value: TySize, Align: 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(Ty: 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(Ty: 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>(args&: CGT, args&: NPR, args&: 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(Loc: D->getLocation(),
127 DiagID: diag::err_verify_nonconst_addrspace)
128 << "__flash*";
129 }
130 return TargetCodeGenInfo::getGlobalVarAddressSpace(CGM, D);
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>(Val: D);
138 if (!FD) return;
139 auto *Fn = cast<llvm::Function>(Val: GV);
140
141 if (FD->getAttr<AVRInterruptAttr>())
142 Fn->addFnAttr(Kind: "interrupt");
143
144 if (FD->getAttr<AVRSignalAttr>())
145 Fn->addFnAttr(Kind: "signal");
146 }
147};
148}
149
150std::unique_ptr<TargetCodeGenInfo>
151CodeGen::createAVRTargetCodeGenInfo(CodeGenModule &CGM, unsigned NPR,
152 unsigned NRR) {
153 return std::make_unique<AVRTargetCodeGenInfo>(args&: CGM.getTypes(), args&: NPR, args&: NRR);
154}
155