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
21namespace clang {
22namespace targets {
23
24// AVR Target
25class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
26public:
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("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        {{"r26", "r27"}, 26},
89        {{"r28", "r29"}, 27},
90        {{"r30", "r31"}, 28},
91        {{"SPL", "SPH"}, 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(0, 63);
124      return true;
125    case 'J': // 6-bit negative integer constant
126      Info.setRequiresImmediate(-63, 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(0, 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(-6, 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
178protected:
179  std::string CPU;
180  StringRef ABI;
181  StringRef DefineName;
182  StringRef Arch;
183  int NumFlashBanks = 0;
184};
185
186} // namespace targets
187} // namespace clang
188
189#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
190