mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-16 13:20:41 +00:00
214 lines
8.3 KiB
C++
214 lines
8.3 KiB
C++
//===-- LLVMTargetMachine.cpp - Implement the LLVMTargetMachine class -----===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the LLVMTargetMachine class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "llvm/PassManager.h"
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/MC/MCInstrInfo.h"
|
|
#include "llvm/MC/MCStreamer.h"
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
|
#include "llvm/Target/TargetSubtargetInfo.h"
|
|
#include "llvm/ADT/OwningPtr.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/FormattedStream.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
using namespace llvm;
|
|
|
|
static cl::opt<bool> ShowMCEncoding("show-mc-encoding", cl::Hidden,
|
|
cl::desc("Show encoding in .s output"));
|
|
static cl::opt<bool> ShowMCInst("show-mc-inst", cl::Hidden,
|
|
cl::desc("Show instruction structure in .s output"));
|
|
|
|
static cl::opt<cl::boolOrDefault>
|
|
AsmVerbose("asm-verbose", cl::desc("Add comments to directives."),
|
|
cl::init(cl::BOU_UNSET));
|
|
|
|
static bool getVerboseAsm() {
|
|
switch (AsmVerbose) {
|
|
case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault();
|
|
case cl::BOU_TRUE: return true;
|
|
case cl::BOU_FALSE: return false;
|
|
}
|
|
llvm_unreachable("Invalid verbose asm state");
|
|
}
|
|
|
|
LLVMTargetMachine::LLVMTargetMachine(const Target &T, StringRef Triple,
|
|
StringRef CPU, StringRef FS,
|
|
TargetOptions Options,
|
|
Reloc::Model RM, CodeModel::Model CM,
|
|
CodeGenOpt::Level OL)
|
|
: TargetMachine(T, Triple, CPU, FS, Options) {
|
|
CodeGenInfo = T.createMCCodeGenInfo(Triple, RM, CM, OL);
|
|
AsmInfo = T.createMCAsmInfo(Triple);
|
|
// TargetSelect.h moved to a different directory between LLVM 2.9 and 3.0,
|
|
// and if the old one gets included then MCAsmInfo will be NULL and
|
|
// we'll crash later.
|
|
// Provide the user with a useful error message about what's wrong.
|
|
assert(AsmInfo && "MCAsmInfo not initialized."
|
|
"Make sure you include the correct TargetSelect.h"
|
|
"and that InitializeAllTargetMCs() is being invoked!");
|
|
}
|
|
|
|
bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
|
|
formatted_raw_ostream &Out,
|
|
CodeGenFileType FileType,
|
|
bool DisableVerify) {
|
|
// Add common CodeGen passes.
|
|
MCContext *Context = 0;
|
|
TargetPassConfig *PassConfig = createPassConfig(PM, DisableVerify);
|
|
PM.add(PassConfig);
|
|
if (PassConfig->addCodeGenPasses(Context))
|
|
return true;
|
|
assert(Context != 0 && "Failed to get MCContext");
|
|
|
|
if (hasMCSaveTempLabels())
|
|
Context->setAllowTemporaryLabels(false);
|
|
|
|
const MCAsmInfo &MAI = *getMCAsmInfo();
|
|
const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
|
|
OwningPtr<MCStreamer> AsmStreamer;
|
|
|
|
switch (FileType) {
|
|
case CGFT_AssemblyFile: {
|
|
MCInstPrinter *InstPrinter =
|
|
getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI, STI);
|
|
|
|
// Create a code emitter if asked to show the encoding.
|
|
MCCodeEmitter *MCE = 0;
|
|
MCAsmBackend *MAB = 0;
|
|
if (ShowMCEncoding) {
|
|
const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
|
|
MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), STI, *Context);
|
|
MAB = getTarget().createMCAsmBackend(getTargetTriple());
|
|
}
|
|
|
|
MCStreamer *S = getTarget().createAsmStreamer(*Context, Out,
|
|
getVerboseAsm(),
|
|
hasMCUseLoc(),
|
|
hasMCUseCFI(),
|
|
hasMCUseDwarfDirectory(),
|
|
InstPrinter,
|
|
MCE, MAB,
|
|
ShowMCInst);
|
|
AsmStreamer.reset(S);
|
|
break;
|
|
}
|
|
case CGFT_ObjectFile: {
|
|
// Create the code emitter for the target if it exists. If not, .o file
|
|
// emission fails.
|
|
MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), STI,
|
|
*Context);
|
|
MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple());
|
|
if (MCE == 0 || MAB == 0)
|
|
return true;
|
|
|
|
AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(),
|
|
*Context, *MAB, Out,
|
|
MCE, hasMCRelaxAll(),
|
|
hasMCNoExecStack()));
|
|
AsmStreamer.get()->InitSections();
|
|
break;
|
|
}
|
|
case CGFT_Null:
|
|
// The Null output is intended for use for performance analysis and testing,
|
|
// not real users.
|
|
AsmStreamer.reset(createNullStreamer(*Context));
|
|
break;
|
|
}
|
|
|
|
// Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
|
|
FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer);
|
|
if (Printer == 0)
|
|
return true;
|
|
|
|
// If successful, createAsmPrinter took ownership of AsmStreamer.
|
|
AsmStreamer.take();
|
|
|
|
PM.add(Printer);
|
|
|
|
PM.add(createGCInfoDeleter());
|
|
return false;
|
|
}
|
|
|
|
/// addPassesToEmitMachineCode - Add passes to the specified pass manager to
|
|
/// get machine code emitted. This uses a JITCodeEmitter object to handle
|
|
/// actually outputting the machine code and resolving things like the address
|
|
/// of functions. This method should returns true if machine code emission is
|
|
/// not supported.
|
|
///
|
|
bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM,
|
|
JITCodeEmitter &JCE,
|
|
bool DisableVerify) {
|
|
// Add common CodeGen passes.
|
|
MCContext *Ctx = 0;
|
|
OwningPtr<TargetPassConfig> PassConfig(createPassConfig(PM, DisableVerify));
|
|
if (PassConfig->addCodeGenPasses(Ctx))
|
|
return true;
|
|
|
|
addCodeEmitter(PM, JCE);
|
|
PM.add(createGCInfoDeleter());
|
|
|
|
return false; // success!
|
|
}
|
|
|
|
/// addPassesToEmitMC - Add passes to the specified pass manager to get
|
|
/// machine code emitted with the MCJIT. This method returns true if machine
|
|
/// code is not supported. It fills the MCContext Ctx pointer which can be
|
|
/// used to build custom MCStreamer.
|
|
///
|
|
bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
|
|
MCContext *&Ctx,
|
|
raw_ostream &Out,
|
|
bool DisableVerify) {
|
|
// Add common CodeGen passes.
|
|
OwningPtr<TargetPassConfig> PassConfig(createPassConfig(PM, DisableVerify));
|
|
if (PassConfig->addCodeGenPasses(Ctx))
|
|
return true;
|
|
|
|
if (hasMCSaveTempLabels())
|
|
Ctx->setAllowTemporaryLabels(false);
|
|
|
|
// Create the code emitter for the target if it exists. If not, .o file
|
|
// emission fails.
|
|
const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
|
|
MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(),STI, *Ctx);
|
|
MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple());
|
|
if (MCE == 0 || MAB == 0)
|
|
return true;
|
|
|
|
OwningPtr<MCStreamer> AsmStreamer;
|
|
AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(), *Ctx,
|
|
*MAB, Out, MCE,
|
|
hasMCRelaxAll(),
|
|
hasMCNoExecStack()));
|
|
AsmStreamer.get()->InitSections();
|
|
|
|
// Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
|
|
FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer);
|
|
if (Printer == 0)
|
|
return true;
|
|
|
|
// If successful, createAsmPrinter took ownership of AsmStreamer.
|
|
AsmStreamer.take();
|
|
|
|
PM.add(Printer);
|
|
|
|
return false; // success!
|
|
}
|