1326941Sdim//===--- AVR.h - Declare AVR target feature support -------------*- C++ -*-===//
2326941Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326941Sdim//
7326941Sdim//===----------------------------------------------------------------------===//
8326941Sdim//
9326941Sdim// This file declares AVR TargetInfo objects.
10326941Sdim//
11326941Sdim//===----------------------------------------------------------------------===//
12326941Sdim
13326941Sdim#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
14326941Sdim#define LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
15326941Sdim
16326941Sdim#include "clang/Basic/TargetInfo.h"
17326941Sdim#include "clang/Basic/TargetOptions.h"
18326941Sdim#include "llvm/ADT/Triple.h"
19326941Sdim#include "llvm/Support/Compiler.h"
20326941Sdim
21326941Sdimnamespace clang {
22326941Sdimnamespace targets {
23326941Sdim
24326941Sdim// AVR Target
25326941Sdimclass LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
26326941Sdimpublic:
27326941Sdim  AVRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
28326941Sdim      : TargetInfo(Triple) {
29326941Sdim    TLSSupported = false;
30326941Sdim    PointerWidth = 16;
31326941Sdim    PointerAlign = 8;
32326941Sdim    IntWidth = 16;
33326941Sdim    IntAlign = 8;
34326941Sdim    LongWidth = 32;
35326941Sdim    LongAlign = 8;
36326941Sdim    LongLongWidth = 64;
37326941Sdim    LongLongAlign = 8;
38326941Sdim    SuitableAlign = 8;
39326941Sdim    DefaultAlignForAttributeAligned = 8;
40326941Sdim    HalfWidth = 16;
41326941Sdim    HalfAlign = 8;
42326941Sdim    FloatWidth = 32;
43326941Sdim    FloatAlign = 8;
44326941Sdim    DoubleWidth = 32;
45326941Sdim    DoubleAlign = 8;
46326941Sdim    DoubleFormat = &llvm::APFloat::IEEEsingle();
47326941Sdim    LongDoubleWidth = 32;
48326941Sdim    LongDoubleAlign = 8;
49326941Sdim    LongDoubleFormat = &llvm::APFloat::IEEEsingle();
50326941Sdim    SizeType = UnsignedInt;
51326941Sdim    PtrDiffType = SignedInt;
52326941Sdim    IntPtrType = SignedInt;
53326941Sdim    Char16Type = UnsignedInt;
54326941Sdim    WIntType = SignedInt;
55326941Sdim    Char32Type = UnsignedLong;
56326941Sdim    SigAtomicType = SignedChar;
57341825Sdim    resetDataLayout("e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8");
58326941Sdim  }
59326941Sdim
60326941Sdim  void getTargetDefines(const LangOptions &Opts,
61326941Sdim                        MacroBuilder &Builder) const override;
62326941Sdim
63326941Sdim  ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
64326941Sdim
65326941Sdim  BuiltinVaListKind getBuiltinVaListKind() const override {
66326941Sdim    return TargetInfo::VoidPtrBuiltinVaList;
67326941Sdim  }
68326941Sdim
69326941Sdim  const char *getClobbers() const override { return ""; }
70326941Sdim
71326941Sdim  ArrayRef<const char *> getGCCRegNames() const override {
72326941Sdim    static const char *const GCCRegNames[] = {
73326941Sdim        "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",  "r9",
74326941Sdim        "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
75326941Sdim        "r20", "r21", "r22", "r23", "r24", "r25", "X",   "Y",   "Z",   "SP"
76326941Sdim    };
77326941Sdim    return llvm::makeArrayRef(GCCRegNames);
78326941Sdim  }
79326941Sdim
80326941Sdim  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
81326941Sdim    return None;
82326941Sdim  }
83326941Sdim
84326941Sdim  ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override {
85326941Sdim    static const TargetInfo::AddlRegName AddlRegNames[] = {
86326941Sdim        {{"r26", "r27"}, 26},
87326941Sdim        {{"r28", "r29"}, 27},
88326941Sdim        {{"r30", "r31"}, 28},
89326941Sdim        {{"SPL", "SPH"}, 29},
90326941Sdim    };
91326941Sdim    return llvm::makeArrayRef(AddlRegNames);
92326941Sdim  }
93326941Sdim
94326941Sdim  bool validateAsmConstraint(const char *&Name,
95326941Sdim                             TargetInfo::ConstraintInfo &Info) const override {
96326941Sdim    // There aren't any multi-character AVR specific constraints.
97326941Sdim    if (StringRef(Name).size() > 1)
98326941Sdim      return false;
99326941Sdim
100326941Sdim    switch (*Name) {
101326941Sdim    default:
102326941Sdim      return false;
103326941Sdim    case 'a': // Simple upper registers
104326941Sdim    case 'b': // Base pointer registers pairs
105326941Sdim    case 'd': // Upper register
106326941Sdim    case 'l': // Lower registers
107326941Sdim    case 'e': // Pointer register pairs
108326941Sdim    case 'q': // Stack pointer register
109326941Sdim    case 'r': // Any register
110326941Sdim    case 'w': // Special upper register pairs
111326941Sdim    case 't': // Temporary register
112326941Sdim    case 'x':
113326941Sdim    case 'X': // Pointer register pair X
114326941Sdim    case 'y':
115326941Sdim    case 'Y': // Pointer register pair Y
116326941Sdim    case 'z':
117326941Sdim    case 'Z': // Pointer register pair Z
118326941Sdim      Info.setAllowsRegister();
119326941Sdim      return true;
120326941Sdim    case 'I': // 6-bit positive integer constant
121326941Sdim      Info.setRequiresImmediate(0, 63);
122326941Sdim      return true;
123326941Sdim    case 'J': // 6-bit negative integer constant
124326941Sdim      Info.setRequiresImmediate(-63, 0);
125326941Sdim      return true;
126326941Sdim    case 'K': // Integer constant (Range: 2)
127326941Sdim      Info.setRequiresImmediate(2);
128326941Sdim      return true;
129326941Sdim    case 'L': // Integer constant (Range: 0)
130326941Sdim      Info.setRequiresImmediate(0);
131326941Sdim      return true;
132326941Sdim    case 'M': // 8-bit integer constant
133326941Sdim      Info.setRequiresImmediate(0, 0xff);
134326941Sdim      return true;
135326941Sdim    case 'N': // Integer constant (Range: -1)
136326941Sdim      Info.setRequiresImmediate(-1);
137326941Sdim      return true;
138326941Sdim    case 'O': // Integer constant (Range: 8, 16, 24)
139326941Sdim      Info.setRequiresImmediate({8, 16, 24});
140326941Sdim      return true;
141326941Sdim    case 'P': // Integer constant (Range: 1)
142326941Sdim      Info.setRequiresImmediate(1);
143326941Sdim      return true;
144326941Sdim    case 'R': // Integer constant (Range: -6 to 5)
145326941Sdim      Info.setRequiresImmediate(-6, 5);
146326941Sdim      return true;
147326941Sdim    case 'G': // Floating point constant
148326941Sdim    case 'Q': // A memory address based on Y or Z pointer with displacement.
149326941Sdim      return true;
150326941Sdim    }
151326941Sdim
152326941Sdim    return false;
153326941Sdim  }
154326941Sdim
155326941Sdim  IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
156326941Sdim    // AVR prefers int for 16-bit integers.
157326941Sdim    return BitWidth == 16 ? (IsSigned ? SignedInt : UnsignedInt)
158326941Sdim                          : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
159326941Sdim  }
160326941Sdim
161326941Sdim  IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
162326941Sdim    // AVR uses int for int_least16_t and int_fast16_t.
163326941Sdim    return BitWidth == 16
164326941Sdim               ? (IsSigned ? SignedInt : UnsignedInt)
165326941Sdim               : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
166326941Sdim  }
167326941Sdim
168326941Sdim  bool isValidCPUName(StringRef Name) const override;
169341825Sdim  void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
170326941Sdim  bool setCPU(const std::string &Name) override {
171326941Sdim    bool isValid = isValidCPUName(Name);
172326941Sdim    if (isValid)
173326941Sdim      CPU = Name;
174326941Sdim    return isValid;
175326941Sdim  }
176326941Sdim
177326941Sdimprotected:
178326941Sdim  std::string CPU;
179326941Sdim};
180326941Sdim
181326941Sdim} // namespace targets
182326941Sdim} // namespace clang
183326941Sdim
184326941Sdim#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
185