Now, we need to add ABI support within the frontend for clang, which allows us to produce code specific to the M88k target from the frontend:
- Let’s start by adding the following clang/lib/CodeGen/TargetInfo.h. This is a prototype that creates the code generation information for the M88k target:
std::unique_ptr createM88kTargetCodeGenInfo(CodeGenModule &CGM);
- We also need to add the following code to clang/lib/Basic/Targets.cpp, which will help teach clang the acceptable target triples for M88k. As we can see, for the M88k target, the acceptable operating system is OpenBSD. This means that clang accepts m88k-openbsd as a target triple: include “Targets/M88k.h”
include “Targets/MSP430.h”
. . .
case llvm::Triple::m88k:
switch (os) {
case llvm::Triple::OpenBSD:
return std::make_unique>(Triple, Opts);
default:
return std::make_unique(Triple, Opts);
}
case llvm::Triple::le32:
. . .
Now, we need to create a file called clang/lib/CodeGen/Targets/M88k.cpp so that we can continue the code generation information and ABI implementation for M88k.
- Within clang/lib/CodeGen/Targets/M88k.cpp, we must add the following necessary headers, one of which is the TargetInfo.h header that we have just modified. Then, we must specify that we’re using the clang and clang::codegen namespaces:
include “ABIInfoImpl.h”
include “TargetInfo.h”
using namespace clang;
using namespace clang::CodeGen;
- Next, we must declare a new anonymous namespace and place our M88kABIInfo inside of it. M88kABIInfo inherits from the existing ABIInfo from clang and contains DefaultABIInfo inside it. For our target, we rely heavily on the existing ABIInfo and DefaultABIInfo, which simplifies the M88kABIInfo class significantly:
namespace {
class M88kABIInfo final : public ABIInfo {
DefaultABIInfo defaultInfo;
- Furthermore, aside from adding the constructor for the M88kABIInfo class, a couple of methods are also added. computeInfo() implements the default clang::CodeGen::ABIInfo class. There’s also the EmitVAArg() function, which generates code that retrieves an argument from a pointer that is passed in; this is updated after. This is primarily used for variadic function support:
public:
explicit M88kABIInfo(CodeGen::CodeGenTypes &CGT)
: ABIInfo(CGT), defaultInfo(CGT) {}
void computeInfo(CodeGen::CGFunctionInfo &FI) const override {}
CodeGen::Address EmitVAArg(CodeGen::CodeGenFunction &CGF,
CodeGen::Address VAListAddr,
QualType Ty) const override {
return VAListAddr;
}
};
- The class constructor for the M88kTargetCodeGenInfo class is added next, which extends from the original TargetCodeGenInfo. After, we must close off the anonymous namespace that was created initially:
class M88kTargetCodeGenInfo final : public TargetCodeGenInfo {
public:
explicit M88kTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
: TargetCodeGenInfo(std::make_unique(CGT)) {} };
}
- Finally, we must add the implementation to create the actual M88kTargetCodeGenInfo class as std::unique_ptr, which takes in a single CodeGenModule that generates LLVM IR code. This directly corresponds to what was originally added to TargetInfo.h:
std::unique_ptr
CodeGen::createM88kTargetCodeGenInfo(CodeGenModule &CGM) {
return std::make_unique(CGM.getTypes());
}
That concludes the ABI support for the M88k in the frontend.