Files
clang-p2996/clang/lib/Basic/Targets/M68k.cpp
Chandler Carruth ca79ff07d8 Revert "Switch builtin strings to use string tables" (#119638)
Reverts llvm/llvm-project#118734

There are currently some specific versions of MSVC that are miscompiling
this code (we think). We don't know why as all the other build bots and
at least some folks' local Windows builds work fine.

This is a candidate revert to help the relevant folks catch their
builders up and have time to debug the issue. However, the expectation
is to roll forward at some point with a workaround if at all possible.
2024-12-13 23:58:48 -08:00

258 lines
6.8 KiB
C++

//===--- M68k.cpp - Implement M68k targets feature support-------------===//
//
// 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 implements M68k TargetInfo objects.
//
//===----------------------------------------------------------------------===//
#include "M68k.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/TargetParser/TargetParser.h"
#include <cstdint>
#include <cstring>
#include <limits>
#include <optional>
namespace clang {
namespace targets {
M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), TargetOpts(Opts) {
std::string Layout;
// M68k is Big Endian
Layout += "E";
// FIXME how to wire it with the used object format?
Layout += "-m:e";
// M68k pointers are always 32 bit wide even for 16-bit CPUs
Layout += "-p:32:16:32";
// M68k integer data types
Layout += "-i8:8:8-i16:16:16-i32:16:32";
// FIXME no floats at the moment
// The registers can hold 8, 16, 32 bits
Layout += "-n8:16:32";
// 16 bit alignment for both stack and aggregate
// in order to conform to ABI used by GCC
Layout += "-a:0:16-S16";
resetDataLayout(Layout);
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
IntPtrType = SignedInt;
}
bool M68kTargetInfo::setCPU(const std::string &Name) {
StringRef N = Name;
CPU = llvm::StringSwitch<CPUKind>(N)
.Case("generic", CK_68000)
.Case("M68000", CK_68000)
.Case("M68010", CK_68010)
.Case("M68020", CK_68020)
.Case("M68030", CK_68030)
.Case("M68040", CK_68040)
.Case("M68060", CK_68060)
.Default(CK_Unknown);
return CPU != CK_Unknown;
}
void M68kTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
using llvm::Twine;
Builder.defineMacro("__m68k__");
DefineStd(Builder, "mc68000", Opts);
// For sub-architecture
switch (CPU) {
case CK_68010:
DefineStd(Builder, "mc68010", Opts);
break;
case CK_68020:
DefineStd(Builder, "mc68020", Opts);
break;
case CK_68030:
DefineStd(Builder, "mc68030", Opts);
break;
case CK_68040:
DefineStd(Builder, "mc68040", Opts);
break;
case CK_68060:
DefineStd(Builder, "mc68060", Opts);
break;
default:
break;
}
if (CPU >= CK_68020) {
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
}
// Floating point
if (TargetOpts.FeatureMap.lookup("isa-68881") ||
TargetOpts.FeatureMap.lookup("isa-68882"))
Builder.defineMacro("__HAVE_68881__");
}
ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const {
// FIXME: Implement.
return {};
}
bool M68kTargetInfo::hasFeature(StringRef Feature) const {
// FIXME elaborate moar
return Feature == "M68000";
}
const char *const M68kTargetInfo::GCCRegNames[] = {
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
"pc"};
ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const {
return llvm::ArrayRef(GCCRegNames);
}
const TargetInfo::GCCRegAlias M68kTargetInfo::GCCRegAliases[] = {
{{"bp"}, "a5"},
{{"fp"}, "a6"},
{{"usp", "ssp", "isp", "a7"}, "sp"},
};
ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const {
return llvm::ArrayRef(GCCRegAliases);
}
bool M68kTargetInfo::validateAsmConstraint(
const char *&Name, TargetInfo::ConstraintInfo &info) const {
switch (*Name) {
case 'a': // address register
case 'd': // data register
info.setAllowsRegister();
return true;
case 'I': // constant integer in the range [1,8]
info.setRequiresImmediate(1, 8);
return true;
case 'J': // constant signed 16-bit integer
info.setRequiresImmediate(std::numeric_limits<int16_t>::min(),
std::numeric_limits<int16_t>::max());
return true;
case 'K': // constant that is NOT in the range of [-0x80, 0x80)
info.setRequiresImmediate();
return true;
case 'L': // constant integer in the range [-8,-1]
info.setRequiresImmediate(-8, -1);
return true;
case 'M': // constant that is NOT in the range of [-0x100, 0x100]
info.setRequiresImmediate();
return true;
case 'N': // constant integer in the range [24,31]
info.setRequiresImmediate(24, 31);
return true;
case 'O': // constant integer 16
info.setRequiresImmediate(16);
return true;
case 'P': // constant integer in the range [8,15]
info.setRequiresImmediate(8, 15);
return true;
case 'C':
++Name;
switch (*Name) {
case '0': // constant integer 0
info.setRequiresImmediate(0);
return true;
case 'i': // constant integer
case 'j': // integer constant that doesn't fit in 16 bits
info.setRequiresImmediate();
return true;
default:
break;
}
break;
case 'Q': // address register indirect addressing
case 'U': // address register indirect w/ constant offset addressing
// TODO: Handle 'S' (basically 'm' when pc-rel is enforced) when
// '-mpcrel' flag is properly handled by the driver.
info.setAllowsMemory();
return true;
default:
break;
}
return false;
}
std::optional<std::string>
M68kTargetInfo::handleAsmEscapedChar(char EscChar) const {
char C;
switch (EscChar) {
case '.':
case '#':
C = EscChar;
break;
case '/':
C = '%';
break;
case '$':
C = 's';
break;
case '&':
C = 'd';
break;
default:
return std::nullopt;
}
return std::string(1, C);
}
std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const {
if (*Constraint == 'C')
// Two-character constraint; add "^" hint for later parsing
return std::string("^") + std::string(Constraint++, 2);
return std::string(1, *Constraint);
}
std::string_view M68kTargetInfo::getClobbers() const {
// FIXME: Is this really right?
return "";
}
TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const {
return TargetInfo::VoidPtrBuiltinVaList;
}
TargetInfo::CallingConvCheckResult
M68kTargetInfo::checkCallingConvention(CallingConv CC) const {
switch (CC) {
case CC_C:
case CC_M68kRTD:
return CCCR_OK;
default:
return TargetInfo::checkCallingConvention(CC);
}
}
} // namespace targets
} // namespace clang