There are six initialization steps to go, mostly registers needed constructors.
- the target. (represent a specific ISA)
- the target machine. ( represent a concrete machine for a target, with subtargets for specific CPUs with different features and attributes.)
- MC layer. (Machine Code layer, convert Machine IR to asm file or object file)
- AsmPrinter (For output asm file or object file)
- AsmParser (Optional)
- Disassembler (Optional)
By the way,there are three layers started from LLVM IR Layer, the Machine IR Layer and the Machine Code Layer.
// do some initialization for llvm application
// and clean up managed static variable in destructor.
InitLLVM X(argc, argv);
LLVMContext Context;
// setup target.
InitializeAllTargets();
LLVMInitializeXXXTargetInfo();
extern "C" void LLVMInitializeCpu0TargetInfo() {
RegisterTarget<Triple::cpu0,
/*HasJIT=*/true>
X(TheCpu0Target, "cpu0", "CPU0 (32-bit big endian)", "Cpu0");
RegisterTarget<Triple::cpu0el,
/*HasJIT=*/true>
Y(TheCpu0elTarget, "cpu0el", "CPU0 (32-bit little endian)", "Cpu0");
}
// then register all needed class constructor into target.
// register target machine in target.
LLVMInitializeXXXTarget();
extern "C" void LLVMInitializeCpu0Target() {
// Register the target.
//- Big endian Target Machine
RegisterTargetMachine<Cpu0ebTargetMachine> X(TheCpu0Target);
//- Little endian Target Machine
RegisterTargetMachine<Cpu0elTargetMachine> Y(TheCpu0elTarget);
}
// MC layer initialization.
InitializeAllTargetMCs();
LLVMInitializeXXXTargetMC();
extern "C" void LLVMInitializeCpu0TargetMC() {
for (Target *T : {&TheCpu0Target, &TheCpu0elTarget}) {
// Register the MC asm info.
RegisterMCAsmInfoFn X(*T, createCpu0MCAsmInfo);
// Register the MC instruction info.
TargetRegistry::RegisterMCInstrInfo(*T, createCpu0MCInstrInfo);
// Register the MC register info.
TargetRegistry::RegisterMCRegInfo(*T, createCpu0MCRegisterInfo);
// Register the elf streamer.
TargetRegistry::RegisterELFStreamer(*T, createMCStreamer);
// Register the asm target streamer.
TargetRegistry::RegisterAsmTargetStreamer(*T, createCpu0AsmTargetStreamer);
// Register the asm backend.
TargetRegistry::RegisterMCAsmBackend(*T, createCpu0AsmBackend);
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(*T, createCpu0MCSubtargetInfo);
// Register the MC instruction analyzer.
TargetRegistry::RegisterMCInstrAnalysis(*T, createCpu0MCInstrAnalysis);
// Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(*T, createCpu0MCInstPrinter);
}
// Register the MC Code Emitter
TargetRegistry::RegisterMCCodeEmitter(TheCpu0Target,
createCpu0MCCodeEmitterEB);
TargetRegistry::RegisterMCCodeEmitter(TheCpu0elTarget,
createCpu0MCCodeEmitterEL);
}
// if you want to output asm file or object file.
InitializeAllAsmPrinters();
LLVMInitializeXXXAsmPrinter();
extern "C" void LLVMInitializeCpu0AsmPrinter() {
RegisterAsmPrinter<Cpu0AsmPrinter> X(TheCpu0Target);
RegisterAsmPrinter<Cpu0AsmPrinter> Y(TheCpu0elTarget);
}
// if you want to support inline asm.
InitializeAllAsmParsers();
LLVMInitializeXXXAsmParser();
extern "C" void LLVMInitializeCpu0AsmParser() {
RegisterMCAsmParser<Cpu0AsmParser> X(TheCpu0Target);
RegisterMCAsmParser<Cpu0AsmParser> Y(TheCpu0elTarget);
}
// if you want to disassemble binary code.
InitializeAllDisassemblers();
LLVMInitializeXXXDisassembler();
extern "C" void LLVMInitializeCpu0Disassembler() {
// Register the disassembler.
TargetRegistry::RegisterMCDisassembler(TheCpu0Target, createCpu0Disassembler);
TargetRegistry::RegisterMCDisassembler(TheCpu0elTarget,
createCpu0elDisassembler);
}