40 changes: 40 additions & 0 deletions clang/lib/Basic/Targets/Xtensa.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===--- Xtensa.cpp - Implement Xtensa target feature support -------------===//
//
// The LLVM Compiler Infrastructure
//
// 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 Xtensa TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "Xtensa.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 XtensaTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsXtensa.def"
};

void XtensaTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__Xtensa__");
Builder.defineMacro("__xtensa__");
Builder.defineMacro("__XTENSA__");
Builder.defineMacro("__XTENSA_EL__");
}

ArrayRef<Builtin::Info> XtensaTargetInfo::getTargetBuiltins() const {
return llvm::makeArrayRef(BuiltinInfo, clang::Xtensa::LastTSBuiltin -
Builtin::FirstTSBuiltin);
}
111 changes: 111 additions & 0 deletions clang/lib/Basic/Targets/Xtensa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//===--- Xtensa.h - Declare Xtensa target feature support -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares Xtensa TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_XTENSA_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_XTENSA_H

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

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

namespace clang {
namespace targets {

class LLVM_LIBRARY_VISIBILITY XtensaTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
std::string CPU;

public:
XtensaTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
BigEndian = false;
NoAsmVariants = true;
LongLongAlign = 64;
SuitableAlign = 32;
DoubleAlign = LongDoubleAlign = 64;
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
IntPtrType = SignedInt;
WCharType = UnsignedChar;
WIntType = UnsignedInt;
UseZeroLengthBitfieldAlignment = true;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
resetDataLayout("e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32");
}

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

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

BuiltinVaListKind getBuiltinVaListKind() const override {

return TargetInfo::XtensaABIBuiltinVaList;
}

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

ArrayRef<const char *> getGCCRegNames() const override {
static const char *const GCCRegNames[] = {
// General register name
"a0", "sp", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10",
"a11", "a12", "a13", "a14", "a15",
// Special register name
"sar"};
return llvm::makeArrayRef(GCCRegNames);
}

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

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
default:
return false;
case 'a':
Info.setAllowsRegister();
return true;
}
return false;
}

int getEHDataRegisterNumber(unsigned RegNo) const override {
return (RegNo < 2) ? RegNo : -1;
}

bool isValidCPUName(StringRef Name) const override {
return llvm::StringSwitch<bool>(Name)
.Case("esp32", true)
.Case("esp8266", true)
.Case("esp32-s2", true)
.Case("generic", true)
.Default(false);
}

bool setCPU(const std::string &Name) override {
CPU = Name;
return isValidCPUName(Name);
}
};
} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_XTENSA_H
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11118,6 +11118,7 @@ bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(
case llvm::Triple::renderscript32:
case llvm::Triple::renderscript64:
case llvm::Triple::ve:
case llvm::Triple::xtensa:
return false;
}
}
Expand Down
223 changes: 223 additions & 0 deletions clang/lib/CodeGen/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9772,6 +9772,227 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
};
} // namespace

//===----------------------------------------------------------------------===//
// Xtensa ABI Implementation
//===----------------------------------------------------------------------===//

namespace {
class XtensaABIInfo : public DefaultABIInfo {
private:
static const int MaxNumArgGPRs = 6;
static const int MaxNumRetGPRs = 4;

public:
XtensaABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}

// DefaultABIInfo's classifyReturnType and classifyArgumentType are
// non-virtual, but computeInfo is virtual, so we overload it.
void computeInfo(CGFunctionInfo &FI) const override;

ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft) const;

ABIArgInfo classifyReturnType(QualType RetTy) const;

Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;

ABIArgInfo extendType(QualType Ty) const;
};
} // end anonymous namespace

void XtensaABIInfo::computeInfo(CGFunctionInfo &FI) const {
QualType RetTy = FI.getReturnType();
if (!getCXXABI().classifyReturnType(FI))
FI.getReturnInfo() = classifyReturnType(RetTy);

int ArgGPRsLeft = MaxNumArgGPRs;
for (auto &ArgInfo : FI.arguments()) {
ArgInfo.info = classifyArgumentType(ArgInfo.type, ArgGPRsLeft);
}
}

ABIArgInfo XtensaABIInfo::classifyArgumentType(QualType Ty,
int &ArgGPRsLeft) const {
assert(ArgGPRsLeft <= MaxNumArgGPRs && "Arg GPR tracking underflow");
Ty = useFirstFieldIfTransparentUnion(Ty);
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always passed indirectly.
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
if (ArgGPRsLeft)
ArgGPRsLeft -= 1;
return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
CGCXXABI::RAA_DirectInMemory);
}

// Ignore empty structs/unions.
if (isEmptyRecord(getContext(), Ty, true))
return ABIArgInfo::getIgnore();

uint64_t Size = getContext().getTypeSize(Ty);
uint64_t NeededAlign = getContext().getTypeAlign(Ty);
bool MustUseStack = false;
int NeededArgGPRs = (Size + 31) / 32;

if (NeededAlign == (2 * 32))
NeededArgGPRs += (ArgGPRsLeft % 2);

// Put on stack objects which are not fit to 6 registers,
// also on stack object which alignment more then 16 bytes and
// object with 16-byte alignment if it isn't the first argument.
if ((NeededArgGPRs > ArgGPRsLeft) || (NeededAlign > (4 * 32)) ||
((ArgGPRsLeft < 6) && (NeededAlign == (4 * 32)))) {
MustUseStack = true;
NeededArgGPRs = ArgGPRsLeft;
}
ArgGPRsLeft -= NeededArgGPRs;

if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType() && !MustUseStack) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
// All integral types are promoted to XLen width, unless passed on the
// stack.
if (Size < 32 && Ty->isIntegralOrEnumerationType() && !MustUseStack) {
return extendType(Ty);
}
if (Size == 64)
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), 64));
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), 32));
}

// Aggregates which are <= 6*32 will be passed in registers if possible,
// so coerce to integers.
if ((Size <= (MaxNumArgGPRs * 32)) && (!MustUseStack)) {
if (Size <= 32) {
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), 32));
} else if (NeededAlign == (2 * 32)) {
return ABIArgInfo::getDirect(llvm::ArrayType::get(
llvm::IntegerType::get(getVMContext(), 64), NeededArgGPRs / 2));
} else {
return ABIArgInfo::getDirect(llvm::ArrayType::get(
llvm::IntegerType::get(getVMContext(), 32), NeededArgGPRs));
}
}
#undef MAX_STRUCT_IN_REGS_SIZE
return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
}

ABIArgInfo XtensaABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
int ArgGPRsLeft = MaxNumRetGPRs;
// The rules for return and argument types are the same, so defer to
// classifyArgumentType.
return classifyArgumentType(RetTy, ArgGPRsLeft);
}

Address XtensaABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const {
// The va_list structure memory layout:
// struct __va_list_tag {
// int32_t *va_stk;
// int32_t *va_reg;
// int32_t va_ndx;
// };
CGBuilderTy &Builder = CGF.Builder;

Address OverflowAreaPtr = Builder.CreateStructGEP(VAListAddr, 0, "__va_stk");
Address OverflowArea = Address(Builder.CreateLoad(OverflowAreaPtr, ""),
CharUnits::fromQuantity(4));
Address RegSaveAreaPtr = Builder.CreateStructGEP(VAListAddr, 1, "__va_reg");
Address RegSaveArea = Address(Builder.CreateLoad(RegSaveAreaPtr, ""),
CharUnits::fromQuantity(4));
Address ARAreaPtr = Builder.CreateStructGEP(VAListAddr, 2, "__va_ndx");
llvm::Value *ARIndex = Builder.CreateLoad(ARAreaPtr, "");

ARIndex = Builder.CreateLShr(ARIndex, Builder.getInt32(2));

unsigned Align = getContext().getTypeAlign(Ty) / 32;
unsigned Size = (getContext().getTypeSize(Ty) + 31) / 32;

if (Align > 1) {
ARIndex = Builder.CreateAdd(ARIndex, Builder.getInt32(Align - 1));
ARIndex =
Builder.CreateAnd(ARIndex, Builder.getInt32((uint32_t) ~(Align - 1)));
}

llvm::Value *ARIndexNext = Builder.CreateAdd(ARIndex, Builder.getInt32(Size));
Builder.CreateStore(Builder.CreateShl(ARIndexNext, Builder.getInt32(2)),
ARAreaPtr);

const unsigned OverflowLimit = 6;
llvm::Value *CC = Builder.CreateICmpULE(
ARIndexNext, Builder.getInt32(OverflowLimit), "cond");

llvm::BasicBlock *UsingRegSaveArea =
CGF.createBasicBlock("using_regsavearea");
llvm::BasicBlock *UsingOverflow = CGF.createBasicBlock("using_overflow");
llvm::BasicBlock *Cont = CGF.createBasicBlock("cont");

Builder.CreateCondBr(CC, UsingRegSaveArea, UsingOverflow);

llvm::Type *DirectTy = CGF.ConvertType(Ty);

// Case 1: consume registers.
Address RegAddr = Address::invalid();
{
CGF.EmitBlock(UsingRegSaveArea);

CharUnits RegSize = CharUnits::fromQuantity(4);
RegSaveArea =
Address(Builder.CreateInBoundsGEP(CGF.Int32Ty, RegSaveArea.getPointer(),
ARIndex),
RegSaveArea.getAlignment().alignmentOfArrayElement(RegSize));
RegAddr = Builder.CreateElementBitCast(RegSaveArea, DirectTy);
CGF.EmitBranch(Cont);
}

// Case 2: consume space in the overflow area.
Address MemAddr = Address::invalid();
{
CGF.EmitBlock(UsingOverflow);
llvm::Value *CC1 = Builder.CreateICmpULE(
ARIndex, Builder.getInt32(OverflowLimit), "cond_overflow");

llvm::Value *ARIndexOff = Builder.CreateSelect(
CC1, Builder.CreateSub(Builder.getInt32(8), ARIndex),
Builder.getInt32(0));

llvm::Value *ARIndexCorr = Builder.CreateAdd(ARIndex, ARIndexOff);
llvm::Value *ARIndexNextCorr = Builder.CreateAdd(ARIndexNext, ARIndexOff);
Builder.CreateStore(Builder.CreateShl(ARIndexNextCorr, Builder.getInt32(2)),
ARAreaPtr);

CharUnits RegSize = CharUnits::fromQuantity(4);
OverflowArea =
Address(Builder.CreateInBoundsGEP(
CGF.Int32Ty, OverflowArea.getPointer(), ARIndexCorr),
OverflowArea.getAlignment().alignmentOfArrayElement(RegSize));
MemAddr = Builder.CreateElementBitCast(OverflowArea, DirectTy);
CGF.EmitBranch(Cont);
}

CGF.EmitBlock(Cont);

// Merge the cases with a phi.
Address Result =
emitMergePHI(CGF, RegAddr, UsingRegSaveArea, MemAddr, UsingOverflow, "");

return Result;
}

ABIArgInfo XtensaABIInfo::extendType(QualType Ty) const {
return ABIArgInfo::getExtend(Ty);
}

namespace {
class XtensaTargetCodeGenInfo : public TargetCodeGenInfo {
public:
XtensaTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
: TargetCodeGenInfo(new XtensaABIInfo(CGT)) {}
};
} // namespace

//===----------------------------------------------------------------------===//
// Driver code
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -9959,6 +10180,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
case llvm::Triple::spir:
case llvm::Triple::spir64:
return SetCGInfo(new SPIRTargetCodeGenInfo(Types));
case llvm::Triple::xtensa:
return SetCGInfo(new XtensaTargetCodeGenInfo(Types));
}
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ add_clang_library(clangDriver
ToolChains/WebAssembly.cpp
ToolChains/XCore.cpp
ToolChains/PPCLinux.cpp
ToolChains/Xtensa.cpp
ToolChains/InterfaceStubs.cpp
Types.cpp
XRayArgs.cpp
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "ToolChains/TCE.h"
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "ToolChains/Xtensa.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
Expand Down Expand Up @@ -4934,6 +4935,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::riscv64:
TC = std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
break;
case llvm::Triple::xtensa:
TC = std::make_unique<toolchains::XtensaToolChain>(*this, Target, Args);
break;
default:
if (Target.getVendor() == llvm::Triple::Myriad)
TC = std::make_unique<toolchains::MyriadToolChain>(*this, Target,
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
case llvm::Triple::xtensa:
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
return A->getValue();
return "";
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2106,6 +2106,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
"s390x-suse-linux", "s390x-redhat-linux"};

static const char *const XtensaLibDirs[] = {"/lib"};
static const char *const XtensaTriples[] = {"xtensa-unknown-elf"};

using std::begin;
using std::end;
Expand Down Expand Up @@ -2353,6 +2355,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
LibDirs.append(begin(SystemZLibDirs), end(SystemZLibDirs));
TripleAliases.append(begin(SystemZTriples), end(SystemZTriples));
break;
case llvm::Triple::xtensa:
LibDirs.append(begin(XtensaLibDirs), end(XtensaLibDirs));
TripleAliases.append(begin(XtensaTriples), end(XtensaTriples));
break;
default:
// By default, just rely on the standard lib directories and the original
// triple.
Expand Down
272 changes: 272 additions & 0 deletions clang/lib/Driver/ToolChains/Xtensa.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
//===--- Xtensa.cpp - Xtensa ToolChain Implementations ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// 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
//
//===----------------------------------------------------------------------===//

#include "Xtensa.h"
#include "CommonArgs.h"
#include "InputInfo.h"
#include "clang/Basic/Cuda.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Distro.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>

using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;

XtensaGCCToolchainDetector::XtensaGCCToolchainDetector(
const Driver &D, const llvm::Triple &HostTriple,
const llvm::opt::ArgList &Args) {
std::string InstalledDir;
InstalledDir = D.getInstalledDir();
StringRef CPUName = XtensaToolChain::GetTargetCPUVersion(Args);
std::string Dir;
std::string ToolchainName;
std::string ToolchainDir;

if (CPUName.equals("esp32"))
ToolchainName = "xtensa-esp32-elf";
else if (CPUName.equals("esp32-s2"))
ToolchainName = "xtensa-esp32s2-elf";
else if (CPUName.equals("esp8266"))
ToolchainName = "xtensa-lx106-elf";

Slash = llvm::sys::path::get_separator().str();

ToolchainDir = InstalledDir + Slash + "..";
Dir = ToolchainDir + Slash + "lib" + Slash + "gcc" + Slash + ToolchainName +
Slash;
GCCLibAndIncVersion = "";

if (D.getVFS().exists(Dir)) {
std::error_code EC;
for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Dir, EC), LE;
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef VersionText = llvm::sys::path::filename(LI->path());
auto GCCVersion = Generic_GCC::GCCVersion::Parse(VersionText);
if (GCCVersion.Major == -1)
continue;
GCCLibAndIncVersion = GCCVersion.Text;
}
if (GCCLibAndIncVersion == "")
llvm_unreachable("Unexpected Xtensa GCC toolchain version");

} else {
// Unable to find Xtensa GCC toolchain;
GCCToolchainName = "";
return;
}
GCCToolchainDir = ToolchainDir;
GCCToolchainName = ToolchainName;
}

/// Xtensa Toolchain
XtensaToolChain::XtensaToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args), XtensaGCCToolchain(D, getTriple(), Args) {
for (auto *A : Args) {
std::string Str = A->getAsString(Args);
if (!Str.compare("-mlongcalls"))
A->claim();
if (!Str.compare("-fno-tree-switch-conversion"))
A->claim();

// Currently don't use integrated assembler for assembler input files
if ((IsIntegratedAsm) && (Str.length() > 2)) {
std::string ExtSubStr = Str.substr(Str.length() - 2);
if (!ExtSubStr.compare(".s"))
IsIntegratedAsm = false;
if (!ExtSubStr.compare(".S"))
IsIntegratedAsm = false;
}
}

// Currently don't use integrated assembler for assembler input files
if (IsIntegratedAsm) {
if (Args.getLastArgValue(options::OPT_x).equals("assembler"))
IsIntegratedAsm = false;

if (Args.getLastArgValue(options::OPT_x).equals("assembler-with-cpp"))
IsIntegratedAsm = false;
}
}

Tool *XtensaToolChain::buildLinker() const {
return new tools::Xtensa::Linker(*this);
}

Tool *XtensaToolChain::buildAssembler() const {
return new tools::Xtensa::Assembler(*this);
}

void XtensaToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdlibinc))
return;

if (!XtensaGCCToolchain.IsValid())
return;

std::string Slash = XtensaGCCToolchain.Slash;

std::string Path1 = getDriver().ResourceDir.c_str() + Slash + "include";
std::string Path2 =
XtensaGCCToolchain.GCCToolchainDir + Slash + "lib" + Slash + "gcc" +
Slash + XtensaGCCToolchain.GCCToolchainName + Slash +
XtensaGCCToolchain.GCCLibAndIncVersion + Slash + "include";
std::string Path3 =
XtensaGCCToolchain.GCCToolchainDir + Slash + "lib" + Slash + "gcc" +
Slash + XtensaGCCToolchain.GCCToolchainName + Slash +
XtensaGCCToolchain.GCCLibAndIncVersion + Slash + "include-fixed";
std::string Path4 = XtensaGCCToolchain.GCCToolchainDir + Slash +
XtensaGCCToolchain.GCCToolchainName + Slash +
"sys-include";
std::string Path5 = XtensaGCCToolchain.GCCToolchainDir + Slash +
XtensaGCCToolchain.GCCToolchainName + Slash + "include";

const StringRef Paths[] = {Path1, Path2, Path3, Path4, Path5};
addSystemIncludes(DriverArgs, CC1Args, Paths);
}

void XtensaToolChain::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
if (!XtensaGCCToolchain.IsValid())
return;

std::string Slash = XtensaGCCToolchain.Slash;

std::string BaseDir = XtensaGCCToolchain.GCCToolchainDir + Slash +
XtensaGCCToolchain.GCCToolchainName + Slash +
"include" + Slash + "c++" + Slash +
XtensaGCCToolchain.GCCLibAndIncVersion;
std::string TargetDir = BaseDir + Slash + XtensaGCCToolchain.GCCToolchainName;
addLibStdCXXIncludePaths(BaseDir, "", "", "", "", "", DriverArgs, CC1Args);
addLibStdCXXIncludePaths(TargetDir, "", "", "", "", "", DriverArgs, CC1Args);
TargetDir = BaseDir + Slash + "backward";
addLibStdCXXIncludePaths(TargetDir, "", "", "", "", "", DriverArgs, CC1Args);
}

ToolChain::CXXStdlibType
XtensaToolChain::GetCXXStdlibType(const ArgList &Args) const {
Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
if (!A)
return ToolChain::CST_Libstdcxx;

StringRef Value = A->getValue();
if (Value != "libstdc++")
getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);

return ToolChain::CST_Libstdcxx;
}

const StringRef XtensaToolChain::GetTargetCPUVersion(const ArgList &Args) {
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
StringRef CPUName = A->getValue();
return CPUName;
}
return "esp32";
}

void tools::Xtensa::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
const auto &TC =
static_cast<const toolchains::XtensaToolChain &>(getToolChain());

if (!TC.XtensaGCCToolchain.IsValid())
llvm_unreachable("Unable to find Xtensa GCC assembler");

claimNoWarnArgs(Args);
ArgStringList CmdArgs;

CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());

CmdArgs.push_back("-c");

if (Args.hasArg(options::OPT_v))
CmdArgs.push_back("-v");

if (Arg *A = Args.getLastArg(options::OPT_g_Group))
if (!A->getOption().matches(options::OPT_g0))
CmdArgs.push_back("-g");

if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
false))
CmdArgs.push_back("-fverbose-asm");

Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);

for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());

std::string Slash = TC.XtensaGCCToolchain.Slash;

const char *Asm =
Args.MakeArgString(getToolChain().getDriver().Dir + Slash +
TC.XtensaGCCToolchain.GCCToolchainName + "-as");
C.addCommand(std::make_unique<Command>(JA, *this, Asm, CmdArgs, Inputs));
}

void Xtensa::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
const auto &TC =
static_cast<const toolchains::XtensaToolChain &>(getToolChain());

if (!TC.XtensaGCCToolchain.IsValid())
llvm_unreachable("Unable to find Xtensa GCC linker");

std::string Slash = TC.XtensaGCCToolchain.Slash;

std::string Linker = getToolChain().getDriver().Dir + Slash +
TC.XtensaGCCToolchain.GCCToolchainName + "-ld";
ArgStringList CmdArgs;

Args.AddAllArgs(CmdArgs,
{options::OPT_T_Group, options::OPT_e, options::OPT_s,
options::OPT_L, options::OPT_t, options::OPT_u_Group});

AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);

std::string Libs = TC.XtensaGCCToolchain.GCCToolchainDir + Slash + "lib" +
Slash + "gcc" + Slash +
TC.XtensaGCCToolchain.GCCToolchainName + Slash +
TC.XtensaGCCToolchain.GCCLibAndIncVersion + Slash;
CmdArgs.push_back("-L");
CmdArgs.push_back(Args.MakeArgString(Libs));

Libs = TC.XtensaGCCToolchain.GCCToolchainDir + Slash +
TC.XtensaGCCToolchain.GCCToolchainName + Slash + "lib" + Slash;
CmdArgs.push_back("-L");
CmdArgs.push_back(Args.MakeArgString(Libs));

CmdArgs.push_back("-v");

CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
CmdArgs, Inputs));
}

94 changes: 94 additions & 0 deletions clang/lib/Driver/ToolChains/Xtensa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//===--- Xtensa.h - Xtensa Tool and ToolChain Implementations ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Xtensa_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Xtensa_H

#include "Gnu.h"
#include "InputInfo.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace toolchains {

class XtensaGCCToolchainDetector {
public:
std::string GCCLibAndIncVersion;
std::string GCCToolchainName;
std::string GCCToolchainDir;
std::string Slash;

XtensaGCCToolchainDetector(const Driver &D, const llvm::Triple &HostTriple,
const llvm::opt::ArgList &Args);

bool IsValid() const { return GCCToolchainName != ""; }
};

class LLVM_LIBRARY_VISIBILITY XtensaToolChain : public Generic_ELF {
protected:
Tool *buildLinker() const override;
Tool *buildAssembler() const override;

public:
XtensaToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
bool IsIntegratedAssemblerDefault() const override {
return (IsIntegratedAsm || (XtensaGCCToolchain.GCCToolchainName == ""));
}

static const StringRef GetTargetCPUVersion(const llvm::opt::ArgList &Args);

XtensaGCCToolchainDetector XtensaGCCToolchain;
bool IsIntegratedAsm = true;
};

} // end namespace toolchains

namespace tools {
namespace Xtensa {
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC)
: GnuTool("Xtensa::Linker", "xtensa-esp32-elf-ld", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};

class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
Assembler(const ToolChain &TC)
: Tool("Xtensa::Assembler", "xtensa-esp32-elf-as", TC) {}

bool hasIntegratedCPP() const override { return false; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};

} // end namespace Xtensa
} // end namespace tools
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Xtensa_H
81 changes: 81 additions & 0 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (CheckPPCBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
case llvm::Triple::xtensa:
if (CheckXtensaBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
default:
break;
}
Expand Down Expand Up @@ -3483,6 +3487,83 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}

bool Sema::CheckXtensaBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
default:
return false;
case Xtensa::BI__builtin_xtensa_mul_ad_ll:
case Xtensa::BI__builtin_xtensa_mul_ad_lh:
case Xtensa::BI__builtin_xtensa_mul_ad_hl:
case Xtensa::BI__builtin_xtensa_mul_ad_hh:
case Xtensa::BI__builtin_xtensa_mula_ad_ll:
case Xtensa::BI__builtin_xtensa_mula_ad_lh:
case Xtensa::BI__builtin_xtensa_mula_ad_hl:
case Xtensa::BI__builtin_xtensa_mula_ad_hh:
case Xtensa::BI__builtin_xtensa_muls_ad_ll:
case Xtensa::BI__builtin_xtensa_muls_ad_lh:
case Xtensa::BI__builtin_xtensa_muls_ad_hl:
case Xtensa::BI__builtin_xtensa_muls_ad_hh:
i = 1;
l = 2;
u = 3;
break;
case Xtensa::BI__builtin_xtensa_mul_da_ll:
case Xtensa::BI__builtin_xtensa_mul_da_lh:
case Xtensa::BI__builtin_xtensa_mul_da_hl:
case Xtensa::BI__builtin_xtensa_mul_da_hh:
case Xtensa::BI__builtin_xtensa_mula_da_ll:
case Xtensa::BI__builtin_xtensa_mula_da_lh:
case Xtensa::BI__builtin_xtensa_mula_da_hl:
case Xtensa::BI__builtin_xtensa_mula_da_hh:
case Xtensa::BI__builtin_xtensa_muls_da_ll:
case Xtensa::BI__builtin_xtensa_muls_da_lh:
case Xtensa::BI__builtin_xtensa_muls_da_hl:
case Xtensa::BI__builtin_xtensa_muls_da_hh:
i = 0;
l = 0;
u = 1;
break;
case Xtensa::BI__builtin_xtensa_mul_dd_ll:
case Xtensa::BI__builtin_xtensa_mul_dd_lh:
case Xtensa::BI__builtin_xtensa_mul_dd_hl:
case Xtensa::BI__builtin_xtensa_mul_dd_hh:
case Xtensa::BI__builtin_xtensa_mula_dd_ll:
case Xtensa::BI__builtin_xtensa_mula_dd_lh:
case Xtensa::BI__builtin_xtensa_mula_dd_hl:
case Xtensa::BI__builtin_xtensa_mula_dd_hh:
case Xtensa::BI__builtin_xtensa_muls_dd_ll:
case Xtensa::BI__builtin_xtensa_muls_dd_lh:
case Xtensa::BI__builtin_xtensa_muls_dd_hl:
case Xtensa::BI__builtin_xtensa_muls_dd_hh:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 1) ||
SemaBuiltinConstantArgRange(TheCall, 1, 2, 3);
case Xtensa::BI__builtin_xtensa_mula_da_ll_lddec:
case Xtensa::BI__builtin_xtensa_mula_da_lh_lddec:
case Xtensa::BI__builtin_xtensa_mula_da_hl_lddec:
case Xtensa::BI__builtin_xtensa_mula_da_hh_lddec:
case Xtensa::BI__builtin_xtensa_mula_da_ll_ldinc:
case Xtensa::BI__builtin_xtensa_mula_da_lh_ldinc:
case Xtensa::BI__builtin_xtensa_mula_da_hl_ldinc:
case Xtensa::BI__builtin_xtensa_mula_da_hh_ldinc:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 3) ||
SemaBuiltinConstantArgRange(TheCall, 2, 0, 1);
case Xtensa::BI__builtin_xtensa_mula_dd_ll_lddec:
case Xtensa::BI__builtin_xtensa_mula_dd_lh_lddec:
case Xtensa::BI__builtin_xtensa_mula_dd_hl_lddec:
case Xtensa::BI__builtin_xtensa_mula_dd_hh_lddec:
case Xtensa::BI__builtin_xtensa_mula_dd_ll_ldinc:
case Xtensa::BI__builtin_xtensa_mula_dd_lh_ldinc:
case Xtensa::BI__builtin_xtensa_mula_dd_hl_ldinc:
case Xtensa::BI__builtin_xtensa_mula_dd_hh_ldinc:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 3) ||
SemaBuiltinConstantArgRange(TheCall, 2, 0, 1) ||
SemaBuiltinConstantArgRange(TheCall, 3, 2, 3);
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}

/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *).
/// This checks that the target supports __builtin_cpu_supports and
/// that the string argument is constant and valid.
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/ADT/Triple.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class Triple {
x86, // X86: i[3-9]86
x86_64, // X86-64: amd64, x86_64
xcore, // XCore: xcore
xtensa, // Tensilica Xtensa
nvptx, // NVPTX: 32-bit
nvptx64, // NVPTX: 64-bit
le32, // le32: generic little-endian 32-bit CPU (PNaCl)
Expand Down
15 changes: 15 additions & 0 deletions llvm/include/llvm/BinaryFormat/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,21 @@ enum {
#include "ELFRelocs/MSP430.def"
};

// Xtensa specific e_flags
enum : unsigned {
// Four-bit Xtensa machine type mask.
EF_XTENSA_MACH = 0x0000000f,
// Various CPU types.
EF_XTENSA_MACH_NONE = 0x00000000, //A base Xtensa implementation
EF_XTENSA_XT_INSN = 0x00000100,
EF_XTENSA_XT_LIT = 0x00000200,
};

// ELF Relocation types for Xtensa
enum {
#include "ELFRelocs/Xtensa.def"
};

#undef ELF_RELOC

// Section header.
Expand Down
59 changes: 59 additions & 0 deletions llvm/include/llvm/BinaryFormat/ELFRelocs/Xtensa.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#ifndef ELF_RELOC
#error "ELF_RELOC must be defined"
#endif

ELF_RELOC (R_XTENSA_NONE, 0)
ELF_RELOC (R_XTENSA_32, 1)
ELF_RELOC (R_XTENSA_RTLD, 2)
ELF_RELOC (R_XTENSA_GLOB_DAT, 3)
ELF_RELOC (R_XTENSA_JMP_SLOT, 4)
ELF_RELOC (R_XTENSA_RELATIVE, 5)
ELF_RELOC (R_XTENSA_PLT, 6)
ELF_RELOC (R_XTENSA_OP0, 8)
ELF_RELOC (R_XTENSA_OP1, 9)
ELF_RELOC (R_XTENSA_OP2, 10)
ELF_RELOC (R_XTENSA_ASM_EXPAND, 11)
ELF_RELOC (R_XTENSA_ASM_SIMPLIFY, 12)
ELF_RELOC (R_XTENSA_32_PCREL, 14)
ELF_RELOC (R_XTENSA_GNU_VTINHERIT, 15)
ELF_RELOC (R_XTENSA_GNU_VTENTRY, 16)
ELF_RELOC (R_XTENSA_DIFF8, 17)
ELF_RELOC (R_XTENSA_DIFF16, 18)
ELF_RELOC (R_XTENSA_DIFF32, 19)
ELF_RELOC (R_XTENSA_SLOT0_OP, 20)
ELF_RELOC (R_XTENSA_SLOT1_OP, 21)
ELF_RELOC (R_XTENSA_SLOT2_OP, 22)
ELF_RELOC (R_XTENSA_SLOT3_OP, 23)
ELF_RELOC (R_XTENSA_SLOT4_OP, 24)
ELF_RELOC (R_XTENSA_SLOT5_OP, 25)
ELF_RELOC (R_XTENSA_SLOT6_OP, 26)
ELF_RELOC (R_XTENSA_SLOT7_OP, 27)
ELF_RELOC (R_XTENSA_SLOT8_OP, 28)
ELF_RELOC (R_XTENSA_SLOT9_OP, 29)
ELF_RELOC (R_XTENSA_SLOT10_OP, 30)
ELF_RELOC (R_XTENSA_SLOT11_OP, 31)
ELF_RELOC (R_XTENSA_SLOT12_OP, 32)
ELF_RELOC (R_XTENSA_SLOT13_OP, 33)
ELF_RELOC (R_XTENSA_SLOT14_OP, 34)
ELF_RELOC (R_XTENSA_SLOT0_ALT, 35)
ELF_RELOC (R_XTENSA_SLOT1_ALT, 36)
ELF_RELOC (R_XTENSA_SLOT2_ALT, 37)
ELF_RELOC (R_XTENSA_SLOT3_ALT, 38)
ELF_RELOC (R_XTENSA_SLOT4_ALT, 39)
ELF_RELOC (R_XTENSA_SLOT5_ALT, 40)
ELF_RELOC (R_XTENSA_SLOT6_ALT, 41)
ELF_RELOC (R_XTENSA_SLOT7_ALT, 42)
ELF_RELOC (R_XTENSA_SLOT8_ALT, 43)
ELF_RELOC (R_XTENSA_SLOT9_ALT, 44)
ELF_RELOC (R_XTENSA_SLOT10_ALT, 45)
ELF_RELOC (R_XTENSA_SLOT11_ALT, 46)
ELF_RELOC (R_XTENSA_SLOT12_ALT, 47)
ELF_RELOC (R_XTENSA_SLOT13_ALT, 48)
ELF_RELOC (R_XTENSA_SLOT14_ALT, 49)
ELF_RELOC (R_XTENSA_TLSDESC_FN, 50)
ELF_RELOC (R_XTENSA_TLSDESC_ARG, 51)
ELF_RELOC (R_XTENSA_TLS_DTPOFF, 52)
ELF_RELOC (R_XTENSA_TLS_TPOFF, 53)
ELF_RELOC (R_XTENSA_TLS_FUNC, 54)
ELF_RELOC (R_XTENSA_TLS_ARG, 55)
ELF_RELOC (R_XTENSA_TLS_CALL, 56)
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ tablegen(LLVM IntrinsicsS390.h -gen-intrinsic-enums -intrinsic-prefix=s390)
tablegen(LLVM IntrinsicsWebAssembly.h -gen-intrinsic-enums -intrinsic-prefix=wasm)
tablegen(LLVM IntrinsicsX86.h -gen-intrinsic-enums -intrinsic-prefix=x86)
tablegen(LLVM IntrinsicsXCore.h -gen-intrinsic-enums -intrinsic-prefix=xcore)
tablegen(LLVM IntrinsicsXtensa.h -gen-intrinsic-enums -intrinsic-prefix=xtensa)
add_public_tablegen_target(intrinsics_gen)
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -1358,3 +1358,4 @@ include "llvm/IR/IntrinsicsBPF.td"
include "llvm/IR/IntrinsicsSystemZ.td"
include "llvm/IR/IntrinsicsWebAssembly.td"
include "llvm/IR/IntrinsicsRISCV.td"
include "llvm/IR/IntrinsicsXtensa.td"
251 changes: 251 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsXtensa.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
//===- IntrinsicsXtensa.td - Defines Xtensa intrinsics -----*- tablegen -*-===//
//
// 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 defines all of the Xtensa-specific intrinsics.
//
//===----------------------------------------------------------------------===//

let TargetPrefix = "xtensa" in { // All intrinsics start with "llvm.xtensa.".

def int_xtensa_umul_aa_ll: GCCBuiltin<"__builtin_xtensa_umul_aa_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_umul_aa_hl: GCCBuiltin<"__builtin_xtensa_umul_aa_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_umul_aa_lh: GCCBuiltin<"__builtin_xtensa_umul_aa_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_umul_aa_hh: GCCBuiltin<"__builtin_xtensa_umul_aa_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;

def int_xtensa_mul_aa_ll: GCCBuiltin<"__builtin_xtensa_mul_aa_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_mul_aa_hl: GCCBuiltin<"__builtin_xtensa_mul_aa_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_mul_aa_lh: GCCBuiltin<"__builtin_xtensa_mul_aa_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_mul_aa_hh: GCCBuiltin<"__builtin_xtensa_mul_aa_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;

def int_xtensa_mul_ad_ll: GCCBuiltin<"__builtin_xtensa_mul_ad_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;
def int_xtensa_mul_ad_hl: GCCBuiltin<"__builtin_xtensa_mul_ad_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;
def int_xtensa_mul_ad_lh: GCCBuiltin<"__builtin_xtensa_mul_ad_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;
def int_xtensa_mul_ad_hh: GCCBuiltin<"__builtin_xtensa_mul_ad_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;

def int_xtensa_mul_da_ll: GCCBuiltin<"__builtin_xtensa_mul_da_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;
def int_xtensa_mul_da_hl: GCCBuiltin<"__builtin_xtensa_mul_da_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;
def int_xtensa_mul_da_lh: GCCBuiltin<"__builtin_xtensa_mul_da_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;
def int_xtensa_mul_da_hh: GCCBuiltin<"__builtin_xtensa_mul_da_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;

def int_xtensa_mul_dd_ll: GCCBuiltin<"__builtin_xtensa_mul_dd_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;
def int_xtensa_mul_dd_hl: GCCBuiltin<"__builtin_xtensa_mul_dd_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;
def int_xtensa_mul_dd_lh: GCCBuiltin<"__builtin_xtensa_mul_dd_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;
def int_xtensa_mul_dd_hh: GCCBuiltin<"__builtin_xtensa_mul_dd_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;

def int_xtensa_mula_aa_ll: GCCBuiltin<"__builtin_xtensa_mula_aa_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_mula_aa_hl: GCCBuiltin<"__builtin_xtensa_mula_aa_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_mula_aa_lh: GCCBuiltin<"__builtin_xtensa_mula_aa_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_mula_aa_hh: GCCBuiltin<"__builtin_xtensa_mula_aa_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;

def int_xtensa_mula_ad_ll: GCCBuiltin<"__builtin_xtensa_mula_ad_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;
def int_xtensa_mula_ad_hl: GCCBuiltin<"__builtin_xtensa_mula_ad_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;
def int_xtensa_mula_ad_lh: GCCBuiltin<"__builtin_xtensa_mula_ad_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;
def int_xtensa_mula_ad_hh: GCCBuiltin<"__builtin_xtensa_mula_ad_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;

def int_xtensa_mula_da_ll: GCCBuiltin<"__builtin_xtensa_mula_da_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;
def int_xtensa_mula_da_hl: GCCBuiltin<"__builtin_xtensa_mula_da_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;
def int_xtensa_mula_da_lh: GCCBuiltin<"__builtin_xtensa_mula_da_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;
def int_xtensa_mula_da_hh: GCCBuiltin<"__builtin_xtensa_mula_da_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;

def int_xtensa_mula_dd_ll: GCCBuiltin<"__builtin_xtensa_mula_dd_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;
def int_xtensa_mula_dd_hl: GCCBuiltin<"__builtin_xtensa_mula_dd_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;
def int_xtensa_mula_dd_lh: GCCBuiltin<"__builtin_xtensa_mula_dd_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;
def int_xtensa_mula_dd_hh: GCCBuiltin<"__builtin_xtensa_mula_dd_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;

def int_xtensa_muls_aa_ll: GCCBuiltin<"__builtin_xtensa_muls_aa_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_muls_aa_hl: GCCBuiltin<"__builtin_xtensa_muls_aa_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_muls_aa_lh: GCCBuiltin<"__builtin_xtensa_muls_aa_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
def int_xtensa_muls_aa_hh: GCCBuiltin<"__builtin_xtensa_muls_aa_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;

def int_xtensa_muls_ad_ll: GCCBuiltin<"__builtin_xtensa_muls_ad_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;
def int_xtensa_muls_ad_hl: GCCBuiltin<"__builtin_xtensa_muls_ad_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;
def int_xtensa_muls_ad_lh: GCCBuiltin<"__builtin_xtensa_muls_ad_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;
def int_xtensa_muls_ad_hh: GCCBuiltin<"__builtin_xtensa_muls_ad_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>;

def int_xtensa_muls_da_ll: GCCBuiltin<"__builtin_xtensa_muls_da_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;
def int_xtensa_muls_da_hl: GCCBuiltin<"__builtin_xtensa_muls_da_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;
def int_xtensa_muls_da_lh: GCCBuiltin<"__builtin_xtensa_muls_da_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;
def int_xtensa_muls_da_hh: GCCBuiltin<"__builtin_xtensa_muls_da_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>;

def int_xtensa_muls_dd_ll: GCCBuiltin<"__builtin_xtensa_muls_dd_ll">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;
def int_xtensa_muls_dd_hl: GCCBuiltin<"__builtin_xtensa_muls_dd_hl">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;
def int_xtensa_muls_dd_lh: GCCBuiltin<"__builtin_xtensa_muls_dd_lh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;
def int_xtensa_muls_dd_hh: GCCBuiltin<"__builtin_xtensa_muls_dd_hh">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>]>;


def int_xtensa_mula_da_ll_lddec: GCCBuiltin<"__builtin_xtensa_mula_da_ll_lddec">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>]>;
def int_xtensa_mula_da_lh_lddec: GCCBuiltin<"__builtin_xtensa_mula_da_lh_lddec">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>]>;
def int_xtensa_mula_da_hl_lddec: GCCBuiltin<"__builtin_xtensa_mula_da_hl_lddec">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>]>;
def int_xtensa_mula_da_hh_lddec: GCCBuiltin<"__builtin_xtensa_mula_da_hh_lddec">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>]>;

def int_xtensa_mula_da_ll_ldinc: GCCBuiltin<"__builtin_xtensa_mula_da_ll_ldinc">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>]>;
def int_xtensa_mula_da_lh_ldinc: GCCBuiltin<"__builtin_xtensa_mula_da_lh_ldinc">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>]>;
def int_xtensa_mula_da_hl_ldinc: GCCBuiltin<"__builtin_xtensa_mula_da_hl_ldinc">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>]>;
def int_xtensa_mula_da_hh_ldinc: GCCBuiltin<"__builtin_xtensa_mula_da_hh_ldinc">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>]>;

def int_xtensa_mula_dd_ll_lddec: GCCBuiltin<"__builtin_xtensa_mula_dd_ll_lddec">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>, ImmArg<3>]>;
def int_xtensa_mula_dd_lh_lddec: GCCBuiltin<"__builtin_xtensa_mula_dd_lh_lddec">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>, ImmArg<3>]>;
def int_xtensa_mula_dd_hl_lddec: GCCBuiltin<"__builtin_xtensa_mula_dd_hl_lddec">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>, ImmArg<3>]>;
def int_xtensa_mula_dd_hh_lddec: GCCBuiltin<"__builtin_xtensa_mula_dd_hh_lddec">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>, ImmArg<3>]>;

def int_xtensa_mula_dd_ll_ldinc: GCCBuiltin<"__builtin_xtensa_mula_dd_ll_ldinc">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>, ImmArg<3>]>;
def int_xtensa_mula_dd_lh_ldinc: GCCBuiltin<"__builtin_xtensa_mula_dd_lh_ldinc">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>, ImmArg<3>]>;
def int_xtensa_mula_dd_hl_ldinc: GCCBuiltin<"__builtin_xtensa_mula_dd_hl_ldinc">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>, ImmArg<3>]>;
def int_xtensa_mula_dd_hh_ldinc: GCCBuiltin<"__builtin_xtensa_mula_dd_hh_ldinc">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
[ImmArg<0>, ImmArg<2>, ImmArg<3>]>;

//===----------------------------------------------------------------------===//
// Load operations

def int_xtensa_lddec: GCCBuiltin<"__builtin_xtensa_lddec">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>]>;

def int_xtensa_ldinc: GCCBuiltin<"__builtin_xtensa_ldinc">,
Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>]>;

//===----------------------------------------------------------------------===//
// WSR/XSR/RSR

def int_xtensa_wsr_acclo: GCCBuiltin<"__builtin_xtensa_wsr_acclo">,
Intrinsic<[], [llvm_i32_ty], []>;

def int_xtensa_rsr_acclo: GCCBuiltin<"__builtin_xtensa_rsr_acclo">,
Intrinsic<[llvm_i32_ty], [], []>;

def int_xtensa_xsr_acclo: GCCBuiltin<"__builtin_xtensa_xsr_acclo">,
Intrinsic<[], [llvm_ptr_ty], []>;

def int_xtensa_wsr_acchi: GCCBuiltin<"__builtin_xtensa_wsr_acchi">,
Intrinsic<[], [llvm_i32_ty], []>;

def int_xtensa_rsr_acchi: GCCBuiltin<"__builtin_xtensa_rsr_acchi">,
Intrinsic<[llvm_i32_ty], [], []>;

def int_xtensa_xsr_acchi: GCCBuiltin<"__builtin_xtensa_xsr_acchi">,
Intrinsic<[], [llvm_ptr_ty], []>;

def int_xtensa_wsr_m0: GCCBuiltin<"__builtin_xtensa_wsr_m0">,
Intrinsic<[], [llvm_i32_ty], []>;

def int_xtensa_rsr_m0: GCCBuiltin<"__builtin_xtensa_rsr_m0">,
Intrinsic<[llvm_i32_ty]>;

def int_xtensa_xsr_m0: GCCBuiltin<"__builtin_xtensa_xsr_m0">,
Intrinsic<[], [llvm_ptr_ty], []>;

def int_xtensa_wsr_m1: GCCBuiltin<"__builtin_xtensa_wsr_m1">,
Intrinsic<[], [llvm_i32_ty], []>;

def int_xtensa_rsr_m1: GCCBuiltin<"__builtin_xtensa_rsr_m1">,
Intrinsic<[llvm_i32_ty], [], []>;

def int_xtensa_xsr_m1: GCCBuiltin<"__builtin_xtensa_xsr_m1">,
Intrinsic<[], [llvm_ptr_ty], []>;

def int_xtensa_wsr_m2: GCCBuiltin<"__builtin_xtensa_wsr_m2">,
Intrinsic<[], [llvm_i32_ty], []>;

def int_xtensa_rsr_m2: GCCBuiltin<"__builtin_xtensa_rsr_m2">,
Intrinsic<[llvm_i32_ty], [], []>;

def int_xtensa_xsr_m2: GCCBuiltin<"__builtin_xtensa_xsr_m2">,
Intrinsic<[], [llvm_ptr_ty], []>;

def int_xtensa_wsr_m3: GCCBuiltin<"__builtin_xtensa_wsr_m3">,
Intrinsic<[], [llvm_i32_ty], []>;

def int_xtensa_rsr_m3: GCCBuiltin<"__builtin_xtensa_rsr_m3">,
Intrinsic<[llvm_i32_ty], [], []>;

def int_xtensa_xsr_m3: GCCBuiltin<"__builtin_xtensa_xsr_m3">,
Intrinsic<[], [llvm_ptr_ty], []>;

}
5 changes: 4 additions & 1 deletion llvm/include/llvm/Object/ELFObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "ELF32-sparc";
case ELF::EM_AMDGPU:
return "ELF32-amdgpu";
case ELF::EM_XTENSA:
return "ELF32-Xtensa";
default:
return "ELF32-unknown";
}
Expand Down Expand Up @@ -1187,7 +1189,8 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {

case ELF::EM_BPF:
return IsLittleEndian ? Triple::bpfel : Triple::bpfeb;

case ELF::EM_XTENSA:
return Triple::xtensa;
default:
return Triple::UnknownArch;
}
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ module LLVM_BinaryFormat {
textual header "BinaryFormat/ELFRelocs/Sparc.def"
textual header "BinaryFormat/ELFRelocs/SystemZ.def"
textual header "BinaryFormat/ELFRelocs/x86_64.def"
textual header "BinaryFormat/ELFRelocs/Xtensa.def"
textual header "BinaryFormat/WasmRelocs.def"
textual header "BinaryFormat/MsgPack.def"
}
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/IR/IntrinsicsX86.h"
#include "llvm/IR/IntrinsicsXCore.h"
#include "llvm/IR/IntrinsicsXtensa.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/MC/MCObjectFileInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
FDECFIEncoding =
PositionIndependent ? dwarf::DW_EH_PE_pcrel : dwarf::DW_EH_PE_absptr;
break;
case Triple::xtensa:
FDECFIEncoding = dwarf::DW_EH_PE_sdata4;
break;
default:
FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
break;
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Object/ELF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine,
break;
}
break;
case ELF::EM_XTENSA:
switch (Type) {
#include "llvm/BinaryFormat/ELFRelocs/Xtensa.def"
default:
break;
}
break;
default:
break;
}
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/ObjectYAML/ELFYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO,
break;
case ELF::EM_X86_64:
break;
case ELF::EM_XTENSA:
BCase(EF_XTENSA_XT_INSN);
BCaseMask(EF_XTENSA_MACH_NONE, EF_XTENSA_MACH);
BCase(EF_XTENSA_XT_LIT);
break;
default:
llvm_unreachable("Unsupported architecture");
}
Expand Down Expand Up @@ -657,6 +662,9 @@ void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration(
case ELF::EM_PPC64:
#include "llvm/BinaryFormat/ELFRelocs/PowerPC64.def"
break;
case ELF::EM_XTENSA:
#include "llvm/BinaryFormat/ELFRelocs/Xtensa.def"
break;
default:
// Nothing to do.
break;
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Support/Triple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
case x86: return "i386";
case x86_64: return "x86_64";
case xcore: return "xcore";
case xtensa: return "xtensa";
}

llvm_unreachable("Invalid ArchType!");
Expand Down Expand Up @@ -147,6 +148,8 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) {
case riscv64: return "riscv";

case ve: return "ve";

case xtensa: return "xtensa";
}
}

Expand Down Expand Up @@ -317,6 +320,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("renderscript32", renderscript32)
.Case("renderscript64", renderscript64)
.Case("ve", ve)
.Case("xtensa", xtensa)
.Default(UnknownArch);
}

Expand Down Expand Up @@ -446,6 +450,7 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("ve", Triple::ve)
.Case("wasm32", Triple::wasm32)
.Case("wasm64", Triple::wasm64)
.Case("xtensa", Triple::xtensa)
.Default(Triple::UnknownArch);

// Some architectures require special parsing logic just to compute the
Expand Down Expand Up @@ -706,6 +711,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::thumbeb:
case Triple::ve:
case Triple::xcore:
case Triple::xtensa:
return Triple::ELF;

case Triple::ppc64:
Expand Down Expand Up @@ -1267,6 +1273,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::wasm32:
case llvm::Triple::x86:
case llvm::Triple::xcore:
case llvm::Triple::xtensa:
return 32;

case llvm::Triple::aarch64:
Expand Down Expand Up @@ -1350,6 +1357,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::wasm32:
case Triple::x86:
case Triple::xcore:
case Triple::xtensa:
// Already 32-bit.
break;

Expand Down Expand Up @@ -1388,6 +1396,7 @@ Triple Triple::get64BitArchVariant() const {
case Triple::tce:
case Triple::tcele:
case Triple::xcore:
case Triple::xtensa:
T.setArch(UnknownArch);
break;

Expand Down Expand Up @@ -1471,6 +1480,7 @@ Triple Triple::getBigEndianArchVariant() const {
case Triple::x86_64:
case Triple::xcore:
case Triple::ve:
case Triple::xtensa:

// ARM is intentionally unsupported here, changing the architecture would
// drop any arch suffixes.
Expand Down Expand Up @@ -1563,6 +1573,7 @@ bool Triple::isLittleEndian() const {
case Triple::x86:
case Triple::x86_64:
case Triple::xcore:
case Triple::xtensa:
return true;
default:
return false;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/LLVMBuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ subdirectories =
WebAssembly
X86
XCore
Xtensa
VE

; This is a special group whose required libraries are extended (by llvm-build)
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/Xtensa/AsmParser/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )

add_llvm_component_library(LLVMXtensaAsmParser
XtensaAsmParser.cpp
)

add_dependencies(LLVMXtensaAsmParser XtensaCommonTableGen)
22 changes: 22 additions & 0 deletions llvm/lib/Target/Xtensa/AsmParser/LLVMBuild.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
;===- ./lib/Target/AsmParser/LLVMBuild.txt --------------------*- Conf -*--===;
;
; 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 is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[component_0]
type = Library
name = XtensaAsmParser
parent = Xtensa
required_libraries = XtensaDesc XtensaInfo MC MCParser Support
add_to_library_groups = Xtensa
1,079 changes: 1,079 additions & 0 deletions llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions llvm/lib/Target/Xtensa/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
set(LLVM_TARGET_DEFINITIONS Xtensa.td)

tablegen(LLVM XtensaGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM XtensaGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM XtensaGenCallingConv.inc -gen-callingconv)
tablegen(LLVM XtensaGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM XtensaGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM XtensaGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM XtensaGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM XtensaGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM XtensaGenSubtargetInfo.inc -gen-subtarget)

add_public_tablegen_target(XtensaCommonTableGen)

add_llvm_target(XtensaCodeGen
XtensaAsmPrinter.cpp
XtensaConstantPoolValue.cpp
XtensaFrameLowering.cpp
XtensaInstrInfo.cpp
XtensaISelDAGToDAG.cpp
XtensaISelLowering.cpp
XtensaMachineFunctionInfo.cpp
XtensaMCInstLower.cpp
XtensaRegisterInfo.cpp
XtensaSizeReductionPass.cpp
XtensaSubtarget.cpp
XtensaTargetMachine.cpp
)

add_subdirectory(AsmParser)
add_subdirectory(Disassembler)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)

3 changes: 3 additions & 0 deletions llvm/lib/Target/Xtensa/Disassembler/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
add_llvm_component_library(LLVMXtensaDisassembler
XtensaDisassembler.cpp
)
24 changes: 24 additions & 0 deletions llvm/lib/Target/Xtensa/Disassembler/LLVMBuild.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
;===-- ./lib/Target/Xtensa/Disassembler/LLVMBuild.txt ---------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; 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 is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[component_0]
type = Library
name = XtensaDisassembler
parent = Xtensa
required_libraries = MCDisassembler Support XtensaInfo
add_to_library_groups = Xtensa
682 changes: 682 additions & 0 deletions llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions llvm/lib/Target/Xtensa/LLVMBuild.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
;===- ./lib/Target/Xtensa/LLVMBuild.txt ------------------------*- Conf -*--===;
;
; 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 is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[common]
subdirectories = AsmParser Disassembler TargetInfo MCTargetDesc

[component_0]
type = TargetGroup
name = Xtensa
parent = Target
has_asmparser = 1
has_asmprinter = 1
has_disassembler = 1

[component_1]
type = Library
name = XtensaCodeGen
parent = Xtensa
required_libraries = AsmPrinter CodeGen Core MC SelectionDAG XtensaDesc XtensaInfo Support Target
add_to_library_groups = Xtensa
10 changes: 10 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_llvm_component_library(LLVMXtensaDesc
XtensaAsmBackend.cpp
XtensaELFObjectWriter.cpp
XtensaInstPrinter.cpp
XtensaMCAsmInfo.cpp
XtensaMCCodeEmitter.cpp
XtensaMCExpr.cpp
XtensaMCTargetDesc.cpp
XtensaTargetStreamer.cpp
)
22 changes: 22 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/LLVMBuild.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
;===- ./lib/Target/MCTargetDesc/LLVMBuild.txt ------------------*- Conf -*--===;
;
; 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 is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[component_0]
type = Library
name = XtensaDesc
parent = Xtensa
required_libraries = MC XtensaInfo Support
add_to_library_groups = Xtensa
221 changes: 221 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
//===-- XtensaMCAsmBackend.cpp - Xtensa assembler backend ---------------===//
//
// The LLVM Compiler Infrastructure
//
// 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
//
//===--------------------------------------------------------------------===//

#include "MCTargetDesc/XtensaFixupKinds.h"
#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace llvm {
class MCObjectTargetWriter;
class XtensaMCAsmBackend : public MCAsmBackend {
uint8_t OSABI;
bool IsLittleEndian;

public:
XtensaMCAsmBackend(uint8_t osABI, bool isLE)
: MCAsmBackend(support::little), OSABI(osABI), IsLittleEndian(isLE) {}

unsigned getNumFixupKinds() const override {
return Xtensa::NumTargetFixupKinds;
}
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsResolved,
const MCSubtargetInfo *STI) const override;
bool mayNeedRelaxation(const MCInst &Inst,
const MCSubtargetInfo &STI) const override;
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
const MCRelaxableFragment *Fragment,
const MCAsmLayout &Layout) const override;
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
MCInst &Res) const override;
bool writeNopData(raw_ostream &OS, uint64_t Count) const override;

std::unique_ptr<MCObjectTargetWriter> createObjectTargetWriter() const {
return createXtensaObjectWriter(OSABI, IsLittleEndian);
}
};
} // namespace llvm

const MCFixupKindInfo &
XtensaMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[Xtensa::NumTargetFixupKinds] = {
// name offset bits flags
{"fixup_xtensa_branch_6", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_xtensa_branch_8", 16, 8, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_xtensa_branch_12", 12, 12, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_xtensa_jump_18", 6, 18, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_xtensa_call_18", 6, 18,
MCFixupKindInfo::FKF_IsPCRel |
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
{"fixup_xtensa_l32r_16", 8, 16,
MCFixupKindInfo::FKF_IsPCRel |
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}};

if (Kind < FirstTargetFixupKind)
return MCAsmBackend::getFixupKindInfo(Kind);
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
"Invalid kind!");
return Infos[Kind - FirstTargetFixupKind];
}

static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
MCContext &Ctx) {
unsigned Kind = Fixup.getKind();
switch (Kind) {
default:
llvm_unreachable("Unknown fixup kind!");
case FK_Data_1:
case FK_Data_2:
case FK_Data_4:
case FK_Data_8:
return Value;
case Xtensa::fixup_xtensa_branch_6: {
Value -= 4;
if (!isInt<6>(Value))
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
unsigned Hi2 = (Value >> 4) & 0x3;
unsigned Lo4 = (Value)&0xf;
return (Hi2 << 4) | (Lo4 << 12);
}
case Xtensa::fixup_xtensa_branch_8:
Value -= 4;
if (!isInt<8>(Value))
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
return (Value & 0xff);
case Xtensa::fixup_xtensa_branch_12:
Value -= 4;
if (!isInt<12>(Value))
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
return (Value & 0xfff);
case Xtensa::fixup_xtensa_jump_18:
Value -= 4;
if (!isInt<18>(Value))
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
return (Value & 0x3ffff);
case Xtensa::fixup_xtensa_call_18:
Value -= 4;
if (!isInt<20>(Value))
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
if (Value & 0x3)
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
return (Value & 0xffffc) >> 2;
case Xtensa::fixup_xtensa_l32r_16:
unsigned Offset = Fixup.getOffset();
if (Offset & 0x3)
Value -= 4;
if (!isInt<18>(Value) && (Value & 0x20000))
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
if (Value & 0x3)
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
return (Value & 0x3fffc) >> 2;
}
}

static unsigned getSize(unsigned Kind) {
switch (Kind) {
default:
return 3;
case MCFixupKind::FK_Data_4:
return 4;
case Xtensa::fixup_xtensa_branch_6:
return 2;
}
}

void XtensaMCAsmBackend::applyFixup(const MCAssembler &Asm,
const MCFixup &Fixup, const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved,
const MCSubtargetInfo *STI) const {
MCContext &Ctx = Asm.getContext();
MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());

Value = adjustFixupValue(Fixup, Value, Ctx);

// Shift the value into position.
Value <<= Info.TargetOffset;

if (!Value)
return; // Doesn't change encoding.

unsigned Offset = Fixup.getOffset();
unsigned FullSize = getSize(Fixup.getKind());

for (unsigned i = 0; i != FullSize; ++i) {
Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
}
}

bool XtensaMCAsmBackend::mayNeedRelaxation(const MCInst &Inst,
const MCSubtargetInfo &STI) const {
return false;
}

bool XtensaMCAsmBackend::fixupNeedsRelaxation(
const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *Fragment,
const MCAsmLayout &Layout) const {
return false;
}

void XtensaMCAsmBackend::relaxInstruction(const MCInst &Inst,
const MCSubtargetInfo &STI,
MCInst &Res) const {}

bool XtensaMCAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
uint64_t NumNops24b = Count / 3;

for (uint64_t i = 0; i != NumNops24b; ++i) {
// Currently just little-endian machine supported,
// but probably big-endian will be also implemented in future
if (IsLittleEndian) {
OS.write("\xf0", 1);
OS.write("\x20", 1);
OS.write("\0x00", 1);
} else {
llvm_unreachable("Big-endian mode currently is not supported!");
}
Count -= 3;
}

// TODO maybe function should return error if (Count > 0)
switch (Count) {
default:
break;
case 1:
OS.write("\0", 1);
break;
case 2:
OS.write("\0\0", 2);
break;
}

return true;
}

MCAsmBackend *llvm::createXtensaMCAsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options) {
uint8_t OSABI =
MCELFObjectTargetWriter::getOSABI(STI.getTargetTriple().getOS());
return new llvm::XtensaMCAsmBackend(OSABI, true);
}
70 changes: 70 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//===-- XtensaMCObjectWriter.cpp - Xtensa ELF writer ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// 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
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <cstdint>

using namespace llvm;

namespace {
class XtensaObjectWriter : public MCELFObjectTargetWriter {
public:
XtensaObjectWriter(uint8_t OSABI);

virtual ~XtensaObjectWriter();

protected:
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup, bool IsPCRel) const override;
bool needsRelocateWithSymbol(const MCSymbol &Sym,
unsigned Type) const override;
};
} // namespace

XtensaObjectWriter::XtensaObjectWriter(uint8_t OSABI)
: MCELFObjectTargetWriter(false, OSABI, ELF::EM_XTENSA,
/*HasRelocationAddend=*/true) {}

XtensaObjectWriter::~XtensaObjectWriter() {}

unsigned XtensaObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel) const {
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();

switch ((unsigned)Fixup.getKind()) {
case FK_Data_4:
if (Modifier == MCSymbolRefExpr::VariantKind::VK_TPOFF)
return ELF::R_XTENSA_TLS_TPOFF;
else
return ELF::R_XTENSA_32;
default:
return ELF::R_XTENSA_SLOT0_OP;
}
}

std::unique_ptr<MCObjectTargetWriter>
llvm::createXtensaObjectWriter(uint8_t OSABI, bool IsLittleEndian) {
return std::make_unique<XtensaObjectWriter>(OSABI);
}

bool XtensaObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
unsigned Type) const {
return false;
}
32 changes: 32 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaFixupKinds.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===-- XtensaMCFixups.h - Xtensa-specific fixup entries --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAMCFIXUPS_H
#define LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAMCFIXUPS_H

#include "llvm/MC/MCFixup.h"

namespace llvm {
namespace Xtensa {
enum FixupKind {
fixup_xtensa_branch_6 = FirstTargetFixupKind,
fixup_xtensa_branch_8,
fixup_xtensa_branch_12,
fixup_xtensa_jump_18,
fixup_xtensa_call_18,
fixup_xtensa_l32r_16,
fixup_xtensa_invalid,
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
};
} // end namespace Xtensa
} // end namespace llvm

#endif /* LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAMCFIXUPS_H */
423 changes: 423 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//===- XtensaInstPrinter.h - Convert Xtensa MCInst to asm syntax -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// 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 class prints an Xtensa MCInst to a .s file.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAINSTPRINTER_H
#define LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAINSTPRINTER_H

#include "llvm/MC/MCInstPrinter.h"
#include "llvm/Support/Compiler.h"

namespace llvm {
class MCOperand;

class XtensaInstPrinter : public MCInstPrinter {
public:
XtensaInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI)
: MCInstPrinter(MAI, MII, MRI) {}

// Automatically generated by tblgen.
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo);

// Print the given operand.
static void printOperand(const MCOperand &MO, raw_ostream &O);

// Print an address
static void printAddress(unsigned Base, int64_t Disp, raw_ostream &O);

// Override MCInstPrinter.
void printRegName(raw_ostream &O, unsigned RegNo) const override;
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &O) override;

private:
// Print various types of operand.
void printOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printMemOperand(const MCInst *MI, int OpNUm, raw_ostream &O);
void printBranchTarget(const MCInst *MI, int OpNum, raw_ostream &O);
void printJumpTarget(const MCInst *MI, int OpNum, raw_ostream &O);
void printCallOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printL32RTarget(const MCInst *MI, int OpNum, raw_ostream &O);

void printImm8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm12_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm12m_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printUimm4_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printUimm5_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printShimm1_31_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm1_16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm1n_15_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm32n_95_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm8n_7_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset8m8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset8m16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset8m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset4m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printB4const_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printB4constu_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printSeimm7_22_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
};
} // end namespace llvm

#endif /* LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAINSTPRINTER_H */
32 changes: 32 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===-- XtensaMCAsmInfo.cpp - Xtensa Asm Properties -----------------------===//
//
// The LLVM Compiler Infrastructure
//
// 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 contains the declarations of the XtensaMCAsmInfo properties.
//
//===----------------------------------------------------------------------===//

#include "XtensaMCAsmInfo.h"
#include "llvm/ADT/Triple.h"

using namespace llvm;

XtensaMCAsmInfo::XtensaMCAsmInfo(const Triple &TT) {
CodePointerSize = 4;
CalleeSaveStackSlotSize = 4;
PrivateGlobalPrefix = ".L";
CommentString = "#";
ZeroDirective = "\t.space\t";
Data64bitsDirective = "\t.quad\t";
GlobalDirective = "\t.global\t";
UsesELFSectionDirectiveForBSS = true;
SupportsDebugInformation = true;
ExceptionsType = ExceptionHandling::DwarfCFI;
AlignmentIsInBytes = false;
}
30 changes: 30 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===-- XtensaMCAsmInfo.h - Xtensa Asm Info --------------------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// 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 contains the declaration of the XtensaMCAsmInfo class.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSATARGETASMINFO_H
#define LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSATARGETASMINFO_H

#include "llvm/MC/MCAsmInfoELF.h"

namespace llvm {
class Triple;

class XtensaMCAsmInfo : public MCAsmInfoELF {
public:
explicit XtensaMCAsmInfo(const Triple &TT);
};

} // namespace llvm

#endif /* LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSATARGETASMINFO_H */
572 changes: 572 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCExpr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//===-- XtensaMCExpr.cpp - Xtensa specific MC expression classes ----------===//
//
// The LLVM Compiler Infrastructure
//
// 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 contains the implementation of the assembly expression modifiers
// accepted by the Xtensa architecture
//
//===----------------------------------------------------------------------===//

#include "XtensaMCExpr.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/ErrorHandling.h"

using namespace llvm;

#define DEBUG_TYPE "xtensamcexpr"

const XtensaMCExpr *XtensaMCExpr::create(const MCExpr *Expr, VariantKind Kind,
MCContext &Ctx) {
return new (Ctx) XtensaMCExpr(Expr, Kind);
}

void XtensaMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
bool HasVariant = getKind() != VK_Xtensa_None;
if (HasVariant)
OS << '%' << getVariantKindName(getKind()) << '(';
Expr->print(OS, MAI);
if (HasVariant)
OS << ')';
}

bool XtensaMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
const MCAsmLayout *Layout,
const MCFixup *Fixup) const {
return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
}

void XtensaMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
Streamer.visitUsedExpr(*getSubExpr());
}

XtensaMCExpr::VariantKind XtensaMCExpr::getVariantKindForName(StringRef name) {
return StringSwitch<XtensaMCExpr::VariantKind>(name).Default(
VK_Xtensa_Invalid);
}

StringRef XtensaMCExpr::getVariantKindName(VariantKind Kind) {
switch (Kind) {
default:
llvm_unreachable("Invalid ELF symbol kind");
}
}
58 changes: 58 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCExpr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//===-- XtensaMCExpr.h - Xtensa specific MC expression classes --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// 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 describes Xtensa-specific MCExprs
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_Xtensa_MCTARGETDESC_XtensaMCEXPR_H
#define LLVM_LIB_TARGET_Xtensa_MCTARGETDESC_XtensaMCEXPR_H

#include "llvm/MC/MCExpr.h"

namespace llvm {

class StringRef;
class XtensaMCExpr : public MCTargetExpr {
public:
enum VariantKind { VK_Xtensa_None, VK_Xtensa_Invalid };

private:
const MCExpr *Expr;
const VariantKind Kind;

explicit XtensaMCExpr(const MCExpr *Expr, VariantKind Kind)
: Expr(Expr), Kind(Kind) {}

public:
static const XtensaMCExpr *create(const MCExpr *Expr, VariantKind Kind,
MCContext &Ctx);

VariantKind getKind() const { return Kind; }

const MCExpr *getSubExpr() const { return Expr; }

void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
const MCFixup *Fixup) const override;
void visitUsedExpr(MCStreamer &Streamer) const override;
MCFragment *findAssociatedFragment() const override {
return getSubExpr()->findAssociatedFragment();
}

void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}

static VariantKind getVariantKindForName(StringRef name);
static StringRef getVariantKindName(VariantKind Kind);
};

} // end namespace llvm.

#endif
115 changes: 115 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//===-- XtensaMCTargetDesc.cpp - Xtebsa target descriptions ---------------===//
//
// The LLVM Compiler Infrastructure
//
// 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
//
//===----------------------------------------------------------------------===//
#include "XtensaMCTargetDesc.h"
#include "XtensaInstPrinter.h"
#include "XtensaMCAsmInfo.h"
#include "llvm/MC/MCDwarf.h"
#include "XtensaTargetStreamer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"

#define GET_INSTRINFO_MC_DESC
#include "XtensaGenInstrInfo.inc"

#define GET_REGINFO_MC_DESC
#include "XtensaGenRegisterInfo.inc"

#define GET_SUBTARGETINFO_MC_DESC
#include "XtensaGenSubtargetInfo.inc"

using namespace llvm;

static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI,
const Triple &TT,
const MCTargetOptions &Options) {
MCAsmInfo *MAI = new XtensaMCAsmInfo(TT);
MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(
nullptr, MRI.getDwarfRegNum(Xtensa::SP, true), 0);
MAI->addInitialFrameState(Inst);
return MAI;
}

static MCInstrInfo *createXtensaMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitXtensaMCInstrInfo(X);
return X;
}

static MCInstPrinter *createXtensaMCInstPrinter(const Triple &TT,
unsigned SyntaxVariant,
const MCAsmInfo &MAI,
const MCInstrInfo &MII,
const MCRegisterInfo &MRI) {
return new XtensaInstPrinter(MAI, MII, MRI);
}

static MCRegisterInfo *createXtensaMCRegisterInfo(const Triple &TT) {
MCRegisterInfo *X = new MCRegisterInfo();
InitXtensaMCRegisterInfo(X, Xtensa::SP);
return X;
}

static MCSubtargetInfo *
createXtensaMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
return createXtensaMCSubtargetInfoImpl(TT, CPU, FS);
}

static MCTargetStreamer *
createXtensaAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
MCInstPrinter *InstPrint, bool isVerboseAsm) {
return new XtensaTargetAsmStreamer(S, OS);
}

static MCTargetStreamer *
createXtensaObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
return new XtensaTargetELFStreamer(S);
}

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaTargetMC() {
// Register the MCAsmInfo.
TargetRegistry::RegisterMCAsmInfo(TheXtensaTarget, createXtensaMCAsmInfo);

// Register the MCCodeEmitter.
TargetRegistry::RegisterMCCodeEmitter(TheXtensaTarget,
createXtensaMCCodeEmitter);

// Register the MCInstrInfo.
TargetRegistry::RegisterMCInstrInfo(TheXtensaTarget, createXtensaMCInstrInfo);

// Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(TheXtensaTarget,
createXtensaMCInstPrinter);

// Register the MCRegisterInfo.
TargetRegistry::RegisterMCRegInfo(TheXtensaTarget,
createXtensaMCRegisterInfo);

// Register the MCSubtargetInfo.
TargetRegistry::RegisterMCSubtargetInfo(TheXtensaTarget,
createXtensaMCSubtargetInfo);

// Register the MCAsmBackend.
TargetRegistry::RegisterMCAsmBackend(TheXtensaTarget,
createXtensaMCAsmBackend);

// Register the asm target streamer.
TargetRegistry::RegisterAsmTargetStreamer(TheXtensaTarget,
createXtensaAsmTargetStreamer);

// Register the ELF target streamer.
TargetRegistry::RegisterObjectTargetStreamer(
TheXtensaTarget, createXtensaObjectTargetStreamer);
}
60 changes: 60 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===-- XtensaMCTargetDesc.h - Xtensa Target Descriptions -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// 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 provides Xtensa specific target descriptions.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAMCTARGETDESC_H
#define LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAMCTARGETDESC_H
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/TargetRegistry.h"

namespace llvm {

class MCAsmBackend;
class MCCodeEmitter;
class MCContext;
class MCInstrInfo;
class MCObjectTargetWriter;
class MCObjectWriter;
class MCRegisterInfo;
class MCSubtargetInfo;
class StringRef;
class Target;
class raw_ostream;

extern Target TheXtensaTarget;

MCCodeEmitter *createXtensaMCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
MCContext &Ctx);

MCAsmBackend *createXtensaMCAsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options);
std::unique_ptr<MCObjectTargetWriter>
createXtensaObjectWriter(uint8_t OSABI, bool IsLittleEndian);
} // end namespace llvm

// Defines symbolic names for Xtensa registers.
// This defines a mapping from register name to register number.
#define GET_REGINFO_ENUM
#include "XtensaGenRegisterInfo.inc"

// Defines symbolic names for the Xtensa instructions.
#define GET_INSTRINFO_ENUM
#include "XtensaGenInstrInfo.inc"

#define GET_SUBTARGETINFO_ENUM
#include "XtensaGenSubtargetInfo.inc"

#endif /* LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAMCTARGETDESC_H */
97 changes: 97 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//===-- XtensaTargetStreamer.cpp - Xtensa Target Streamer Methods ---------===//
//
// The LLVM Compiler Infrastructure
//
// 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 provides Xtensa specific target streamer methods.
//
//===----------------------------------------------------------------------===//

#include "XtensaTargetStreamer.h"
#include "XtensaInstPrinter.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/Support/FormattedStream.h"

using namespace llvm;

XtensaTargetStreamer::XtensaTargetStreamer(MCStreamer &S)
: MCTargetStreamer(S) {}

XtensaTargetAsmStreamer::XtensaTargetAsmStreamer(MCStreamer &S,
formatted_raw_ostream &OS)
: XtensaTargetStreamer(S), OS(OS) {}

void XtensaTargetAsmStreamer::emitLiteral(std::string str) { OS << str; }

XtensaTargetELFStreamer::XtensaTargetELFStreamer(MCStreamer &S)
: XtensaTargetStreamer(S) {}

void XtensaTargetELFStreamer::emitLiteralLabel(MCSymbol *LblSym, SMLoc L) {
MCContext &Context = getStreamer().getContext();
MCStreamer &OutStreamer = getStreamer();
MCSectionELF *CS = (MCSectionELF *)OutStreamer.getCurrentSectionOnly();
std::string CSectionName = CS->getSectionName();
std::size_t Pos = CSectionName.find(".text");
std::string SectionName;
if (Pos != std::string::npos) {
SectionName = ".literal";
SectionName += CSectionName.substr(Pos);
} else {
SectionName = CSectionName;
SectionName += ".literal";
}

MCSection *ConstSection = Context.getELFSection(
SectionName, ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
ConstSection->setAlignment(Align(4));

OutStreamer.PushSection();
OutStreamer.SwitchSection(ConstSection);
OutStreamer.EmitLabel(LblSym, L);
OutStreamer.PopSection();
}

void XtensaTargetELFStreamer::emitLiteral(MCSymbol *LblSym, const MCExpr *Value,
SMLoc L) {
MCStreamer &OutStreamer = getStreamer();

OutStreamer.EmitLabel(LblSym, L);
OutStreamer.EmitValue(Value, 4, L);
}

void XtensaTargetELFStreamer::emitLiteral(const MCExpr *Value, SMLoc L) {
MCContext &Context = getStreamer().getContext();
MCStreamer &OutStreamer = getStreamer();
MCSectionELF *CS = (MCSectionELF *)OutStreamer.getCurrentSectionOnly();
std::string CSectionName = CS->getSectionName();
std::size_t Pos = CSectionName.find(".text");
std::string SectionName;
if (Pos != std::string::npos) {
SectionName = ".literal";
SectionName += CSectionName.substr(Pos);
} else {
SectionName = CSectionName;
SectionName += ".literal";
}

MCSection *ConstSection = Context.getELFSection(
SectionName, ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);

OutStreamer.PushSection();
OutStreamer.SwitchSection(ConstSection);
OutStreamer.EmitValue(Value, 4, L);
OutStreamer.PopSection();
}

MCELFStreamer &XtensaTargetELFStreamer::getStreamer() {
return static_cast<MCELFStreamer &>(Streamer);
}
51 changes: 51 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//===-- XtensaTargetStreamer.h - Xtensa Target Streamer --------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_XTENSA_XTENSATARGETSTREAMER_H
#define LLVM_LIB_TARGET_XTENSA_XTENSATARGETSTREAMER_H

#include "XtensaConstantPoolValue.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/SMLoc.h"

namespace llvm {
class XtensaTargetStreamer : public MCTargetStreamer {
public:
XtensaTargetStreamer(MCStreamer &S);
virtual void emitLiteral(MCSymbol *LblSym, const MCExpr *Value, SMLoc L) = 0;
virtual void emitLiteralLabel(MCSymbol *LblSym, SMLoc L) = 0;
virtual void emitLiteral(const MCExpr *Value, SMLoc L) = 0;
virtual void emitLiteral(std::string str) = 0;
};

class XtensaTargetAsmStreamer : public XtensaTargetStreamer {
formatted_raw_ostream &OS;

public:
XtensaTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
void emitLiteral(MCSymbol *LblSym, const MCExpr *Value, SMLoc L) override {}
void emitLiteralLabel(MCSymbol *LblSym, SMLoc L) override {}
void emitLiteral(const MCExpr *Value, SMLoc L) override {}
void emitLiteral(std::string str) override;
};

class XtensaTargetELFStreamer : public XtensaTargetStreamer {
public:
XtensaTargetELFStreamer(MCStreamer &S);
MCELFStreamer &getStreamer();
void emitLiteral(MCSymbol *LblSym, const MCExpr *Value, SMLoc L) override;
void emitLiteralLabel(MCSymbol *LblSym, SMLoc L) override;
void emitLiteral(const MCExpr *Value, SMLoc L) override;
void emitLiteral(std::string str) override {}
};
} // end namespace llvm

#endif
5 changes: 5 additions & 0 deletions llvm/lib/Target/Xtensa/TargetInfo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )

add_llvm_component_library(LLVMXtensaInfo
XtensaTargetInfo.cpp
)
22 changes: 22 additions & 0 deletions llvm/lib/Target/Xtensa/TargetInfo/LLVMBuild.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
;===- ./lib/Target/TargetInfo/LLVMBuild.txt --------------------*- Conf -*--===;
;
; 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 is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[component_0]
type = Library
name = XtensaInfo
parent = Xtensa
required_libraries = Support
add_to_library_groups = Xtensa
20 changes: 20 additions & 0 deletions llvm/lib/Target/Xtensa/TargetInfo/XtensaTargetInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- XtensaTargetInfo.cpp - Xtensa Target Implementation ---------------===//
//
// The LLVM Compiler Infrastructure
//
// 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
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/TargetRegistry.h"

using namespace llvm;
namespace llvm {
Target TheXtensaTarget;
}
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaTargetInfo() {
RegisterTarget<Triple::xtensa> X(TheXtensaTarget, "xtensa", "Xtensa 32",
"XTENSA");
}
30 changes: 30 additions & 0 deletions llvm/lib/Target/Xtensa/Xtensa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===- Xtensa.h - Top-level interface for Xtensa representation -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// 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 contains the entry points for global functions defined in
// the LLVM Xtensa back-end.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_XTENSA_XTENSA_H
#define LLVM_LIB_TARGET_XTENSA_XTENSA_H

#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "llvm/PassRegistry.h"

namespace llvm {
class XtensaTargetMachine;
class FunctionPass;

FunctionPass *createXtensaISelDag(XtensaTargetMachine &TM,
CodeGenOpt::Level OptLevel);
FunctionPass *createXtensaSizeReductionPass();
} // namespace llvm
#endif /* LLVM_LIB_TARGET_XTENSA_XTENSA_H */
Loading