9,641 changes: 39 additions & 9,602 deletions clang/lib/Basic/Targets.cpp

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions clang/lib/Basic/Targets.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===------- Targets.h - Declare target feature support -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares things required for construction of a TargetInfo object
// from a target triple. Typically individual targets will need to include from
// here in order to get these functions if required.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_H

#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringRef.h"

namespace clang {
namespace targets {

LLVM_LIBRARY_VISIBILITY
clang::TargetInfo *AllocateTarget(const llvm::Triple &Triple,
const clang::TargetOptions &Opts);

/// DefineStd - Define a macro name and standard variants. For example if
/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
/// when in GNU mode.
LLVM_LIBRARY_VISIBILITY
void DefineStd(clang::MacroBuilder &Builder, llvm::StringRef MacroName,
const clang::LangOptions &Opts);

LLVM_LIBRARY_VISIBILITY
void defineCPUMacros(clang::MacroBuilder &Builder, llvm::StringRef CPUName,
bool Tuning = true);

LLVM_LIBRARY_VISIBILITY
void addMinGWDefines(const clang::LangOptions &Opts,
clang::MacroBuilder &Builder);
} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_H
71 changes: 71 additions & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//===--- AArch64.cpp - Implement AArch64 target feature support -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements AArch64 TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "AArch64.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/ArrayRef.h"

using namespace clang;
using namespace clang::targets;

const char *const AArch64TargetInfo::GCCRegNames[] = {
// 32-bit Integer registers
"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
"w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
"w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",

// 64-bit Integer registers
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
"x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
"x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",

// 32-bit floating point regsisters
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
"s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
"s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",

// 64-bit floating point regsisters
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
"d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
"d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",

// Vector registers
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
"v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
"v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
};

ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}

const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
{{"w31"}, "wsp"}, {{"x29"}, "fp"}, {{"x30"}, "lr"}, {{"x31"}, "sp"},
// The S/D/Q and W/X registers overlap, but aren't really aliases; we
// don't want to substitute one of these for a different-sized one.
};

ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
return llvm::makeArrayRef(GCCRegAliases);
}

const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsNEON.def"

#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsAArch64.def"
};
495 changes: 495 additions & 0 deletions clang/lib/Basic/Targets/AArch64.h

Large diffs are not rendered by default.

356 changes: 356 additions & 0 deletions clang/lib/Basic/Targets/AMDGPU.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,356 @@
//===--- AMDGPU.cpp - Implement AMDGPU target feature support -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements AMDGPU TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "AMDGPU.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringSwitch.h"

using namespace clang;
using namespace clang::targets;

namespace clang {
namespace targets {

// If you edit the description strings, make sure you update
// getPointerWidthV().

static const char *const DataLayoutStringR600 =
"e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";

static const char *const DataLayoutStringSIPrivateIsZero =
"e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32"
"-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";

static const char *const DataLayoutStringSIGenericIsZero =
"e-p:64:64-p1:64:64-p2:64:64-p3:32:32-p4:32:32-p5:32:32"
"-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5";

static const LangAS::Map AMDGPUPrivIsZeroDefIsGenMap = {
4, // Default
1, // opencl_global
3, // opencl_local
2, // opencl_constant
4, // opencl_generic
1, // cuda_device
2, // cuda_constant
3 // cuda_shared
};

static const LangAS::Map AMDGPUGenIsZeroDefIsGenMap = {
0, // Default
1, // opencl_global
3, // opencl_local
2, // opencl_constant
0, // opencl_generic
1, // cuda_device
2, // cuda_constant
3 // cuda_shared
};

static const LangAS::Map AMDGPUPrivIsZeroDefIsPrivMap = {
0, // Default
1, // opencl_global
3, // opencl_local
2, // opencl_constant
4, // opencl_generic
1, // cuda_device
2, // cuda_constant
3 // cuda_shared
};

static const LangAS::Map AMDGPUGenIsZeroDefIsPrivMap = {
5, // Default
1, // opencl_global
3, // opencl_local
2, // opencl_constant
0, // opencl_generic
1, // cuda_device
2, // cuda_constant
3 // cuda_shared
};
} // namespace targets
} // namespace clang

const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
#include "clang/Basic/BuiltinsAMDGPU.def"
};

const char *const AMDGPUTargetInfo::GCCRegNames[] = {
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
"v9", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17",
"v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26",
"v27", "v28", "v29", "v30", "v31", "v32", "v33", "v34", "v35",
"v36", "v37", "v38", "v39", "v40", "v41", "v42", "v43", "v44",
"v45", "v46", "v47", "v48", "v49", "v50", "v51", "v52", "v53",
"v54", "v55", "v56", "v57", "v58", "v59", "v60", "v61", "v62",
"v63", "v64", "v65", "v66", "v67", "v68", "v69", "v70", "v71",
"v72", "v73", "v74", "v75", "v76", "v77", "v78", "v79", "v80",
"v81", "v82", "v83", "v84", "v85", "v86", "v87", "v88", "v89",
"v90", "v91", "v92", "v93", "v94", "v95", "v96", "v97", "v98",
"v99", "v100", "v101", "v102", "v103", "v104", "v105", "v106", "v107",
"v108", "v109", "v110", "v111", "v112", "v113", "v114", "v115", "v116",
"v117", "v118", "v119", "v120", "v121", "v122", "v123", "v124", "v125",
"v126", "v127", "v128", "v129", "v130", "v131", "v132", "v133", "v134",
"v135", "v136", "v137", "v138", "v139", "v140", "v141", "v142", "v143",
"v144", "v145", "v146", "v147", "v148", "v149", "v150", "v151", "v152",
"v153", "v154", "v155", "v156", "v157", "v158", "v159", "v160", "v161",
"v162", "v163", "v164", "v165", "v166", "v167", "v168", "v169", "v170",
"v171", "v172", "v173", "v174", "v175", "v176", "v177", "v178", "v179",
"v180", "v181", "v182", "v183", "v184", "v185", "v186", "v187", "v188",
"v189", "v190", "v191", "v192", "v193", "v194", "v195", "v196", "v197",
"v198", "v199", "v200", "v201", "v202", "v203", "v204", "v205", "v206",
"v207", "v208", "v209", "v210", "v211", "v212", "v213", "v214", "v215",
"v216", "v217", "v218", "v219", "v220", "v221", "v222", "v223", "v224",
"v225", "v226", "v227", "v228", "v229", "v230", "v231", "v232", "v233",
"v234", "v235", "v236", "v237", "v238", "v239", "v240", "v241", "v242",
"v243", "v244", "v245", "v246", "v247", "v248", "v249", "v250", "v251",
"v252", "v253", "v254", "v255", "s0", "s1", "s2", "s3", "s4",
"s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s13",
"s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
"s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
"s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39", "s40",
"s41", "s42", "s43", "s44", "s45", "s46", "s47", "s48", "s49",
"s50", "s51", "s52", "s53", "s54", "s55", "s56", "s57", "s58",
"s59", "s60", "s61", "s62", "s63", "s64", "s65", "s66", "s67",
"s68", "s69", "s70", "s71", "s72", "s73", "s74", "s75", "s76",
"s77", "s78", "s79", "s80", "s81", "s82", "s83", "s84", "s85",
"s86", "s87", "s88", "s89", "s90", "s91", "s92", "s93", "s94",
"s95", "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103",
"s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111", "s112",
"s113", "s114", "s115", "s116", "s117", "s118", "s119", "s120", "s121",
"s122", "s123", "s124", "s125", "s126", "s127", "exec", "vcc", "scc",
"m0", "flat_scratch", "exec_lo", "exec_hi", "vcc_lo", "vcc_hi",
"flat_scratch_lo", "flat_scratch_hi"
};

ArrayRef<const char *> AMDGPUTargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}

bool AMDGPUTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeatureVec) const {

// XXX - What does the member GPU mean if device name string passed here?
if (getTriple().getArch() == llvm::Triple::amdgcn) {
if (CPU.empty())
CPU = "tahiti";

switch (parseAMDGCNName(CPU)) {
case GK_GFX6:
case GK_GFX7:
break;

case GK_GFX9:
Features["gfx9-insts"] = true;
LLVM_FALLTHROUGH;
case GK_GFX8:
Features["s-memrealtime"] = true;
Features["16-bit-insts"] = true;
Features["dpp"] = true;
break;

case GK_NONE:
return false;
default:
llvm_unreachable("unhandled subtarget");
}
} else {
if (CPU.empty())
CPU = "r600";

switch (parseR600Name(CPU)) {
case GK_R600:
case GK_R700:
case GK_EVERGREEN:
case GK_NORTHERN_ISLANDS:
break;
case GK_R600_DOUBLE_OPS:
case GK_R700_DOUBLE_OPS:
case GK_EVERGREEN_DOUBLE_OPS:
case GK_CAYMAN:
Features["fp64"] = true;
break;
case GK_NONE:
return false;
default:
llvm_unreachable("unhandled subtarget");
}
}

return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec);
}

void AMDGPUTargetInfo::adjustTargetOptions(const CodeGenOptions &CGOpts,
TargetOptions &TargetOpts) const {
bool hasFP32Denormals = false;
bool hasFP64Denormals = false;
for (auto &I : TargetOpts.FeaturesAsWritten) {
if (I == "+fp32-denormals" || I == "-fp32-denormals")
hasFP32Denormals = true;
if (I == "+fp64-fp16-denormals" || I == "-fp64-fp16-denormals")
hasFP64Denormals = true;
}
if (!hasFP32Denormals)
TargetOpts.Features.push_back(
(Twine(hasFullSpeedFMAF32(TargetOpts.CPU) && !CGOpts.FlushDenorm
? '+'
: '-') +
Twine("fp32-denormals"))
.str());
// Always do not flush fp64 or fp16 denorms.
if (!hasFP64Denormals && hasFP64)
TargetOpts.Features.push_back("+fp64-fp16-denormals");
}

AMDGPUTargetInfo::GPUKind AMDGPUTargetInfo::parseR600Name(StringRef Name) {
return llvm::StringSwitch<GPUKind>(Name)
.Case("r600", GK_R600)
.Case("rv610", GK_R600)
.Case("rv620", GK_R600)
.Case("rv630", GK_R600)
.Case("rv635", GK_R600)
.Case("rs780", GK_R600)
.Case("rs880", GK_R600)
.Case("rv670", GK_R600_DOUBLE_OPS)
.Case("rv710", GK_R700)
.Case("rv730", GK_R700)
.Case("rv740", GK_R700_DOUBLE_OPS)
.Case("rv770", GK_R700_DOUBLE_OPS)
.Case("palm", GK_EVERGREEN)
.Case("cedar", GK_EVERGREEN)
.Case("sumo", GK_EVERGREEN)
.Case("sumo2", GK_EVERGREEN)
.Case("redwood", GK_EVERGREEN)
.Case("juniper", GK_EVERGREEN)
.Case("hemlock", GK_EVERGREEN_DOUBLE_OPS)
.Case("cypress", GK_EVERGREEN_DOUBLE_OPS)
.Case("barts", GK_NORTHERN_ISLANDS)
.Case("turks", GK_NORTHERN_ISLANDS)
.Case("caicos", GK_NORTHERN_ISLANDS)
.Case("cayman", GK_CAYMAN)
.Case("aruba", GK_CAYMAN)
.Default(GK_NONE);
}

AMDGPUTargetInfo::GPUKind AMDGPUTargetInfo::parseAMDGCNName(StringRef Name) {
return llvm::StringSwitch<GPUKind>(Name)
.Case("tahiti", GK_GFX6)
.Case("pitcairn", GK_GFX6)
.Case("verde", GK_GFX6)
.Case("oland", GK_GFX6)
.Case("hainan", GK_GFX6)
.Case("bonaire", GK_GFX7)
.Case("kabini", GK_GFX7)
.Case("kaveri", GK_GFX7)
.Case("hawaii", GK_GFX7)
.Case("mullins", GK_GFX7)
.Case("gfx700", GK_GFX7)
.Case("gfx701", GK_GFX7)
.Case("gfx702", GK_GFX7)
.Case("tonga", GK_GFX8)
.Case("iceland", GK_GFX8)
.Case("carrizo", GK_GFX8)
.Case("fiji", GK_GFX8)
.Case("stoney", GK_GFX8)
.Case("polaris10", GK_GFX8)
.Case("polaris11", GK_GFX8)
.Case("gfx800", GK_GFX8)
.Case("gfx801", GK_GFX8)
.Case("gfx802", GK_GFX8)
.Case("gfx803", GK_GFX8)
.Case("gfx804", GK_GFX8)
.Case("gfx810", GK_GFX8)
.Case("gfx900", GK_GFX9)
.Case("gfx901", GK_GFX9)
.Default(GK_NONE);
}

void AMDGPUTargetInfo::setAddressSpaceMap(bool DefaultIsPrivate) {
if (isGenericZero(getTriple())) {
AddrSpaceMap = DefaultIsPrivate ? &AMDGPUGenIsZeroDefIsPrivMap
: &AMDGPUGenIsZeroDefIsGenMap;
} else {
AddrSpaceMap = DefaultIsPrivate ? &AMDGPUPrivIsZeroDefIsPrivMap
: &AMDGPUPrivIsZeroDefIsGenMap;
}
}

AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), GPU(isAMDGCN(Triple) ? GK_GFX6 : GK_R600),
hasFP64(false), hasFMAF(false), hasLDEXPF(false),
AS(isGenericZero(Triple)) {
if (getTriple().getArch() == llvm::Triple::amdgcn) {
hasFP64 = true;
hasFMAF = true;
hasLDEXPF = true;
}
auto IsGenericZero = isGenericZero(Triple);
resetDataLayout(getTriple().getArch() == llvm::Triple::amdgcn
? (IsGenericZero ? DataLayoutStringSIGenericIsZero
: DataLayoutStringSIPrivateIsZero)
: DataLayoutStringR600);
assert(DataLayout->getAllocaAddrSpace() == AS.Private);

setAddressSpaceMap(Triple.getOS() == llvm::Triple::Mesa3D ||
Triple.getEnvironment() == llvm::Triple::OpenCL ||
Triple.getEnvironmentName() == "amdgizcl" ||
!isAMDGCN(Triple));
UseAddrSpaceMapMangling = true;

// Set pointer width and alignment for target address space 0.
PointerWidth = PointerAlign = DataLayout->getPointerSizeInBits();
if (getMaxPointerWidth() == 64) {
LongWidth = LongAlign = 64;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
IntPtrType = SignedLong;
}
}

void AMDGPUTargetInfo::adjust(LangOptions &Opts) {
TargetInfo::adjust(Opts);
setAddressSpaceMap(Opts.OpenCL || !isAMDGCN(getTriple()));
}

ArrayRef<Builtin::Info> AMDGPUTargetInfo::getTargetBuiltins() const {
return llvm::makeArrayRef(BuiltinInfo, clang::AMDGPU::LastTSBuiltin -
Builtin::FirstTSBuiltin);
}

void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
if (getTriple().getArch() == llvm::Triple::amdgcn)
Builder.defineMacro("__AMDGCN__");
else
Builder.defineMacro("__R600__");

if (hasFMAF)
Builder.defineMacro("__HAS_FMAF__");
if (hasLDEXPF)
Builder.defineMacro("__HAS_LDEXPF__");
if (hasFP64)
Builder.defineMacro("__HAS_FP64__");
}
244 changes: 244 additions & 0 deletions clang/lib/Basic/Targets/AMDGPU.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
//===--- AMDGPU.h - Declare AMDGPU target feature support -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares AMDGPU TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_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 {

class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {

static const Builtin::Info BuiltinInfo[];
static const char *const GCCRegNames[];

struct LLVM_LIBRARY_VISIBILITY AddrSpace {
unsigned Generic, Global, Local, Constant, Private;
AddrSpace(bool IsGenericZero_ = false) {
if (IsGenericZero_) {
Generic = 0;
Global = 1;
Local = 3;
Constant = 2;
Private = 5;
} else {
Generic = 4;
Global = 1;
Local = 3;
Constant = 2;
Private = 0;
}
}
};

/// \brief The GPU profiles supported by the AMDGPU target.
enum GPUKind {
GK_NONE,
GK_R600,
GK_R600_DOUBLE_OPS,
GK_R700,
GK_R700_DOUBLE_OPS,
GK_EVERGREEN,
GK_EVERGREEN_DOUBLE_OPS,
GK_NORTHERN_ISLANDS,
GK_CAYMAN,
GK_GFX6,
GK_GFX7,
GK_GFX8,
GK_GFX9
} GPU;

bool hasFP64 : 1;
bool hasFMAF : 1;
bool hasLDEXPF : 1;
const AddrSpace AS;

static bool hasFullSpeedFMAF32(StringRef GPUName) {
return parseAMDGCNName(GPUName) >= GK_GFX9;
}

static bool isAMDGCN(const llvm::Triple &TT) {
return TT.getArch() == llvm::Triple::amdgcn;
}

static bool isGenericZero(const llvm::Triple &TT) {
return TT.getEnvironmentName() == "amdgiz" ||
TT.getEnvironmentName() == "amdgizcl";
}

public:
AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);

void setAddressSpaceMap(bool DefaultIsPrivate);

void adjust(LangOptions &Opts) override;

uint64_t getPointerWidthV(unsigned AddrSpace) const override {
if (GPU <= GK_CAYMAN)
return 32;

if (AddrSpace == AS.Private || AddrSpace == AS.Local) {
return 32;
}
return 64;
}

uint64_t getPointerAlignV(unsigned AddrSpace) const override {
return getPointerWidthV(AddrSpace);
}

uint64_t getMaxPointerWidth() const override {
return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
}

const char *getClobbers() const override { return ""; }

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

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

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
default:
break;
case 'v': // vgpr
case 's': // sgpr
Info.setAllowsRegister();
return true;
}
return false;
}

bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
const std::vector<std::string> &FeatureVec) const override;

void adjustTargetOptions(const CodeGenOptions &CGOpts,
TargetOptions &TargetOpts) const override;

ArrayRef<Builtin::Info> getTargetBuiltins() const override;

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

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

static GPUKind parseR600Name(StringRef Name);

static GPUKind parseAMDGCNName(StringRef Name);

bool isValidCPUName(StringRef Name) const override {
if (getTriple().getArch() == llvm::Triple::amdgcn)
return GK_NONE != parseAMDGCNName(Name);
else
return GK_NONE != parseR600Name(Name);
}

bool setCPU(const std::string &Name) override {
if (getTriple().getArch() == llvm::Triple::amdgcn)
GPU = parseAMDGCNName(Name);
else
GPU = parseR600Name(Name);

return GPU != GK_NONE;
}

void setSupportedOpenCLOpts() override {
auto &Opts = getSupportedOpenCLOpts();
Opts.support("cl_clang_storage_class_specifiers");
Opts.support("cl_khr_icd");

if (hasFP64)
Opts.support("cl_khr_fp64");
if (GPU >= GK_EVERGREEN) {
Opts.support("cl_khr_byte_addressable_store");
Opts.support("cl_khr_global_int32_base_atomics");
Opts.support("cl_khr_global_int32_extended_atomics");
Opts.support("cl_khr_local_int32_base_atomics");
Opts.support("cl_khr_local_int32_extended_atomics");
}
if (GPU >= GK_GFX6) {
Opts.support("cl_khr_fp16");
Opts.support("cl_khr_int64_base_atomics");
Opts.support("cl_khr_int64_extended_atomics");
Opts.support("cl_khr_mipmap_image");
Opts.support("cl_khr_subgroups");
Opts.support("cl_khr_3d_image_writes");
Opts.support("cl_amd_media_ops");
Opts.support("cl_amd_media_ops2");
}
}

LangAS::ID getOpenCLImageAddrSpace() const override {
return LangAS::opencl_constant;
}

llvm::Optional<unsigned> getConstantAddressSpace() const override {
return LangAS::FirstTargetAddressSpace + AS.Constant;
}

/// \returns Target specific vtbl ptr address space.
unsigned getVtblPtrAddressSpace() const override { return AS.Constant; }

/// \returns If a target requires an address within a target specific address
/// space \p AddressSpace to be converted in order to be used, then return the
/// corresponding target specific DWARF address space.
///
/// \returns Otherwise return None and no conversion will be emitted in the
/// DWARF.
Optional<unsigned>
getDWARFAddressSpace(unsigned AddressSpace) const override {
const unsigned DWARF_Private = 1;
const unsigned DWARF_Local = 2;
if (AddressSpace == AS.Private) {
return DWARF_Private;
} else if (AddressSpace == AS.Local) {
return DWARF_Local;
} else {
return None;
}
}

CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
switch (CC) {
default:
return CCCR_Warning;
case CC_C:
case CC_OpenCLKernel:
return CCCR_OK;
}
}

// In amdgcn target the null pointer in global, constant, and generic
// address space has value 0 but in private and local address space has
// value ~0.
uint64_t getNullPointerValue(unsigned AS) const override {
return AS == LangAS::opencl_local ? ~0 : 0;
}
};

} // namespace targets
} // namespace clang

#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
467 changes: 467 additions & 0 deletions clang/lib/Basic/Targets/ARM.cpp

Large diffs are not rendered by default.

761 changes: 761 additions & 0 deletions clang/lib/Basic/Targets/ARM.h

Large diffs are not rendered by default.

320 changes: 320 additions & 0 deletions clang/lib/Basic/Targets/AVR.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
//===--- AVR.cpp - Implement AVR target feature support -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements AVR TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "AVR.h"
#include "clang/Basic/MacroBuilder.h"
#include "llvm/ADT/StringSwitch.h"

using namespace clang;
using namespace clang::targets;

namespace clang {
namespace targets {

/// Information about a specific microcontroller.
struct LLVM_LIBRARY_VISIBILITY MCUInfo {
const char *Name;
const char *DefineName;
};

// This list should be kept up-to-date with AVRDevices.td in LLVM.
static ArrayRef<MCUInfo> AVRMcus = {
{"at90s1200", "__AVR_AT90S1200__"},
{"attiny11", "__AVR_ATtiny11__"},
{"attiny12", "__AVR_ATtiny12__"},
{"attiny15", "__AVR_ATtiny15__"},
{"attiny28", "__AVR_ATtiny28__"},
{"at90s2313", "__AVR_AT90S2313__"},
{"at90s2323", "__AVR_AT90S2323__"},
{"at90s2333", "__AVR_AT90S2333__"},
{"at90s2343", "__AVR_AT90S2343__"},
{"attiny22", "__AVR_ATtiny22__"},
{"attiny26", "__AVR_ATtiny26__"},
{"at86rf401", "__AVR_AT86RF401__"},
{"at90s4414", "__AVR_AT90S4414__"},
{"at90s4433", "__AVR_AT90S4433__"},
{"at90s4434", "__AVR_AT90S4434__"},
{"at90s8515", "__AVR_AT90S8515__"},
{"at90c8534", "__AVR_AT90c8534__"},
{"at90s8535", "__AVR_AT90S8535__"},
{"ata5272", "__AVR_ATA5272__"},
{"attiny13", "__AVR_ATtiny13__"},
{"attiny13a", "__AVR_ATtiny13A__"},
{"attiny2313", "__AVR_ATtiny2313__"},
{"attiny2313a", "__AVR_ATtiny2313A__"},
{"attiny24", "__AVR_ATtiny24__"},
{"attiny24a", "__AVR_ATtiny24A__"},
{"attiny4313", "__AVR_ATtiny4313__"},
{"attiny44", "__AVR_ATtiny44__"},
{"attiny44a", "__AVR_ATtiny44A__"},
{"attiny84", "__AVR_ATtiny84__"},
{"attiny84a", "__AVR_ATtiny84A__"},
{"attiny25", "__AVR_ATtiny25__"},
{"attiny45", "__AVR_ATtiny45__"},
{"attiny85", "__AVR_ATtiny85__"},
{"attiny261", "__AVR_ATtiny261__"},
{"attiny261a", "__AVR_ATtiny261A__"},
{"attiny461", "__AVR_ATtiny461__"},
{"attiny461a", "__AVR_ATtiny461A__"},
{"attiny861", "__AVR_ATtiny861__"},
{"attiny861a", "__AVR_ATtiny861A__"},
{"attiny87", "__AVR_ATtiny87__"},
{"attiny43u", "__AVR_ATtiny43U__"},
{"attiny48", "__AVR_ATtiny48__"},
{"attiny88", "__AVR_ATtiny88__"},
{"attiny828", "__AVR_ATtiny828__"},
{"at43usb355", "__AVR_AT43USB355__"},
{"at76c711", "__AVR_AT76C711__"},
{"atmega103", "__AVR_ATmega103__"},
{"at43usb320", "__AVR_AT43USB320__"},
{"attiny167", "__AVR_ATtiny167__"},
{"at90usb82", "__AVR_AT90USB82__"},
{"at90usb162", "__AVR_AT90USB162__"},
{"ata5505", "__AVR_ATA5505__"},
{"atmega8u2", "__AVR_ATmega8U2__"},
{"atmega16u2", "__AVR_ATmega16U2__"},
{"atmega32u2", "__AVR_ATmega32U2__"},
{"attiny1634", "__AVR_ATtiny1634__"},
{"atmega8", "__AVR_ATmega8__"},
{"ata6289", "__AVR_ATA6289__"},
{"atmega8a", "__AVR_ATmega8A__"},
{"ata6285", "__AVR_ATA6285__"},
{"ata6286", "__AVR_ATA6286__"},
{"atmega48", "__AVR_ATmega48__"},
{"atmega48a", "__AVR_ATmega48A__"},
{"atmega48pa", "__AVR_ATmega48PA__"},
{"atmega48p", "__AVR_ATmega48P__"},
{"atmega88", "__AVR_ATmega88__"},
{"atmega88a", "__AVR_ATmega88A__"},
{"atmega88p", "__AVR_ATmega88P__"},
{"atmega88pa", "__AVR_ATmega88PA__"},
{"atmega8515", "__AVR_ATmega8515__"},
{"atmega8535", "__AVR_ATmega8535__"},
{"atmega8hva", "__AVR_ATmega8HVA__"},
{"at90pwm1", "__AVR_AT90PWM1__"},
{"at90pwm2", "__AVR_AT90PWM2__"},
{"at90pwm2b", "__AVR_AT90PWM2B__"},
{"at90pwm3", "__AVR_AT90PWM3__"},
{"at90pwm3b", "__AVR_AT90PWM3B__"},
{"at90pwm81", "__AVR_AT90PWM81__"},
{"ata5790", "__AVR_ATA5790__"},
{"ata5795", "__AVR_ATA5795__"},
{"atmega16", "__AVR_ATmega16__"},
{"atmega16a", "__AVR_ATmega16A__"},
{"atmega161", "__AVR_ATmega161__"},
{"atmega162", "__AVR_ATmega162__"},
{"atmega163", "__AVR_ATmega163__"},
{"atmega164a", "__AVR_ATmega164A__"},
{"atmega164p", "__AVR_ATmega164P__"},
{"atmega164pa", "__AVR_ATmega164PA__"},
{"atmega165", "__AVR_ATmega165__"},
{"atmega165a", "__AVR_ATmega165A__"},
{"atmega165p", "__AVR_ATmega165P__"},
{"atmega165pa", "__AVR_ATmega165PA__"},
{"atmega168", "__AVR_ATmega168__"},
{"atmega168a", "__AVR_ATmega168A__"},
{"atmega168p", "__AVR_ATmega168P__"},
{"atmega168pa", "__AVR_ATmega168PA__"},
{"atmega169", "__AVR_ATmega169__"},
{"atmega169a", "__AVR_ATmega169A__"},
{"atmega169p", "__AVR_ATmega169P__"},
{"atmega169pa", "__AVR_ATmega169PA__"},
{"atmega32", "__AVR_ATmega32__"},
{"atmega32a", "__AVR_ATmega32A__"},
{"atmega323", "__AVR_ATmega323__"},
{"atmega324a", "__AVR_ATmega324A__"},
{"atmega324p", "__AVR_ATmega324P__"},
{"atmega324pa", "__AVR_ATmega324PA__"},
{"atmega325", "__AVR_ATmega325__"},
{"atmega325a", "__AVR_ATmega325A__"},
{"atmega325p", "__AVR_ATmega325P__"},
{"atmega325pa", "__AVR_ATmega325PA__"},
{"atmega3250", "__AVR_ATmega3250__"},
{"atmega3250a", "__AVR_ATmega3250A__"},
{"atmega3250p", "__AVR_ATmega3250P__"},
{"atmega3250pa", "__AVR_ATmega3250PA__"},
{"atmega328", "__AVR_ATmega328__"},
{"atmega328p", "__AVR_ATmega328P__"},
{"atmega329", "__AVR_ATmega329__"},
{"atmega329a", "__AVR_ATmega329A__"},
{"atmega329p", "__AVR_ATmega329P__"},
{"atmega329pa", "__AVR_ATmega329PA__"},
{"atmega3290", "__AVR_ATmega3290__"},
{"atmega3290a", "__AVR_ATmega3290A__"},
{"atmega3290p", "__AVR_ATmega3290P__"},
{"atmega3290pa", "__AVR_ATmega3290PA__"},
{"atmega406", "__AVR_ATmega406__"},
{"atmega64", "__AVR_ATmega64__"},
{"atmega64a", "__AVR_ATmega64A__"},
{"atmega640", "__AVR_ATmega640__"},
{"atmega644", "__AVR_ATmega644__"},
{"atmega644a", "__AVR_ATmega644A__"},
{"atmega644p", "__AVR_ATmega644P__"},
{"atmega644pa", "__AVR_ATmega644PA__"},
{"atmega645", "__AVR_ATmega645__"},
{"atmega645a", "__AVR_ATmega645A__"},
{"atmega645p", "__AVR_ATmega645P__"},
{"atmega649", "__AVR_ATmega649__"},
{"atmega649a", "__AVR_ATmega649A__"},
{"atmega649p", "__AVR_ATmega649P__"},
{"atmega6450", "__AVR_ATmega6450__"},
{"atmega6450a", "__AVR_ATmega6450A__"},
{"atmega6450p", "__AVR_ATmega6450P__"},
{"atmega6490", "__AVR_ATmega6490__"},
{"atmega6490a", "__AVR_ATmega6490A__"},
{"atmega6490p", "__AVR_ATmega6490P__"},
{"atmega64rfr2", "__AVR_ATmega64RFR2__"},
{"atmega644rfr2", "__AVR_ATmega644RFR2__"},
{"atmega16hva", "__AVR_ATmega16HVA__"},
{"atmega16hva2", "__AVR_ATmega16HVA2__"},
{"atmega16hvb", "__AVR_ATmega16HVB__"},
{"atmega16hvbrevb", "__AVR_ATmega16HVBREVB__"},
{"atmega32hvb", "__AVR_ATmega32HVB__"},
{"atmega32hvbrevb", "__AVR_ATmega32HVBREVB__"},
{"atmega64hve", "__AVR_ATmega64HVE__"},
{"at90can32", "__AVR_AT90CAN32__"},
{"at90can64", "__AVR_AT90CAN64__"},
{"at90pwm161", "__AVR_AT90PWM161__"},
{"at90pwm216", "__AVR_AT90PWM216__"},
{"at90pwm316", "__AVR_AT90PWM316__"},
{"atmega32c1", "__AVR_ATmega32C1__"},
{"atmega64c1", "__AVR_ATmega64C1__"},
{"atmega16m1", "__AVR_ATmega16M1__"},
{"atmega32m1", "__AVR_ATmega32M1__"},
{"atmega64m1", "__AVR_ATmega64M1__"},
{"atmega16u4", "__AVR_ATmega16U4__"},
{"atmega32u4", "__AVR_ATmega32U4__"},
{"atmega32u6", "__AVR_ATmega32U6__"},
{"at90usb646", "__AVR_AT90USB646__"},
{"at90usb647", "__AVR_AT90USB647__"},
{"at90scr100", "__AVR_AT90SCR100__"},
{"at94k", "__AVR_AT94K__"},
{"m3000", "__AVR_AT000__"},
{"atmega128", "__AVR_ATmega128__"},
{"atmega128a", "__AVR_ATmega128A__"},
{"atmega1280", "__AVR_ATmega1280__"},
{"atmega1281", "__AVR_ATmega1281__"},
{"atmega1284", "__AVR_ATmega1284__"},
{"atmega1284p", "__AVR_ATmega1284P__"},
{"atmega128rfa1", "__AVR_ATmega128RFA1__"},
{"atmega128rfr2", "__AVR_ATmega128RFR2__"},
{"atmega1284rfr2", "__AVR_ATmega1284RFR2__"},
{"at90can128", "__AVR_AT90CAN128__"},
{"at90usb1286", "__AVR_AT90USB1286__"},
{"at90usb1287", "__AVR_AT90USB1287__"},
{"atmega2560", "__AVR_ATmega2560__"},
{"atmega2561", "__AVR_ATmega2561__"},
{"atmega256rfr2", "__AVR_ATmega256RFR2__"},
{"atmega2564rfr2", "__AVR_ATmega2564RFR2__"},
{"atxmega16a4", "__AVR_ATxmega16A4__"},
{"atxmega16a4u", "__AVR_ATxmega16a4U__"},
{"atxmega16c4", "__AVR_ATxmega16C4__"},
{"atxmega16d4", "__AVR_ATxmega16D4__"},
{"atxmega32a4", "__AVR_ATxmega32A4__"},
{"atxmega32a4u", "__AVR_ATxmega32A4U__"},
{"atxmega32c4", "__AVR_ATxmega32C4__"},
{"atxmega32d4", "__AVR_ATxmega32D4__"},
{"atxmega32e5", "__AVR_ATxmega32E5__"},
{"atxmega16e5", "__AVR_ATxmega16E5__"},
{"atxmega8e5", "__AVR_ATxmega8E5__"},
{"atxmega32x1", "__AVR_ATxmega32X1__"},
{"atxmega64a3", "__AVR_ATxmega64A3__"},
{"atxmega64a3u", "__AVR_ATxmega64A3U__"},
{"atxmega64a4u", "__AVR_ATxmega64A4U__"},
{"atxmega64b1", "__AVR_ATxmega64B1__"},
{"atxmega64b3", "__AVR_ATxmega64B3__"},
{"atxmega64c3", "__AVR_ATxmega64C3__"},
{"atxmega64d3", "__AVR_ATxmega64D3__"},
{"atxmega64d4", "__AVR_ATxmega64D4__"},
{"atxmega64a1", "__AVR_ATxmega64A1__"},
{"atxmega64a1u", "__AVR_ATxmega64A1U__"},
{"atxmega128a3", "__AVR_ATxmega128A3__"},
{"atxmega128a3u", "__AVR_ATxmega128A3U__"},
{"atxmega128b1", "__AVR_ATxmega128B1__"},
{"atxmega128b3", "__AVR_ATxmega128B3__"},
{"atxmega128c3", "__AVR_ATxmega128C3__"},
{"atxmega128d3", "__AVR_ATxmega128D3__"},
{"atxmega128d4", "__AVR_ATxmega128D4__"},
{"atxmega192a3", "__AVR_ATxmega192A3__"},
{"atxmega192a3u", "__AVR_ATxmega192A3U__"},
{"atxmega192c3", "__AVR_ATxmega192C3__"},
{"atxmega192d3", "__AVR_ATxmega192D3__"},
{"atxmega256a3", "__AVR_ATxmega256A3__"},
{"atxmega256a3u", "__AVR_ATxmega256A3U__"},
{"atxmega256a3b", "__AVR_ATxmega256A3B__"},
{"atxmega256a3bu", "__AVR_ATxmega256A3BU__"},
{"atxmega256c3", "__AVR_ATxmega256C3__"},
{"atxmega256d3", "__AVR_ATxmega256D3__"},
{"atxmega384c3", "__AVR_ATxmega384C3__"},
{"atxmega384d3", "__AVR_ATxmega384D3__"},
{"atxmega128a1", "__AVR_ATxmega128A1__"},
{"atxmega128a1u", "__AVR_ATxmega128A1U__"},
{"atxmega128a4u", "__AVR_ATxmega128a4U__"},
{"attiny4", "__AVR_ATtiny4__"},
{"attiny5", "__AVR_ATtiny5__"},
{"attiny9", "__AVR_ATtiny9__"},
{"attiny10", "__AVR_ATtiny10__"},
{"attiny20", "__AVR_ATtiny20__"},
{"attiny40", "__AVR_ATtiny40__"},
{"attiny102", "__AVR_ATtiny102__"},
{"attiny104", "__AVR_ATtiny104__"},
};

} // namespace targets
} // namespace clang

bool AVRTargetInfo::isValidCPUName(StringRef Name) const {
bool IsFamily = llvm::StringSwitch<bool>(Name)
.Case("avr1", true)
.Case("avr2", true)
.Case("avr25", true)
.Case("avr3", true)
.Case("avr31", true)
.Case("avr35", true)
.Case("avr4", true)
.Case("avr5", true)
.Case("avr51", true)
.Case("avr6", true)
.Case("avrxmega1", true)
.Case("avrxmega2", true)
.Case("avrxmega3", true)
.Case("avrxmega4", true)
.Case("avrxmega5", true)
.Case("avrxmega6", true)
.Case("avrxmega7", true)
.Case("avrtiny", true)
.Default(false);

bool IsMCU =
std::find_if(AVRMcus.begin(), AVRMcus.end(), [&](const MCUInfo &Info) {
return Info.Name == Name;
}) != AVRMcus.end();
return IsFamily || IsMCU;
}

void AVRTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("AVR");
Builder.defineMacro("__AVR");
Builder.defineMacro("__AVR__");

if (!this->CPU.empty()) {
auto It =
std::find_if(AVRMcus.begin(), AVRMcus.end(), [&](const MCUInfo &Info) {
return Info.Name == this->CPU;
});

if (It != AVRMcus.end())
Builder.defineMacro(It->DefineName);
}
}
186 changes: 186 additions & 0 deletions clang/lib/Basic/Targets/AVR.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
//===--- AVR.h - Declare AVR target feature support -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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;
WCharType = SignedInt;
WIntType = SignedInt;
Char32Type = UnsignedLong;
SigAtomicType = SignedChar;
resetDataLayout("e-p:16:16:16-i8:8:8-i16:16:16-i32:32:32-i64:64:64"
"-f32:32:32-f64:64:64-n8");
}

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;
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
25 changes: 25 additions & 0 deletions clang/lib/Basic/Targets/BPF.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===--- BPF.cpp - Implement BPF target feature support -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements BPF TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "BPF.h"
#include "Targets.h"
#include "clang/Basic/MacroBuilder.h"

using namespace clang;
using namespace clang::targets;

void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
DefineStd(Builder, "bpf", Opts);
Builder.defineMacro("__BPF__");
}
82 changes: 82 additions & 0 deletions clang/lib/Basic/Targets/BPF.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//===--- BPF.h - Declare BPF target feature support -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares BPF TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_BPF_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_BPF_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 {

class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public TargetInfo {
public:
BPFTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
IntPtrType = SignedLong;
IntMaxType = SignedLong;
Int64Type = SignedLong;
RegParmMax = 5;
if (Triple.getArch() == llvm::Triple::bpfeb) {
resetDataLayout("E-m:e-p:64:64-i64:64-n32:64-S128");
} else {
resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
}
MaxAtomicPromoteWidth = 64;
MaxAtomicInlineWidth = 64;
TLSSupported = false;
}

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

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

ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }

const char *getClobbers() const override { return ""; }

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

ArrayRef<const char *> getGCCRegNames() const override { return None; }

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override {
return true;
}

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

CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
switch (CC) {
default:
return CCCR_Warning;
case CC_C:
case CC_OpenCLKernel:
return CCCR_OK;
}
}
};
} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_BPF_H
159 changes: 159 additions & 0 deletions clang/lib/Basic/Targets/Hexagon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
//===--- Hexagon.cpp - Implement Hexagon target feature support -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Hexagon TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "Hexagon.h"
#include "Targets.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/ADT/StringSwitch.h"

using namespace clang;
using namespace clang::targets;

void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__qdsp6__", "1");
Builder.defineMacro("__hexagon__", "1");

if (CPU == "hexagonv4") {
Builder.defineMacro("__HEXAGON_V4__");
Builder.defineMacro("__HEXAGON_ARCH__", "4");
if (Opts.HexagonQdsp6Compat) {
Builder.defineMacro("__QDSP6_V4__");
Builder.defineMacro("__QDSP6_ARCH__", "4");
}
} else if (CPU == "hexagonv5") {
Builder.defineMacro("__HEXAGON_V5__");
Builder.defineMacro("__HEXAGON_ARCH__", "5");
if (Opts.HexagonQdsp6Compat) {
Builder.defineMacro("__QDSP6_V5__");
Builder.defineMacro("__QDSP6_ARCH__", "5");
}
} else if (CPU == "hexagonv55") {
Builder.defineMacro("__HEXAGON_V55__");
Builder.defineMacro("__HEXAGON_ARCH__", "55");
Builder.defineMacro("__QDSP6_V55__");
Builder.defineMacro("__QDSP6_ARCH__", "55");
} else if (CPU == "hexagonv60") {
Builder.defineMacro("__HEXAGON_V60__");
Builder.defineMacro("__HEXAGON_ARCH__", "60");
Builder.defineMacro("__QDSP6_V60__");
Builder.defineMacro("__QDSP6_ARCH__", "60");
} else if (CPU == "hexagonv62") {
Builder.defineMacro("__HEXAGON_V62__");
Builder.defineMacro("__HEXAGON_ARCH__", "62");
}

if (hasFeature("hvx")) {
Builder.defineMacro("__HVX__");
if (hasFeature("hvx-double"))
Builder.defineMacro("__HVXDBL__");
}
}

bool HexagonTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeaturesVec) const {
// Default for v60: -hvx, -hvx-double.
Features["hvx"] = false;
Features["hvx-double"] = false;
Features["long-calls"] = false;

return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}

bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) {
for (auto &F : Features) {
if (F == "+hvx")
HasHVX = true;
else if (F == "-hvx")
HasHVX = HasHVXDouble = false;
else if (F == "+hvx-double")
HasHVX = HasHVXDouble = true;
else if (F == "-hvx-double")
HasHVXDouble = false;

if (F == "+long-calls")
UseLongCalls = true;
else if (F == "-long-calls")
UseLongCalls = false;
}
return true;
}

void HexagonTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name, bool Enabled) const {
if (Enabled) {
if (Name == "hvx-double")
Features["hvx"] = true;
} else {
if (Name == "hvx")
Features["hvx-double"] = false;
}
Features[Name] = Enabled;
}

const char *const HexagonTargetInfo::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", "r26",
"r27", "r28", "r29", "r30", "r31", "p0", "p1", "p2", "p3",
"sa0", "lc0", "sa1", "lc1", "m0", "m1", "usr", "ugp"
};

ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}

const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
{{"sp"}, "r29"},
{{"fp"}, "r30"},
{{"lr"}, "r31"},
};

ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
return llvm::makeArrayRef(GCCRegAliases);
}

const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
{#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsHexagon.def"
};

bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Case("hexagon", true)
.Case("hvx", HasHVX)
.Case("hvx-double", HasHVXDouble)
.Case("long-calls", UseLongCalls)
.Default(false);
}

const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
return llvm::StringSwitch<const char *>(Name)
.Case("hexagonv4", "4")
.Case("hexagonv5", "5")
.Case("hexagonv55", "55")
.Case("hexagonv60", "60")
.Case("hexagonv62", "62")
.Default(nullptr);
}

ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
Builtin::FirstTSBuiltin);
}
130 changes: 130 additions & 0 deletions clang/lib/Basic/Targets/Hexagon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//===--- Hexagon.h - Declare Hexagon target feature support -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares Hexagon TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_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 {

// Hexagon abstract base class
class LLVM_LIBRARY_VISIBILITY HexagonTargetInfo : public TargetInfo {

static const Builtin::Info BuiltinInfo[];
static const char *const GCCRegNames[];
static const TargetInfo::GCCRegAlias GCCRegAliases[];
std::string CPU;
bool HasHVX, HasHVXDouble;
bool UseLongCalls;

public:
HexagonTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
// Specify the vector alignment explicitly. For v512x1, the calculated
// alignment would be 512*alignment(i1), which is 512 bytes, instead of
// the required minimum of 64 bytes.
resetDataLayout(
"e-m:e-p:32:32:32-a:0-n16:32-"
"i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-"
"v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048");
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
IntPtrType = SignedInt;

// {} in inline assembly are packet specifiers, not assembly variant
// specifiers.
NoAsmVariants = true;

LargeArrayMinWidth = 64;
LargeArrayAlign = 64;
UseBitFieldTypeAlignment = true;
ZeroLengthBitfieldBoundary = 32;
HasHVX = HasHVXDouble = false;
UseLongCalls = false;
}

ArrayRef<Builtin::Info> getTargetBuiltins() const override;

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
case 'v':
case 'q':
if (HasHVX) {
Info.setAllowsRegister();
return true;
}
break;
case 'a': // Modifier register m0-m1.
Info.setAllowsRegister();
return true;
case 's':
// Relocatable constant.
return true;
}
return false;
}

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

bool isCLZForZeroUndef() const override { return false; }

bool hasFeature(StringRef Feature) const override;

bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
const std::vector<std::string> &FeaturesVec) const override;

bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;

void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
bool Enabled) const override;

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

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

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

const char *getClobbers() const override { return ""; }

static const char *getHexagonCPUSuffix(StringRef Name);

bool isValidCPUName(StringRef Name) const override {
return getHexagonCPUSuffix(Name);
}

bool setCPU(const std::string &Name) override {
if (!isValidCPUName(Name))
return false;
CPU = Name;
return true;
}

int getEHDataRegisterNumber(unsigned RegNo) const override {
return RegNo < 2 ? RegNo : -1;
}
};
} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H
67 changes: 67 additions & 0 deletions clang/lib/Basic/Targets/Lanai.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//===--- Lanai.cpp - Implement Lanai target feature support ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Lanai TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "Lanai.h"
#include "clang/Basic/MacroBuilder.h"
#include "llvm/ADT/StringSwitch.h"

using namespace clang;
using namespace clang::targets;

const char *const LanaiTargetInfo::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", "r26", "r27", "r28", "r29", "r30", "r31"
};

ArrayRef<const char *> LanaiTargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}

const TargetInfo::GCCRegAlias LanaiTargetInfo::GCCRegAliases[] = {
{{"pc"}, "r2"}, {{"sp"}, "r4"}, {{"fp"}, "r5"}, {{"rv"}, "r8"},
{{"rr1"}, "r10"}, {{"rr2"}, "r11"}, {{"rca"}, "r15"},
};

ArrayRef<TargetInfo::GCCRegAlias> LanaiTargetInfo::getGCCRegAliases() const {
return llvm::makeArrayRef(GCCRegAliases);
}

bool LanaiTargetInfo::isValidCPUName(StringRef Name) const {
return llvm::StringSwitch<bool>(Name).Case("v11", true).Default(false);
}

bool LanaiTargetInfo::setCPU(const std::string &Name) {
CPU = llvm::StringSwitch<CPUKind>(Name).Case("v11", CK_V11).Default(CK_NONE);

return CPU != CK_NONE;
}

bool LanaiTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature).Case("lanai", true).Default(false);
}

void LanaiTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Define __lanai__ when building for target lanai.
Builder.defineMacro("__lanai__");

// Set define for the CPU specified.
switch (CPU) {
case CK_V11:
Builder.defineMacro("__LANAI_V11__");
break;
case CK_NONE:
llvm_unreachable("Unhandled target CPU");
}
}
92 changes: 92 additions & 0 deletions clang/lib/Basic/Targets/Lanai.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//===--- Lanai.h - Declare Lanai target feature support ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares Lanai TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_LANAI_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_LANAI_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 {

class LLVM_LIBRARY_VISIBILITY LanaiTargetInfo : public TargetInfo {
// Class for Lanai (32-bit).
// The CPU profiles supported by the Lanai backend
enum CPUKind {
CK_NONE,
CK_V11,
} CPU;

static const TargetInfo::GCCRegAlias GCCRegAliases[];
static const char *const GCCRegNames[];

public:
LanaiTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
// Description string has to be kept in sync with backend.
resetDataLayout("E" // Big endian
"-m:e" // ELF name manging
"-p:32:32" // 32 bit pointers, 32 bit aligned
"-i64:64" // 64 bit integers, 64 bit aligned
"-a:0:32" // 32 bit alignment of objects of aggregate type
"-n32" // 32 bit native integer width
"-S64" // 64 bit natural stack alignment
);

// Setting RegParmMax equal to what mregparm was set to in the old
// toolchain
RegParmMax = 4;

// Set the default CPU to V11
CPU = CK_V11;

// Temporary approach to make everything at least word-aligned and allow for
// safely casting between pointers with different alignment requirements.
// TODO: Remove this when there are no more cast align warnings on the
// firmware.
MinGlobalAlign = 32;
}

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

bool isValidCPUName(StringRef Name) const override;

bool setCPU(const std::string &Name) override;

bool hasFeature(StringRef Feature) const override;

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

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

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

ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override {
return false;
}

const char *getClobbers() const override { return ""; }
};
} // namespace targets
} // namespace clang

#endif // LLVM_CLANG_LIB_BASIC_TARGETS_LANAI_H
39 changes: 39 additions & 0 deletions clang/lib/Basic/Targets/Le64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//===--- Le64.cpp - Implement Le64 target feature support -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Le64 TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "Le64.h"
#include "Targets.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"

using namespace clang;
using namespace clang::targets;

const Builtin::Info Le64TargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsLe64.def"
};

ArrayRef<Builtin::Info> Le64TargetInfo::getTargetBuiltins() const {
return llvm::makeArrayRef(BuiltinInfo, clang::Le64::LastTSBuiltin -
Builtin::FirstTSBuiltin);
}

void Le64TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
DefineStd(Builder, "unix", Opts);
defineCPUMacros(Builder, "le64", /*Tuning=*/false);
Builder.defineMacro("__ELF__");
}
64 changes: 64 additions & 0 deletions clang/lib/Basic/Targets/Le64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//===--- Le64.h - Declare Le64 target feature support -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares Le64 TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_LE64_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_LE64_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 {

class LLVM_LIBRARY_VISIBILITY Le64TargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];

public:
Le64TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
NoAsmVariants = true;
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
resetDataLayout("e-m:e-v128:32-v16:16-v32:32-v96:32-n8:16:32:64-S128");
}

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

ArrayRef<Builtin::Info> getTargetBuiltins() const override;

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

const char *getClobbers() const override { return ""; }

ArrayRef<const char *> getGCCRegNames() const override { return None; }

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

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
return false;
}

bool hasProtectedVisibility() const override { return false; }
};

} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_LE64_H
34 changes: 34 additions & 0 deletions clang/lib/Basic/Targets/MSP430.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===--- MSP430.cpp - Implement MSP430 target feature support -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements MSP430 TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "MSP430.h"
#include "clang/Basic/MacroBuilder.h"

using namespace clang;
using namespace clang::targets;

const char *const MSP430TargetInfo::GCCRegNames[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
};

ArrayRef<const char *> MSP430TargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}

void MSP430TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("MSP430");
Builder.defineMacro("__MSP430__");
// FIXME: defines for different 'flavours' of MCU
}
92 changes: 92 additions & 0 deletions clang/lib/Basic/Targets/MSP430.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//===--- MSP430.h - Declare MSP430 target feature support -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares MSP430 TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MSP430_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_MSP430_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 {

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

public:
MSP430TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
TLSSupported = false;
IntWidth = 16;
IntAlign = 16;
LongWidth = 32;
LongLongWidth = 64;
LongAlign = LongLongAlign = 16;
PointerWidth = 16;
PointerAlign = 16;
SuitableAlign = 16;
SizeType = UnsignedInt;
IntMaxType = SignedLongLong;
IntPtrType = SignedInt;
PtrDiffType = SignedInt;
SigAtomicType = SignedLong;
resetDataLayout("e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16");
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;

ArrayRef<Builtin::Info> getTargetBuiltins() const override {
// FIXME: Implement.
return None;
}

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

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

ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
// No aliases.
return None;
}

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override {
// FIXME: implement
switch (*Name) {
case 'K': // the constant 1
case 'L': // constant -1^20 .. 1^19
case 'M': // constant 1-4:
return true;
}
// No target constraints for now.
return false;
}

const char *getClobbers() const override {
// FIXME: Is this really right?
return "";
}

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

} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_MSP430_H
242 changes: 242 additions & 0 deletions clang/lib/Basic/Targets/Mips.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
//===--- Mips.cpp - Implement Mips target feature support -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Mips TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "Mips.h"
#include "Targets.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/ADT/StringSwitch.h"

using namespace clang;
using namespace clang::targets;

const Builtin::Info MipsTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
{#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsMips.def"
};

bool MipsTargetInfo::processorSupportsGPR64() const {
return llvm::StringSwitch<bool>(CPU)
.Case("mips3", true)
.Case("mips4", true)
.Case("mips5", true)
.Case("mips64", true)
.Case("mips64r2", true)
.Case("mips64r3", true)
.Case("mips64r5", true)
.Case("mips64r6", true)
.Case("octeon", true)
.Default(false);
return false;
}

bool MipsTargetInfo::isValidCPUName(StringRef Name) const {
return llvm::StringSwitch<bool>(Name)
.Case("mips1", true)
.Case("mips2", true)
.Case("mips3", true)
.Case("mips4", true)
.Case("mips5", true)
.Case("mips32", true)
.Case("mips32r2", true)
.Case("mips32r3", true)
.Case("mips32r5", true)
.Case("mips32r6", true)
.Case("mips64", true)
.Case("mips64r2", true)
.Case("mips64r3", true)
.Case("mips64r5", true)
.Case("mips64r6", true)
.Case("octeon", true)
.Case("p5600", true)
.Default(false);
}

void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
if (BigEndian) {
DefineStd(Builder, "MIPSEB", Opts);
Builder.defineMacro("_MIPSEB");
} else {
DefineStd(Builder, "MIPSEL", Opts);
Builder.defineMacro("_MIPSEL");
}

Builder.defineMacro("__mips__");
Builder.defineMacro("_mips");
if (Opts.GNUMode)
Builder.defineMacro("mips");

if (ABI == "o32") {
Builder.defineMacro("__mips", "32");
Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS32");
} else {
Builder.defineMacro("__mips", "64");
Builder.defineMacro("__mips64");
Builder.defineMacro("__mips64__");
Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64");
}

const std::string ISARev = llvm::StringSwitch<std::string>(getCPU())
.Cases("mips32", "mips64", "1")
.Cases("mips32r2", "mips64r2", "2")
.Cases("mips32r3", "mips64r3", "3")
.Cases("mips32r5", "mips64r5", "5")
.Cases("mips32r6", "mips64r6", "6")
.Default("");
if (!ISARev.empty())
Builder.defineMacro("__mips_isa_rev", ISARev);

if (ABI == "o32") {
Builder.defineMacro("__mips_o32");
Builder.defineMacro("_ABIO32", "1");
Builder.defineMacro("_MIPS_SIM", "_ABIO32");
} else if (ABI == "n32") {
Builder.defineMacro("__mips_n32");
Builder.defineMacro("_ABIN32", "2");
Builder.defineMacro("_MIPS_SIM", "_ABIN32");
} else if (ABI == "n64") {
Builder.defineMacro("__mips_n64");
Builder.defineMacro("_ABI64", "3");
Builder.defineMacro("_MIPS_SIM", "_ABI64");
} else
llvm_unreachable("Invalid ABI.");

if (!IsNoABICalls) {
Builder.defineMacro("__mips_abicalls");
if (CanUseBSDABICalls)
Builder.defineMacro("__ABICALLS__");
}

Builder.defineMacro("__REGISTER_PREFIX__", "");

switch (FloatABI) {
case HardFloat:
Builder.defineMacro("__mips_hard_float", Twine(1));
break;
case SoftFloat:
Builder.defineMacro("__mips_soft_float", Twine(1));
break;
}

if (IsSingleFloat)
Builder.defineMacro("__mips_single_float", Twine(1));

Builder.defineMacro("__mips_fpr", HasFP64 ? Twine(64) : Twine(32));
Builder.defineMacro("_MIPS_FPSET",
Twine(32 / (HasFP64 || IsSingleFloat ? 1 : 2)));

if (IsMips16)
Builder.defineMacro("__mips16", Twine(1));

if (IsMicromips)
Builder.defineMacro("__mips_micromips", Twine(1));

if (IsNan2008)
Builder.defineMacro("__mips_nan2008", Twine(1));

switch (DspRev) {
default:
break;
case DSP1:
Builder.defineMacro("__mips_dsp_rev", Twine(1));
Builder.defineMacro("__mips_dsp", Twine(1));
break;
case DSP2:
Builder.defineMacro("__mips_dsp_rev", Twine(2));
Builder.defineMacro("__mips_dspr2", Twine(1));
Builder.defineMacro("__mips_dsp", Twine(1));
break;
}

if (HasMSA)
Builder.defineMacro("__mips_msa", Twine(1));

if (DisableMadd4)
Builder.defineMacro("__mips_no_madd4", Twine(1));

Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0)));
Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth()));
Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth()));

Builder.defineMacro("_MIPS_ARCH", "\"" + CPU + "\"");
Builder.defineMacro("_MIPS_ARCH_" + StringRef(CPU).upper());

// These shouldn't be defined for MIPS-I but there's no need to check
// for that since MIPS-I isn't supported.
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");

// 32-bit MIPS processors don't have the necessary lld/scd instructions
// found in 64-bit processors. In the case of O32 on a 64-bit processor,
// the instructions exist but using them violates the ABI since they
// require 64-bit GPRs and O32 only supports 32-bit GPRs.
if (ABI == "n32" || ABI == "n64")
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}

bool MipsTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Case("mips", true)
.Case("fp64", HasFP64)
.Default(false);
}

ArrayRef<Builtin::Info> MipsTargetInfo::getTargetBuiltins() const {
return llvm::makeArrayRef(BuiltinInfo, clang::Mips::LastTSBuiltin -
Builtin::FirstTSBuiltin);
}

bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
// FIXME: It's valid to use O32 on a 64-bit CPU but the backend can't handle
// this yet. It's better to fail here than on the backend assertion.
if (processorSupportsGPR64() && ABI == "o32") {
Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
return false;
}

// 64-bit ABI's require 64-bit CPU's.
if (!processorSupportsGPR64() && (ABI == "n32" || ABI == "n64")) {
Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
return false;
}

// FIXME: It's valid to use O32 on a mips64/mips64el triple but the backend
// can't handle this yet. It's better to fail here than on the
// backend assertion.
if ((getTriple().getArch() == llvm::Triple::mips64 ||
getTriple().getArch() == llvm::Triple::mips64el) &&
ABI == "o32") {
Diags.Report(diag::err_target_unsupported_abi_for_triple)
<< ABI << getTriple().str();
return false;
}

// FIXME: It's valid to use N32/N64 on a mips/mipsel triple but the backend
// can't handle this yet. It's better to fail here than on the
// backend assertion.
if ((getTriple().getArch() == llvm::Triple::mips ||
getTriple().getArch() == llvm::Triple::mipsel) &&
(ABI == "n32" || ABI == "n64")) {
Diags.Report(diag::err_target_unsupported_abi_for_triple)
<< ABI << getTriple().str();
return false;
}

return true;
}
391 changes: 391 additions & 0 deletions clang/lib/Basic/Targets/Mips.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,391 @@
//===--- Mips.h - Declare Mips target feature support -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares Mips TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_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 {

class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
void setDataLayout() {
StringRef Layout;

if (ABI == "o32")
Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
else if (ABI == "n32")
Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
else if (ABI == "n64")
Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128";
else
llvm_unreachable("Invalid ABI");

if (BigEndian)
resetDataLayout(("E-" + Layout).str());
else
resetDataLayout(("e-" + Layout).str());
}

static const Builtin::Info BuiltinInfo[];
std::string CPU;
bool IsMips16;
bool IsMicromips;
bool IsNan2008;
bool IsSingleFloat;
bool IsNoABICalls;
bool CanUseBSDABICalls;
enum MipsFloatABI { HardFloat, SoftFloat } FloatABI;
enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev;
bool HasMSA;
bool DisableMadd4;

protected:
bool HasFP64;
std::string ABI;

public:
MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple), IsMips16(false), IsMicromips(false),
IsNan2008(false), IsSingleFloat(false), IsNoABICalls(false),
CanUseBSDABICalls(false), FloatABI(HardFloat), DspRev(NoDSP),
HasMSA(false), DisableMadd4(false), HasFP64(false) {
TheCXXABI.set(TargetCXXABI::GenericMIPS);

setABI((getTriple().getArch() == llvm::Triple::mips ||
getTriple().getArch() == llvm::Triple::mipsel)
? "o32"
: "n64");

CPU = ABI == "o32" ? "mips32r2" : "mips64r2";

CanUseBSDABICalls = Triple.getOS() == llvm::Triple::FreeBSD ||
Triple.getOS() == llvm::Triple::OpenBSD;
}

bool isNaN2008Default() const {
return CPU == "mips32r6" || CPU == "mips64r6";
}

bool isFP64Default() const {
return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64";
}

bool isNan2008() const override { return IsNan2008; }

bool processorSupportsGPR64() const;

StringRef getABI() const override { return ABI; }

bool setABI(const std::string &Name) override {
if (Name == "o32") {
setO32ABITypes();
ABI = Name;
return true;
}

if (Name == "n32") {
setN32ABITypes();
ABI = Name;
return true;
}
if (Name == "n64") {
setN64ABITypes();
ABI = Name;
return true;
}
return false;
}

void setO32ABITypes() {
Int64Type = SignedLongLong;
IntMaxType = Int64Type;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
LongDoubleWidth = LongDoubleAlign = 64;
LongWidth = LongAlign = 32;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
PointerWidth = PointerAlign = 32;
PtrDiffType = SignedInt;
SizeType = UnsignedInt;
SuitableAlign = 64;
}

void setN32N64ABITypes() {
LongDoubleWidth = LongDoubleAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad();
if (getTriple().getOS() == llvm::Triple::FreeBSD) {
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
}
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
SuitableAlign = 128;
}

void setN64ABITypes() {
setN32N64ABITypes();
if (getTriple().getOS() == llvm::Triple::OpenBSD) {
Int64Type = SignedLongLong;
} else {
Int64Type = SignedLong;
}
IntMaxType = Int64Type;
LongWidth = LongAlign = 64;
PointerWidth = PointerAlign = 64;
PtrDiffType = SignedLong;
SizeType = UnsignedLong;
}

void setN32ABITypes() {
setN32N64ABITypes();
Int64Type = SignedLongLong;
IntMaxType = Int64Type;
LongWidth = LongAlign = 32;
PointerWidth = PointerAlign = 32;
PtrDiffType = SignedInt;
SizeType = UnsignedInt;
}

bool isValidCPUName(StringRef Name) const override;

bool setCPU(const std::string &Name) override {
CPU = Name;
return isValidCPUName(Name);
}

const std::string &getCPU() const { return CPU; }
bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
const std::vector<std::string> &FeaturesVec) const override {
if (CPU.empty())
CPU = getCPU();
if (CPU == "octeon")
Features["mips64r2"] = Features["cnmips"] = true;
else
Features[CPU] = true;
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}

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

ArrayRef<Builtin::Info> getTargetBuiltins() const override;

bool hasFeature(StringRef Feature) const override;

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

ArrayRef<const char *> getGCCRegNames() const override {
static const char *const GCCRegNames[] = {
// CPU register names
// Must match second column of GCCRegAliases
"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10",
"$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20",
"$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30",
"$31",
// Floating point register names
"$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",
"$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18",
"$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
"$f28", "$f29", "$f30", "$f31",
// Hi/lo and condition register names
"hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5",
"$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi",
"$ac3lo",
// MSA register names
"$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9",
"$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18",
"$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27",
"$w28", "$w29", "$w30", "$w31",
// MSA control register names
"$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify",
"$msarequest", "$msamap", "$msaunmap"
};
return llvm::makeArrayRef(GCCRegNames);
}

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
default:
return false;
case 'r': // CPU registers.
case 'd': // Equivalent to "r" unless generating MIPS16 code.
case 'y': // Equivalent to "r", backward compatibility only.
case 'f': // floating-point registers.
case 'c': // $25 for indirect jumps
case 'l': // lo register
case 'x': // hilo register pair
Info.setAllowsRegister();
return true;
case 'I': // Signed 16-bit constant
case 'J': // Integer 0
case 'K': // Unsigned 16-bit constant
case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui)
case 'M': // Constants not loadable via lui, addiu, or ori
case 'N': // Constant -1 to -65535
case 'O': // A signed 15-bit constant
case 'P': // A constant between 1 go 65535
return true;
case 'R': // An address that can be used in a non-macro load or store
Info.setAllowsMemory();
return true;
case 'Z':
if (Name[1] == 'C') { // An address usable by ll, and sc.
Info.setAllowsMemory();
Name++; // Skip over 'Z'.
return true;
}
return false;
}
}

std::string convertConstraint(const char *&Constraint) const override {
std::string R;
switch (*Constraint) {
case 'Z': // Two-character constraint; add "^" hint for later parsing.
if (Constraint[1] == 'C') {
R = std::string("^") + std::string(Constraint, 2);
Constraint++;
return R;
}
break;
}
return TargetInfo::convertConstraint(Constraint);
}

const char *getClobbers() const override {
// In GCC, $1 is not widely used in generated code (it's used only in a few
// specific situations), so there is no real need for users to add it to
// the clobbers list if they want to use it in their inline assembly code.
//
// In LLVM, $1 is treated as a normal GPR and is always allocatable during
// code generation, so using it in inline assembly without adding it to the
// clobbers list can cause conflicts between the inline assembly code and
// the surrounding generated code.
//
// Another problem is that LLVM is allowed to choose $1 for inline assembly
// operands, which will conflict with the ".set at" assembler option (which
// we use only for inline assembly, in order to maintain compatibility with
// GCC) and will also conflict with the user's usage of $1.
//
// The easiest way to avoid these conflicts and keep $1 as an allocatable
// register for generated code is to automatically clobber $1 for all inline
// assembly code.
//
// FIXME: We should automatically clobber $1 only for inline assembly code
// which actually uses it. This would allow LLVM to use $1 for inline
// assembly operands if the user's assembly code doesn't use it.
return "~{$1}";
}

bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override {
IsMips16 = false;
IsMicromips = false;
IsNan2008 = isNaN2008Default();
IsSingleFloat = false;
FloatABI = HardFloat;
DspRev = NoDSP;
HasFP64 = isFP64Default();

for (const auto &Feature : Features) {
if (Feature == "+single-float")
IsSingleFloat = true;
else if (Feature == "+soft-float")
FloatABI = SoftFloat;
else if (Feature == "+mips16")
IsMips16 = true;
else if (Feature == "+micromips")
IsMicromips = true;
else if (Feature == "+dsp")
DspRev = std::max(DspRev, DSP1);
else if (Feature == "+dspr2")
DspRev = std::max(DspRev, DSP2);
else if (Feature == "+msa")
HasMSA = true;
else if (Feature == "+nomadd4")
DisableMadd4 = true;
else if (Feature == "+fp64")
HasFP64 = true;
else if (Feature == "-fp64")
HasFP64 = false;
else if (Feature == "+nan2008")
IsNan2008 = true;
else if (Feature == "-nan2008")
IsNan2008 = false;
else if (Feature == "+noabicalls")
IsNoABICalls = true;
}

setDataLayout();

return true;
}

int getEHDataRegisterNumber(unsigned RegNo) const override {
if (RegNo == 0)
return 4;
if (RegNo == 1)
return 5;
return -1;
}

bool isCLZForZeroUndef() const override { return false; }

ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
static const TargetInfo::GCCRegAlias O32RegAliases[] = {
{{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
{{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
{{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"},
{{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"},
{{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"},
{{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
{{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
{{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
{{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
{{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
{{"ra"}, "$31"}
};
static const TargetInfo::GCCRegAlias NewABIRegAliases[] = {
{{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
{{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
{{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"},
{{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"},
{{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"},
{{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
{{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
{{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
{{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
{{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
{{"ra"}, "$31"}
};
if (ABI == "o32")
return llvm::makeArrayRef(O32RegAliases);
return llvm::makeArrayRef(NewABIRegAliases);
}

bool hasInt128Type() const override { return ABI == "n32" || ABI == "n64"; }

bool validateTarget(DiagnosticsEngine &Diags) const override;
};
} // namespace targets
} // namespace clang

#endif // LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
196 changes: 196 additions & 0 deletions clang/lib/Basic/Targets/NVPTX.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
//===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements NVPTX TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "NVPTX.h"
#include "Targets.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/ADT/StringSwitch.h"

using namespace clang;
using namespace clang::targets;

const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
{#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
#include "clang/Basic/BuiltinsNVPTX.def"
};

const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};

NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts,
unsigned TargetPointerWidth)
: TargetInfo(Triple) {
assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) &&
"NVPTX only supports 32- and 64-bit modes.");

TLSSupported = false;
AddrSpaceMap = &NVPTXAddrSpaceMap;
UseAddrSpaceMapMangling = true;

// Define available target features
// These must be defined in sorted order!
NoAsmVariants = true;
GPU = CudaArch::SM_20;

if (TargetPointerWidth == 32)
resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
else
resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64");

// If possible, get a TargetInfo for our host triple, so we can match its
// types.
llvm::Triple HostTriple(Opts.HostTriple);
if (!HostTriple.isNVPTX())
HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts));

// If no host target, make some guesses about the data layout and return.
if (!HostTarget) {
LongWidth = LongAlign = TargetPointerWidth;
PointerWidth = PointerAlign = TargetPointerWidth;
switch (TargetPointerWidth) {
case 32:
SizeType = TargetInfo::UnsignedInt;
PtrDiffType = TargetInfo::SignedInt;
IntPtrType = TargetInfo::SignedInt;
break;
case 64:
SizeType = TargetInfo::UnsignedLong;
PtrDiffType = TargetInfo::SignedLong;
IntPtrType = TargetInfo::SignedLong;
break;
default:
llvm_unreachable("TargetPointerWidth must be 32 or 64");
}
return;
}

// Copy properties from host target.
PointerWidth = HostTarget->getPointerWidth(/* AddrSpace = */ 0);
PointerAlign = HostTarget->getPointerAlign(/* AddrSpace = */ 0);
BoolWidth = HostTarget->getBoolWidth();
BoolAlign = HostTarget->getBoolAlign();
IntWidth = HostTarget->getIntWidth();
IntAlign = HostTarget->getIntAlign();
HalfWidth = HostTarget->getHalfWidth();
HalfAlign = HostTarget->getHalfAlign();
FloatWidth = HostTarget->getFloatWidth();
FloatAlign = HostTarget->getFloatAlign();
DoubleWidth = HostTarget->getDoubleWidth();
DoubleAlign = HostTarget->getDoubleAlign();
LongWidth = HostTarget->getLongWidth();
LongAlign = HostTarget->getLongAlign();
LongLongWidth = HostTarget->getLongLongWidth();
LongLongAlign = HostTarget->getLongLongAlign();
MinGlobalAlign = HostTarget->getMinGlobalAlign();
NewAlign = HostTarget->getNewAlign();
DefaultAlignForAttributeAligned =
HostTarget->getDefaultAlignForAttributeAligned();
SizeType = HostTarget->getSizeType();
IntMaxType = HostTarget->getIntMaxType();
PtrDiffType = HostTarget->getPtrDiffType(/* AddrSpace = */ 0);
IntPtrType = HostTarget->getIntPtrType();
WCharType = HostTarget->getWCharType();
WIntType = HostTarget->getWIntType();
Char16Type = HostTarget->getChar16Type();
Char32Type = HostTarget->getChar32Type();
Int64Type = HostTarget->getInt64Type();
SigAtomicType = HostTarget->getSigAtomicType();
ProcessIDType = HostTarget->getProcessIDType();

UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment();
UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();

// This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
// we need those macros to be identical on host and device, because (among
// other things) they affect which standard library classes are defined, and
// we need all classes to be defined on both the host and device.
MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();

// Properties intentionally not copied from host:
// - LargeArrayMinWidth, LargeArrayAlign: Not visible across the
// host/device boundary.
// - SuitableAlign: Not visible across the host/device boundary, and may
// correctly be different on host/device, e.g. if host has wider vector
// types than device.
// - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same
// as its double type, but that's not necessarily true on the host.
// TODO: nvcc emits a warning when using long double on device; we should
// do the same.
}

ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}

bool NVPTXTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Cases("ptx", "nvptx", true)
.Case("satom", GPU >= CudaArch::SM_60) // Atomics w/ scope.
.Default(false);
}

void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__PTX__");
Builder.defineMacro("__NVPTX__");
if (Opts.CUDAIsDevice) {
// Set __CUDA_ARCH__ for the GPU specified.
std::string CUDAArchCode = [this] {
switch (GPU) {
case CudaArch::UNKNOWN:
assert(false && "No GPU arch when compiling CUDA device code.");
return "";
case CudaArch::SM_20:
return "200";
case CudaArch::SM_21:
return "210";
case CudaArch::SM_30:
return "300";
case CudaArch::SM_32:
return "320";
case CudaArch::SM_35:
return "350";
case CudaArch::SM_37:
return "370";
case CudaArch::SM_50:
return "500";
case CudaArch::SM_52:
return "520";
case CudaArch::SM_53:
return "530";
case CudaArch::SM_60:
return "600";
case CudaArch::SM_61:
return "610";
case CudaArch::SM_62:
return "620";
}
llvm_unreachable("unhandled CudaArch");
}();
Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
}
}

ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const {
return llvm::makeArrayRef(BuiltinInfo, clang::NVPTX::LastTSBuiltin -
Builtin::FirstTSBuiltin);
}
Loading