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