1 | //===--- AVR.h - Declare AVR target feature support -------------*- C++ -*-===// |
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 | // This file declares AVR TargetInfo objects. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H |
14 | #define LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H |
15 | |
16 | #include "clang/Basic/TargetInfo.h" |
17 | #include "clang/Basic/TargetOptions.h" |
18 | #include "llvm/Support/Compiler.h" |
19 | #include "llvm/TargetParser/Triple.h" |
20 | |
21 | namespace clang { |
22 | namespace targets { |
23 | |
24 | // AVR Target |
25 | class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo { |
26 | public: |
27 | AVRTargetInfo(const llvm::Triple &Triple, const TargetOptions &) |
28 | : TargetInfo(Triple) { |
29 | TLSSupported = false; |
30 | PointerWidth = 16; |
31 | PointerAlign = 8; |
32 | ShortWidth = 16; |
33 | ShortAlign = 8; |
34 | IntWidth = 16; |
35 | IntAlign = 8; |
36 | LongWidth = 32; |
37 | LongAlign = 8; |
38 | LongLongWidth = 64; |
39 | LongLongAlign = 8; |
40 | SuitableAlign = 8; |
41 | DefaultAlignForAttributeAligned = 8; |
42 | HalfWidth = 16; |
43 | HalfAlign = 8; |
44 | FloatWidth = 32; |
45 | FloatAlign = 8; |
46 | DoubleWidth = 32; |
47 | DoubleAlign = 8; |
48 | DoubleFormat = &llvm::APFloat::IEEEsingle(); |
49 | LongDoubleWidth = 32; |
50 | LongDoubleAlign = 8; |
51 | LongDoubleFormat = &llvm::APFloat::IEEEsingle(); |
52 | SizeType = UnsignedInt; |
53 | PtrDiffType = SignedInt; |
54 | IntPtrType = SignedInt; |
55 | Char16Type = UnsignedInt; |
56 | WIntType = SignedInt; |
57 | Int16Type = SignedInt; |
58 | Char32Type = UnsignedLong; |
59 | SigAtomicType = SignedChar; |
60 | resetDataLayout(DL: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8" ); |
61 | } |
62 | |
63 | void getTargetDefines(const LangOptions &Opts, |
64 | MacroBuilder &Builder) const override; |
65 | |
66 | llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override { |
67 | return {}; |
68 | } |
69 | |
70 | bool allowsLargerPreferedTypeAlignment() const override { return false; } |
71 | |
72 | BuiltinVaListKind getBuiltinVaListKind() const override { |
73 | return TargetInfo::VoidPtrBuiltinVaList; |
74 | } |
75 | |
76 | std::string_view getClobbers() const override { return "" ; } |
77 | |
78 | ArrayRef<const char *> getGCCRegNames() const override { |
79 | static const char *const GCCRegNames[] = { |
80 | "r0" , "r1" , "r2" , "r3" , "r4" , "r5" , "r6" , "r7" , "r8" , "r9" , |
81 | "r10" , "r11" , "r12" , "r13" , "r14" , "r15" , "r16" , "r17" , "r18" , "r19" , |
82 | "r20" , "r21" , "r22" , "r23" , "r24" , "r25" , "X" , "Y" , "Z" , "SP" }; |
83 | return llvm::ArrayRef(GCCRegNames); |
84 | } |
85 | |
86 | ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { |
87 | return {}; |
88 | } |
89 | |
90 | ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override { |
91 | static const TargetInfo::AddlRegName AddlRegNames[] = { |
92 | {.Names: {"r26" , "r27" }, .RegNum: 26}, |
93 | {.Names: {"r28" , "r29" }, .RegNum: 27}, |
94 | {.Names: {"r30" , "r31" }, .RegNum: 28}, |
95 | {.Names: {"SPL" , "SPH" }, .RegNum: 29}, |
96 | }; |
97 | return llvm::ArrayRef(AddlRegNames); |
98 | } |
99 | |
100 | bool validateAsmConstraint(const char *&Name, |
101 | TargetInfo::ConstraintInfo &Info) const override { |
102 | // There aren't any multi-character AVR specific constraints. |
103 | if (StringRef(Name).size() > 1) |
104 | return false; |
105 | |
106 | switch (*Name) { |
107 | default: |
108 | return false; |
109 | case 'a': // Simple upper registers |
110 | case 'b': // Base pointer registers pairs |
111 | case 'd': // Upper register |
112 | case 'l': // Lower registers |
113 | case 'e': // Pointer register pairs |
114 | case 'q': // Stack pointer register |
115 | case 'r': // Any register |
116 | case 'w': // Special upper register pairs |
117 | case 't': // Temporary register |
118 | case 'x': |
119 | case 'X': // Pointer register pair X |
120 | case 'y': |
121 | case 'Y': // Pointer register pair Y |
122 | case 'z': |
123 | case 'Z': // Pointer register pair Z |
124 | Info.setAllowsRegister(); |
125 | return true; |
126 | case 'I': // 6-bit positive integer constant |
127 | // Due to issue https://github.com/llvm/llvm-project/issues/51513, we |
128 | // allow value 64 in the frontend and let it be denied in the backend. |
129 | Info.setRequiresImmediate(Min: 0, Max: 64); |
130 | return true; |
131 | case 'J': // 6-bit negative integer constant |
132 | Info.setRequiresImmediate(Min: -63, Max: 0); |
133 | return true; |
134 | case 'K': // Integer constant (Range: 2) |
135 | Info.setRequiresImmediate(2); |
136 | return true; |
137 | case 'L': // Integer constant (Range: 0) |
138 | Info.setRequiresImmediate(0); |
139 | return true; |
140 | case 'M': // 8-bit integer constant |
141 | Info.setRequiresImmediate(Min: 0, Max: 0xff); |
142 | return true; |
143 | case 'N': // Integer constant (Range: -1) |
144 | Info.setRequiresImmediate(-1); |
145 | return true; |
146 | case 'O': // Integer constant (Range: 8, 16, 24) |
147 | Info.setRequiresImmediate({8, 16, 24}); |
148 | return true; |
149 | case 'P': // Integer constant (Range: 1) |
150 | Info.setRequiresImmediate(1); |
151 | return true; |
152 | case 'R': // Integer constant (Range: -6 to 5) |
153 | Info.setRequiresImmediate(Min: -6, Max: 5); |
154 | return true; |
155 | case 'G': // Floating point constant 0.0 |
156 | Info.setRequiresImmediate(0); |
157 | return true; |
158 | case 'Q': // A memory address based on Y or Z pointer with displacement. |
159 | return true; |
160 | } |
161 | |
162 | return false; |
163 | } |
164 | |
165 | IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final { |
166 | // AVR prefers int for 16-bit integers. |
167 | return BitWidth == 16 ? (IsSigned ? SignedInt : UnsignedInt) |
168 | : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned); |
169 | } |
170 | |
171 | IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final { |
172 | // AVR uses int for int_least16_t and int_fast16_t. |
173 | return BitWidth == 16 |
174 | ? (IsSigned ? SignedInt : UnsignedInt) |
175 | : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned); |
176 | } |
177 | |
178 | bool isValidCPUName(StringRef Name) const override; |
179 | void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
180 | bool setCPU(const std::string &Name) override; |
181 | std::optional<std::string> handleAsmEscapedChar(char EscChar) const override; |
182 | StringRef getABI() const override { return ABI; } |
183 | |
184 | std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { |
185 | return std::make_pair(x: 32, y: 32); |
186 | } |
187 | |
188 | protected: |
189 | std::string CPU; |
190 | StringRef ABI; |
191 | StringRef DefineName; |
192 | StringRef Arch; |
193 | int NumFlashBanks = 0; |
194 | }; |
195 | |
196 | } // namespace targets |
197 | } // namespace clang |
198 | |
199 | #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H |
200 | |