| //===--- AVR.h - Declare AVR target feature support -------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file declares AVR TargetInfo objects. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H |
| #define LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H |
| |
| #include "clang/Basic/TargetInfo.h" |
| #include "clang/Basic/TargetOptions.h" |
| #include "llvm/ADT/Triple.h" |
| #include "llvm/Support/Compiler.h" |
| |
| namespace clang { |
| namespace targets { |
| |
| // AVR Target |
| class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo { |
| public: |
| AVRTargetInfo(const llvm::Triple &Triple, const TargetOptions &) |
| : TargetInfo(Triple) { |
| TLSSupported = false; |
| PointerWidth = 16; |
| PointerAlign = 8; |
| IntWidth = 16; |
| IntAlign = 8; |
| LongWidth = 32; |
| LongAlign = 8; |
| LongLongWidth = 64; |
| LongLongAlign = 8; |
| SuitableAlign = 8; |
| DefaultAlignForAttributeAligned = 8; |
| HalfWidth = 16; |
| HalfAlign = 8; |
| FloatWidth = 32; |
| FloatAlign = 8; |
| DoubleWidth = 32; |
| DoubleAlign = 8; |
| DoubleFormat = &llvm::APFloat::IEEEsingle(); |
| LongDoubleWidth = 32; |
| LongDoubleAlign = 8; |
| LongDoubleFormat = &llvm::APFloat::IEEEsingle(); |
| SizeType = UnsignedInt; |
| PtrDiffType = SignedInt; |
| IntPtrType = SignedInt; |
| Char16Type = UnsignedInt; |
| WIntType = SignedInt; |
| Char32Type = UnsignedLong; |
| SigAtomicType = SignedChar; |
| resetDataLayout("e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"); |
| } |
| |
| void getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const override; |
| |
| ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; } |
| |
| BuiltinVaListKind getBuiltinVaListKind() const override { |
| return TargetInfo::VoidPtrBuiltinVaList; |
| } |
| |
| const char *getClobbers() const override { return ""; } |
| |
| ArrayRef<const char *> getGCCRegNames() const override { |
| static const char *const GCCRegNames[] = { |
| "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", |
| "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", |
| "r20", "r21", "r22", "r23", "r24", "r25", "X", "Y", "Z", "SP" |
| }; |
| return llvm::makeArrayRef(GCCRegNames); |
| } |
| |
| ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { |
| return None; |
| } |
| |
| ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override { |
| static const TargetInfo::AddlRegName AddlRegNames[] = { |
| {{"r26", "r27"}, 26}, |
| {{"r28", "r29"}, 27}, |
| {{"r30", "r31"}, 28}, |
| {{"SPL", "SPH"}, 29}, |
| }; |
| return llvm::makeArrayRef(AddlRegNames); |
| } |
| |
| bool validateAsmConstraint(const char *&Name, |
| TargetInfo::ConstraintInfo &Info) const override { |
| // There aren't any multi-character AVR specific constraints. |
| if (StringRef(Name).size() > 1) |
| return false; |
| |
| switch (*Name) { |
| default: |
| return false; |
| case 'a': // Simple upper registers |
| case 'b': // Base pointer registers pairs |
| case 'd': // Upper register |
| case 'l': // Lower registers |
| case 'e': // Pointer register pairs |
| case 'q': // Stack pointer register |
| case 'r': // Any register |
| case 'w': // Special upper register pairs |
| case 't': // Temporary register |
| case 'x': |
| case 'X': // Pointer register pair X |
| case 'y': |
| case 'Y': // Pointer register pair Y |
| case 'z': |
| case 'Z': // Pointer register pair Z |
| Info.setAllowsRegister(); |
| return true; |
| case 'I': // 6-bit positive integer constant |
| Info.setRequiresImmediate(0, 63); |
| return true; |
| case 'J': // 6-bit negative integer constant |
| Info.setRequiresImmediate(-63, 0); |
| return true; |
| case 'K': // Integer constant (Range: 2) |
| Info.setRequiresImmediate(2); |
| return true; |
| case 'L': // Integer constant (Range: 0) |
| Info.setRequiresImmediate(0); |
| return true; |
| case 'M': // 8-bit integer constant |
| Info.setRequiresImmediate(0, 0xff); |
| return true; |
| case 'N': // Integer constant (Range: -1) |
| Info.setRequiresImmediate(-1); |
| return true; |
| case 'O': // Integer constant (Range: 8, 16, 24) |
| Info.setRequiresImmediate({8, 16, 24}); |
| return true; |
| case 'P': // Integer constant (Range: 1) |
| Info.setRequiresImmediate(1); |
| return true; |
| case 'R': // Integer constant (Range: -6 to 5) |
| Info.setRequiresImmediate(-6, 5); |
| return true; |
| case 'G': // Floating point constant |
| case 'Q': // A memory address based on Y or Z pointer with displacement. |
| return true; |
| } |
| |
| return false; |
| } |
| |
| IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final { |
| // AVR prefers int for 16-bit integers. |
| return BitWidth == 16 ? (IsSigned ? SignedInt : UnsignedInt) |
| : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned); |
| } |
| |
| IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final { |
| // AVR uses int for int_least16_t and int_fast16_t. |
| return BitWidth == 16 |
| ? (IsSigned ? SignedInt : UnsignedInt) |
| : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned); |
| } |
| |
| bool isValidCPUName(StringRef Name) const override; |
| void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
| bool setCPU(const std::string &Name) override { |
| bool isValid = isValidCPUName(Name); |
| if (isValid) |
| CPU = Name; |
| return isValid; |
| } |
| |
| protected: |
| std::string CPU; |
| }; |
| |
| } // namespace targets |
| } // namespace clang |
| |
| #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H |