| //===--- Sparc.h - declare sparc 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 Sparc TargetInfo objects. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H |
| #define LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_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 { |
| // Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit). |
| class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo { |
| static const TargetInfo::GCCRegAlias GCCRegAliases[]; |
| static const char *const GCCRegNames[]; |
| bool SoftFloat; |
| |
| public: |
| SparcTargetInfo(const llvm::Triple &Triple, const TargetOptions &) |
| : TargetInfo(Triple), SoftFloat(false) {} |
| |
| int getEHDataRegisterNumber(unsigned RegNo) const override { |
| if (RegNo == 0) |
| return 24; |
| if (RegNo == 1) |
| return 25; |
| return -1; |
| } |
| |
| bool handleTargetFeatures(std::vector<std::string> &Features, |
| DiagnosticsEngine &Diags) override { |
| // Check if software floating point is enabled |
| if (llvm::is_contained(Features, "+soft-float")) |
| SoftFloat = true; |
| return true; |
| } |
| void getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const override; |
| |
| bool hasFeature(StringRef Feature) const override; |
| |
| bool hasSjLjLowering() const override { return true; } |
| |
| ArrayRef<Builtin::Info> getTargetBuiltins() const override { |
| // FIXME: Implement! |
| return None; |
| } |
| BuiltinVaListKind getBuiltinVaListKind() const override { |
| return TargetInfo::VoidPtrBuiltinVaList; |
| } |
| ArrayRef<const char *> getGCCRegNames() const override; |
| ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override; |
| bool validateAsmConstraint(const char *&Name, |
| TargetInfo::ConstraintInfo &info) const override { |
| // FIXME: Implement! |
| switch (*Name) { |
| case 'I': // Signed 13-bit constant |
| case 'J': // Zero |
| case 'K': // 32-bit constant with the low 12 bits clear |
| case 'L': // A constant in the range supported by movcc (11-bit signed imm) |
| case 'M': // A constant in the range supported by movrcc (19-bit signed imm) |
| case 'N': // Same as 'K' but zext (required for SIMode) |
| case 'O': // The constant 4096 |
| return true; |
| |
| case 'f': |
| case 'e': |
| info.setAllowsRegister(); |
| return true; |
| } |
| return false; |
| } |
| const char *getClobbers() const override { |
| // FIXME: Implement! |
| return ""; |
| } |
| |
| // No Sparc V7 for now, the backend doesn't support it anyway. |
| enum CPUKind { |
| CK_GENERIC, |
| CK_V8, |
| CK_SUPERSPARC, |
| CK_SPARCLITE, |
| CK_F934, |
| CK_HYPERSPARC, |
| CK_SPARCLITE86X, |
| CK_SPARCLET, |
| CK_TSC701, |
| CK_V9, |
| CK_ULTRASPARC, |
| CK_ULTRASPARC3, |
| CK_NIAGARA, |
| CK_NIAGARA2, |
| CK_NIAGARA3, |
| CK_NIAGARA4, |
| CK_MYRIAD2100, |
| CK_MYRIAD2150, |
| CK_MYRIAD2155, |
| CK_MYRIAD2450, |
| CK_MYRIAD2455, |
| CK_MYRIAD2x5x, |
| CK_MYRIAD2080, |
| CK_MYRIAD2085, |
| CK_MYRIAD2480, |
| CK_MYRIAD2485, |
| CK_MYRIAD2x8x, |
| CK_LEON2, |
| CK_LEON2_AT697E, |
| CK_LEON2_AT697F, |
| CK_LEON3, |
| CK_LEON3_UT699, |
| CK_LEON3_GR712RC, |
| CK_LEON4, |
| CK_LEON4_GR740 |
| } CPU = CK_GENERIC; |
| |
| enum CPUGeneration { |
| CG_V8, |
| CG_V9, |
| }; |
| |
| CPUGeneration getCPUGeneration(CPUKind Kind) const; |
| |
| CPUKind getCPUKind(StringRef Name) const; |
| |
| bool isValidCPUName(StringRef Name) const override { |
| return getCPUKind(Name) != CK_GENERIC; |
| } |
| |
| void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
| |
| bool setCPU(const std::string &Name) override { |
| CPU = getCPUKind(Name); |
| return CPU != CK_GENERIC; |
| } |
| }; |
| |
| // SPARC v8 is the 32-bit mode selected by Triple::sparc. |
| class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo { |
| public: |
| SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : SparcTargetInfo(Triple, Opts) { |
| resetDataLayout("E-m:e-p:32:32-i64:64-f128:64-n32-S64"); |
| // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int. |
| switch (getTriple().getOS()) { |
| default: |
| SizeType = UnsignedInt; |
| IntPtrType = SignedInt; |
| PtrDiffType = SignedInt; |
| break; |
| case llvm::Triple::NetBSD: |
| case llvm::Triple::OpenBSD: |
| SizeType = UnsignedLong; |
| IntPtrType = SignedLong; |
| PtrDiffType = SignedLong; |
| break; |
| } |
| // Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're |
| // willing to do atomic ops on up to 64 bits. |
| MaxAtomicPromoteWidth = 64; |
| if (getCPUGeneration(CPU) == CG_V9) |
| MaxAtomicInlineWidth = 64; |
| else |
| // FIXME: This isn't correct for plain V8 which lacks CAS, |
| // only for LEON 3+ and Myriad. |
| MaxAtomicInlineWidth = 32; |
| } |
| |
| void getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const override; |
| |
| bool hasSjLjLowering() const override { return true; } |
| bool hasExtIntType() const override { return true; } |
| }; |
| |
| // SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel. |
| class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo { |
| public: |
| SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : SparcV8TargetInfo(Triple, Opts) { |
| resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64"); |
| } |
| }; |
| |
| // SPARC v9 is the 64-bit mode selected by Triple::sparcv9. |
| class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo { |
| public: |
| SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : SparcTargetInfo(Triple, Opts) { |
| // FIXME: Support Sparc quad-precision long double? |
| resetDataLayout("E-m:e-i64:64-n32:64-S128"); |
| // This is an LP64 platform. |
| LongWidth = LongAlign = PointerWidth = PointerAlign = 64; |
| |
| // OpenBSD uses long long for int64_t and intmax_t. |
| if (getTriple().isOSOpenBSD()) |
| IntMaxType = SignedLongLong; |
| else |
| IntMaxType = SignedLong; |
| Int64Type = IntMaxType; |
| |
| // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit |
| // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned. |
| LongDoubleWidth = 128; |
| LongDoubleAlign = 128; |
| SuitableAlign = 128; |
| LongDoubleFormat = &llvm::APFloat::IEEEquad(); |
| MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; |
| } |
| |
| void getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const override; |
| |
| bool isValidCPUName(StringRef Name) const override { |
| return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9; |
| } |
| |
| void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
| |
| bool setCPU(const std::string &Name) override { |
| if (!SparcTargetInfo::setCPU(Name)) |
| return false; |
| return getCPUGeneration(CPU) == CG_V9; |
| } |
| |
| bool hasExtIntType() const override { return true; } |
| }; |
| } // namespace targets |
| } // namespace clang |
| #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H |