Initializing the target machine class – Basics of IR Code Generation
By Reginald Bellamy / October 3, 2023 / No Comments / Emitting the function body, Exams of IT, IT Certifications, LLVM IR REFERENCE
Now, only the target machine is missing. With the target machine, we define the CPU architecture we’d like to generate code for. For each CPU, there are features available that can be used to influence the code generation process. For example, a newer CPU of a CPU architecture family can support vector instructions. With features, we can toggle the use of vector instructions on or off. To support setting all these options from the command line, LLVM provides some supporting code. In the Driver class, we can add the following include variable:
include “llvm/CodeGen/CommandFlags.h”
This include variable adds common command-line options to our compiler driver. Many LLVM tools also use these command-line options, which have the benefit of providing a common interface to the user. Only the option to specify a target triple is missing. As this is very useful, we’ll add this ourselves:
static llvm::cl::opt<std::string> MTriple(
“mtriple”,
llvm::cl::desc(“Override target triple for module”));
Let’s create the target machine:
- To display error messages, the name of the application must be passed to the function:
llvm::TargetMachine *
createTargetMachine(const char *Argv0) {
- First, we must collect all the information provided by the command line. These are options for the code generator – that is, the name of the CPU and possible features that should be activated or deactivated, and the triple of the target:
llvm::Triple Triple = llvm::Triple(
!MTriple.empty()
? llvm::Triple::normalize(MTriple)
: llvm::sys::getDefaultTargetTriple());
llvm::TargetOptions TargetOptions =
codegen::InitTargetOptionsFromCodeGenFlags(Triple);
std::string CPUStr = codegen::getCPUStr();
std::string FeatureStr = codegen::getFeaturesStr();
- Then, we must look up the target in the target registry. If an error occurs, then we will display the error message and bail out. A possible error would be an unsupported triple specified by the user:
std::string Error;
const llvm::Target *Target =
llvm::TargetRegistry::lookupTarget(
codegen::getMArch(), Triple, Error);
if (!Target) {
llvm::WithColor::error(llvm::errs(), Argv0) << Error;
return nullptr;
}
- With the help of the Target class, we can configure the target machine using all the known options requested by the user:
llvm::TargetMachine *TM = Target->createTargetMachine(
Triple.getTriple(), CPUStr, FeatureStr,
TargetOptions, std::optional<llvm::Reloc::Model>(
codegen::getRelocModel()));
return TM;
}
With the target machine instance, we can generate IR code that targets a CPU architecture of our choice. What is missing is the translation to assembly text or the generation of object code files. We’ll add this support in the next section.