Difference between revisions of "NaplesPU Clang Documentation"
(→tools/clang/lib/Driver/Tools.cpp) |
(→tools/clang/lib/Basic/Targets.cpp) |
||
Line 75: | Line 75: | ||
* allignment and width of several types | * allignment and width of several types | ||
* a DataLayout string used to describe the target. The string related to NuPlus is "e-m:e-p:32:32-i64:64:64-i32:32:32-f32:32:32-f64:64:64". The different features are separated by '-'. The first lower-case 'e' indicates little-endian. "m:e" indicates the ELF mangling mode. "p:32:32" indicates size and alignment of pointers. "i64:64:64", "i32:32:32", "f32:32:32" and "f64:64:64" indicate size and alignment of 32- and 64-bit integers and floats. For more information, check the DataLayout class implementation in lib/IR/DataLayout.cpp and the include/llvm/IR/DataLayout.h file. | * a DataLayout string used to describe the target. The string related to NuPlus is "e-m:e-p:32:32-i64:64:64-i32:32:32-f32:32:32-f64:64:64". The different features are separated by '-'. The first lower-case 'e' indicates little-endian. "m:e" indicates the ELF mangling mode. "p:32:32" indicates size and alignment of pointers. "i64:64:64", "i32:32:32", "f32:32:32" and "f64:64:64" indicate size and alignment of 32- and 64-bit integers and floats. For more information, check the DataLayout class implementation in lib/IR/DataLayout.cpp and the include/llvm/IR/DataLayout.h file. | ||
+ | Note that some of these aspects must be specified also inside the costructor of the NuPlusTargetMachine class located in the *[[NuPlusTargetMachine.cpp | NuPlusTargetMachine.cpp/.h]] files. | ||
<syntaxhighlight lang="cpp" line='line'> | <syntaxhighlight lang="cpp" line='line'> |
Revision as of 17:56, 11 June 2018
In the following, we will show which files should be modified and how.
Contents
- 1 tools/clang/include/clang/Basic/BuiltinsNuPlus.def
- 2 tools/clang/include/clang/Basic/TargetBuiltins.h
- 3 tools/clang/lib/Basic/Targets.cpp
- 4 tools/clang/lib/CodeGen/CGBuiltin.cpp
- 5 tools/clang/lib/CodeGen/CodeGenFunction.h
- 6 tools/clang/lib/Driver/Driver.cpp
- 7 tools/clang/lib/Driver/ToolChains.cpp
- 8 tools/clang/lib/Driver/ToolChains.h
- 9 tools/clang/lib/Driver/Tools.cpp
- 10 tools/clang/lib/Driver/Tools.h
tools/clang/include/clang/Basic/BuiltinsNuPlus.def
This file defines the NuPlus-specific builtin function database. The format of this database is described inside tools/clang/include/clang/Basic/Builtins.def.
tools/clang/include/clang/Basic/TargetBuiltins.h
namespace NuPlus {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "clang/Basic/BuiltinsNuPlus.def"
LastTSBuiltin
};
}
We include the path to BuiltinsNuPlus.def.
tools/clang/lib/Basic/Targets.cpp
class NuPlusTargetInfo : public TargetInfo {
static const char *const GCCRegNames[];
static const Builtin::Info BuiltinInfo[];
public:
NuPlusTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
BigEndian = false;
TLSSupported = false; //thread-local storage
IntWidth = IntAlign = 32;
LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
DoubleAlign = 64;
LongDoubleWidth = LongDoubleAlign = 64;
PointerWidth = PointerAlign = 32;
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
resetDataLayout("e-m:e-p:32:32-i64:64:64-i32:32:32-f32:32:32-f64:64:64");
}
bool setCPU(const std::string &Name) override {
return Name == "nuplus";
}
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
Builder.defineMacro("__NUPLUS__");
}
ArrayRef<Builtin::Info> getTargetBuiltins() const override {
return llvm::makeArrayRef(BuiltinInfo,
clang::NuPlus::LastTSBuiltin - Builtin::FirstTSBuiltin);
}
virtual ArrayRef<const char*> getGCCRegNames() const override;
ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
return None;
}
virtual bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
virtual const char *getClobbers() const override {
return "";
}
virtual BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
}
};
This is required to implement the construction of a TargetInfo object. The NuPlusTargetInfo object is inherited from the TargetInfo object and the majority of its attributes are set by default in the TargetInfo constructor. Check the constructor in tools/clang/lib/Basic/TargetInfo.cpp. As regards NuPlus, the information that must be provided to the frontend includes:
- endianess
- thread-local storage (TLS)
- allignment and width of several types
- a DataLayout string used to describe the target. The string related to NuPlus is "e-m:e-p:32:32-i64:64:64-i32:32:32-f32:32:32-f64:64:64". The different features are separated by '-'. The first lower-case 'e' indicates little-endian. "m:e" indicates the ELF mangling mode. "p:32:32" indicates size and alignment of pointers. "i64:64:64", "i32:32:32", "f32:32:32" and "f64:64:64" indicate size and alignment of 32- and 64-bit integers and floats. For more information, check the DataLayout class implementation in lib/IR/DataLayout.cpp and the include/llvm/IR/DataLayout.h file.
Note that some of these aspects must be specified also inside the costructor of the NuPlusTargetMachine class located in the * NuPlusTargetMachine.cpp/.h files.
const char *const NuPlusTargetInfo::GCCRegNames[] = {
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
"s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39",
"s40", "s41", "s42", "s43", "s44", "s45", "s46", "s47",
"s48", "s49", "s50", "s51", "s52", "s53", "s54", "s55",
"s56", "s57", "TR", "RM", "FP", "SP", "RA", "PC",
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
"v32", "v33", "v34", "v35", "v36", "v37", "v38", "v39",
"v40", "v41", "v42", "v43", "v44", "v45", "v46", "v47",
"v48", "v49", "v50", "v51", "v52", "v53", "v54", "v55",
"v56", "v57", "v58", "v59", "v60", "v61", "v62", "v63"
};
This is the list of all registers in the NuPlus register file.
ArrayRef<const char *> NuPlusTargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}
bool NuPlusTargetInfo::
validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const {
switch (*Name) {
default:
return false;
case 's':
case 'v':
Info.setAllowsRegister();
return true;
case 'I': // Unsigned 8-bit constant
case 'J': // Unsigned 12-bit constant
case 'K': // Signed 16-bit constant
case 'L': // Signed 20-bit displacement (on all targets we support)
case 'M': // 0x7fffffff
return true;
case 'Q': // Memory with base and unsigned 12-bit displacement
case 'R': // Likewise, plus an index
case 'S': // Memory with base and signed 20-bit displacement
case 'T': // Likewise, plus an index
Info.setAllowsMemory();
return true;
}
}
This is related to the constraints in case of inline assembler implementation methods. We derived our method from SystemZTargetInfo::validateAsmConstraint.
const Builtin::Info NuPlusTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
ALL_LANGUAGES },
#include "clang/Basic/BuiltinsNuPlus.def"
};
We specify the format of the builtins and we include the BuiltinsNuPlus.def file, i.e. the file that contains all the nu+ specific builtins.
static TargetInfo *AllocateTarget(const llvm::Triple &Triple, const TargetOptions &Opts) {
switch (Triple.getArch()) {
...
case llvm::Triple::nuplus:
return new NuPlusTargetInfo(Triple);
We add the nu+ case for the above switch statements.
tools/clang/lib/CodeGen/CGBuiltin.cpp
static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF, unsigned BuiltinID, const CallExpr *E, llvm::Triple::ArchType Arch) {
switch (Arch) {
...
case llvm::Triple::nuplus:
return CGF->EmitNuPlusBuiltinExpr(BuiltinID, E);
...
Value *CodeGenFunction::EmitNuPlusBuiltinExpr(unsigned BuiltinID, const CallExpr *E) {
...
}
The EmitNuPlusBuiltinExpr function maps each Builtin call to the corresponding LLVM intrinsic. This is a target dependent function and hence it should be filled with all the NuPlus Builtin calls.
tools/clang/lib/CodeGen/CodeGenFunction.h
llvm::Value *EmitNuPlusBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
We add the function prototype.
tools/clang/lib/Driver/Driver.cpp
const ToolChain &Driver::getToolChain(const ArgList &Args, const llvm::Triple &Target) const {
...
switch (Target.getArch()) {
case llvm::Triple::nuplus:
TC = new toolchains::NuPlusToolChain(*this, Target, Args);
break;
This is required to retrieve the ToolChain for the NuPlus triple.
tools/clang/lib/Driver/ToolChains.cpp
NuPlusToolChain::NuPlusToolChain(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args) : ToolChain(D, Triple, Args){
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
}
NuPlusToolChain::~NuPlusToolChain()
{
}
bool NuPlusToolChain::IsIntegratedAssemblerDefault() const
{
return true;
}
We use the default integrated assembler.
bool NuPlusToolChain::isPICDefault() const
{
return false;
}
bool NuPlusToolChain::isPIEDefault() const
{
return false;
}
bool NuPlusToolChain::isPICDefaultForced() const
{
return false;
}
By default, we don't use the Position Independent Code (PIC) and the Position Independent Executable (PIE).
void NuPlusToolChain::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
CC1Args.push_back("-nostdsysteminc");
if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
options::OPT_fno_use_init_array,
true))
{
CC1Args.push_back("-fuse-init-array");
}
}
This is used to add some options to Clang. In particular,
- -nostdsysteminc Disable standard system #include directories
- -fuse-init-array Use .init_array instead of .ctors. For more details, see ELF Special Sections
bool NuPlusToolChain::IsUnwindTablesDefault() const {
return true;
}
This enables the generation of unwind tables (DWARF-based stack unwinding, .eh_frame section).
Tool *NuPlusToolChain::buildLinker() const {
return new tools::NuPlus::Link(*this);
}
It builds the linker.
tools/clang/lib/Driver/ToolChains.h
class LLVM_LIBRARY_VISIBILITY NuPlusToolChain : public ToolChain {
public:
NuPlusToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
~NuPlusToolChain();
bool IsIntegratedAssemblerDefault() const override;
bool isPICDefault() const override;
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
tools::ArgStringList &CC1Args) const override;
bool IsUnwindTablesDefault() const override;
protected:
virtual Tool *buildLinker() const;
};
The NuPlusToolChain class declaration.
tools/clang/lib/Driver/Tools.cpp
static std::string getCPUName(const ArgList &Args, const llvm::Triple &T, bool FromAs = false) {
...
switch (T.getArch()) {
case llvm::Triple::nuplus:
return "nuplus";
It returns the CPU name.
static void addExceptionArgs(const ArgList &Args, types::ID InputType,
const ToolChain &TC, bool KernelOrKext,
const ObjCRuntime &objcRuntime,
ArgStringList &CmdArgs) {
...
if (types::isCXX(InputType)) {
// Disable C++ EH by default on XCore, PS4 and NuPlus.
bool CXXExceptionsEnabled =
Triple.getArch() != llvm::Triple::xcore &&
!Triple.isPS4CPU() &&
Triple.getArch() != llvm::Triple::nuplus;
By default, the C++ EH (Exception Handling Model) is disabled.
static bool shouldUseFramePointerForTarget(const ArgList &Args, const llvm::Triple &Triple) {
switch (Triple.getArch()) {
...
case llvm::Triple::nuplus:
return !areOptimizationsEnabled(Args);
We don't use a frame pointer if optimizing for the NuPlus target.
void NuPlus::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
assert(Output.isNothing() && "Invalid output.");
}
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld.mcld"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
This is necessary for a proper usage of the linker.
tools/clang/lib/Driver/Tools.h
namespace NuPlus {
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
Link(const ToolChain &TC) : Tool("NuPlus::Link", "NuPlus-ld", TC) {}
virtual bool hasIntegratedCPP() const override { return false; }
virtual bool isLinkJob() const override { return true; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
}