//===--- W65816.h - Declare W65816 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 W65816 TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_W65816_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_W65816_H

#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/Support/Compiler.h"
#include "llvm/TargetParser/Triple.h"

namespace clang {
namespace targets {

class LLVM_LIBRARY_VISIBILITY W65816TargetInfo : public TargetInfo {
  static const char *const GCCRegNames[];

public:
  W65816TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
      : TargetInfo(Triple) {
    TLSSupported = false;
    IntWidth = 16;
    IntAlign = 16;
    LongWidth = 32;
    LongLongWidth = 64;
    LongAlign = LongLongAlign = 16;
    FloatWidth = 32;
    FloatAlign = 16;
    DoubleWidth = LongDoubleWidth = 64;
    DoubleAlign = LongDoubleAlign = 16;
    PointerWidth = 32;
    PointerAlign = 16;
    SuitableAlign = 16;
    SizeType = UnsignedLong;
    IntMaxType = SignedLongLong;
    IntPtrType = SignedLong;
    PtrDiffType = SignedLong;
    SigAtomicType = SignedLong;
    // Per [basic.fundamental]: char32_t has the same size/signedness as
    // uint_least32_t — i.e. 32 bits on every conforming implementation.
    // Without this override the default `Char32Type = UnsignedInt`
    // picks up our 16-bit int, leaving char32_t too small (ETL hits
    // this in integral_limits<char32_t>::max).  Char16Type's
    // UnsignedShort default is already 16-bit (correct).  WCharType
    // stays at SignedInt (= 16) to match stddef.h's
    // `typedef int wchar_t`.
    Char32Type = UnsignedLong;
    resetDataLayout("e-m:e-p:32:16-i16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S8");
  }

  void getTargetDefines(const LangOptions &Opts,
                        MacroBuilder &Builder) const override;

  llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
    return {};
  }

  bool allowsLargerPreferedTypeAlignment() const override { return false; }

  bool hasFeature(StringRef Feature) const override {
    return Feature == "w65816";
  }

  bool hasBitIntType() const override { return true; }

  size_t getMaxBitIntWidth() const override { return 64; }

  ArrayRef<const char *> getGCCRegNames() const override;

  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
    return {};
  }

  bool validateAsmConstraint(const char *&Name,
                             TargetInfo::ConstraintInfo &info) const override {
    // Single-char constraints for the W65816's three real registers.
    // 'a' / 'x' / 'y' are direct register-class constraints; 'r'
    // means any allocatable register (we route to A by default).
    // The backend's getRegForInlineAsmConstraint resolves these to
    // physical registers.  Without listing them here, clang's frontend
    // rejects `=a` etc. before the backend ever sees them.
    switch (*Name) {
      case 'a':
      case 'x':
      case 'y':
      case 'r':
        info.setAllowsRegister();
        return true;
      default:
        return false;
    }
  }

  std::string_view getClobbers() const override { return ""; }

  BuiltinVaListKind getBuiltinVaListKind() const override {
    return TargetInfo::CharPtrBuiltinVaList;
  }
};

} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_W65816_H
