I'm currently working on a compiler for a C/C++ like language. I have reached the compiling phase of code generation. I'm using the LLVM C++ api to create an LLVM IR from the input file.
As far as I understood it my module object (I'm working with just one module) should contain all information I need for getting the textual representation of the LLVM IR as a string.
But I really don't know how to do that.
If you wish to get the LLVM IR of your llvm::Module you can use the llvm::Module::print function. Use this in combination with the LLVM standard streams like this:
llvm::Module module = ...
module.print(llvm::errs()); // for stderr, llvm::outs() for stdout
See also dump():
module.dump(); // print to stderr
Or use raw_ostream
llvm::outs() << module;
// or
llvm::errs() << module;
// or
llvm::dbgs() << module;
Related
I'd like to save a llvm module into file xxx.ll
maybe the code just like
llvm::module M;
...
ofstream << M;
Is there given function in llvm? or we need do some transformation for M then we can use ofstream
I'm using llvm 14
There is a llvm::Module::print method. You'll also need to construct llvm::raw_os_ostream.
I am trying to collect some information from my LLVM optimization pass during runtime. In other words, I want to know the physical address of a specific IR instruction after compilation. So my idea is to convert the LLVM metadata into LLVM DWARF data that can be used during runtime. Instead of attaching the filename and line numbers, I want to attach my own information. My question falls into two parts:
Here is a code that can get the Filename and Line number of an instruction:
if (DILocation *Loc = I->getDebugLoc()) { // Here I is an LLVM instruction
unsigned Line = Loc->getLine();
StringRef File = Loc->getFilename();
StringRef Dir = Loc->getDirectory();
bool ImplicitCode = Loc->isImplicitCode();
}
But How can I set this fields? I could not find a relevant function.
How can I see the updated Debug Information during (filename and line numbers) runtime? I used -g for compiling but still I do not see the Debug Information.
Thanks
The function you need it setDebugLoc() and the info is only included in the result if you include enough of it. The module verifier will tell you what you're missing. These two lines might also be what's tripping you up.
module->addModuleFlag(Module::Warning, "Dwarf Version", dwarf::DWARF_VERSION);
module->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);
I am trying to see how to avoid LLVM JIT compilation every time and use the cached copy. I see that LLVM has ObjectCache support for code generation from module, but to get module from a file or code string, it needs to be compiled and go through different optimization passes. What is the best way to go about it?
Cache the final image object to some file and first lookup the file, and try to parse and try to create ExecutionEngine with the image so that one can execute (get pointer to function and call it)
Save the intermediate output of code compilation and optimization - i.e. write a module to some file (e.g., using dump) and try to read it (parse IR). then use ObjectCache support for code generation from this module.
Option (2) seems two steps and likely worse than (1), but is (1) the right way to go about it?
Given that you have an instance of ObjectFile you can write it to the disk:
std::string cacheName("some_name.o");
std::error_code EC;
raw_fd_ostream outfile(cacheName, EC, sys::fs::F_None);
outfile.write(object.getBinary()->getMemoryBufferRef().getBufferStart(),
object.getBinary()->getMemoryBufferRef().getBufferSize());
outfile.close();
Then you can read it back from disk:
std::string cacheName("some_name.o");
ErrorOr<std::unique_ptr<MemoryBuffer>> buffer =
MemoryBuffer::getFile(cacheName.c_str());
if (!buffer) {
// handle error
}
Expected<std::unique_ptr<ObjectFile>> objectOrError =
ObjectFile::createObjectFile(buffer.get()->getMemBufferRef());
if (!objectOrError) {
// handle error
}
std::unique_ptr<ObjectFile> objectFile(std::move(objectOrError.get()));
auto owningObject = OwningBinary<ObjectFile>(std::move(objectFile),
std::move(buffer.get()));
auto object = owningObject.getBinary();
You can take this code and plug it in your custom ObjectCache, then feed the object cache to the JIT engine.
I hope it helps.
With the following code, I can generate an LLVM bitcode file from a module:
llvm::Module * module;
// fill module with code
module = ...;
std::error_code ec;
llvm::raw_fd_ostream out("anonymous.bc", ec, llvm::sys::fs::F_None);
llvm::WriteBitcodeToFile(module, out);
I can then use that bitcode file to generate an executable machine code file, e.g.:
clang -o anonymous anonymous.bc
Alternatively:
llc anonymous.bc
gcc -o anonymous anonymous.s
My question now is: Can I generate the machine code directly in C++ with the LLVM API without first needing to write the bitcode file?
I am looking for either a code example or at least some starting points in the LLVM API, e.g. which classes to use, nudging me in the right direction might even be enough.
I was also looking for the code for this, and #arrowd's suggestion worked.
To save the trouble for the next person, this is what I came up with.
Given a Module, it generates assembly code on stdout for your native target:
void printASM(Module *M) {
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
auto TargetTriple = sys::getDefaultTargetTriple();
M->setTargetTriple(TargetTriple);
std::string Error;
const Target *target = TargetRegistry::lookupTarget(TargetTriple, Error);
auto cpu = sys::getHostCPUName();
SubtargetFeatures Features;
StringMap<bool> HostFeatures;
if (sys::getHostCPUFeatures(HostFeatures))
for (auto &F : HostFeatures)
Features.AddFeature(F.first(), F.second);
auto features = Features.getString();
TargetOptions Options;
std::unique_ptr<TargetMachine> TM{
target->createTargetMachine(
TargetTriple, cpu, features, Options,
Reloc::PIC_, None, CodeGenOpt::None)
};
legacy::PassManager PM;
M->setDataLayout(TM->createDataLayout());
TM->addPassesToEmitFile(PM, (raw_pwrite_stream &) outs(), (raw_pwrite_stream *) (&outs()),
TargetMachine::CodeGenFileType::CGFT_AssemblyFile, true, nullptr);
PM.run(*M);
}
If anyone knows a shorter way to write this code, feel free to correct me!
Take a look at llc tool source, spcifically compileModule() function. In short, it creates Target, sets some options for it via TargetOptions, then uses it to addPassesToEmitFile() and finally asks PassManager to perform all planned tasks.
I'd like to use LLVM lli tool as static library (rename main() to lli() and export it in libLLi.a) - to create rich UI for it. How can i modify it (or use without modifications) in order to intercept stdin?
Assume i know how to generate LLVM assembly file (using clang -S -emit-llvm .. -o output.ll) and how to execute it using lli tool (lli output.ll).
Common use case:
Source code of simple app to be interpreted by lli:
#include <iostream>
using namespace std;
int main() {
char name[128];
cout << "type your name: ";
cin.getline(name, sizeof(name));
cout << "hi, " << name << endl;
return 0;
}
I need to interpret LLVM assembly for it and to show InputBox when cin.getline invoked and show TextBox when cout << invoked (InputBox and TextBox are rich UI controls).
PS. I can't fork process and forward stdin/stdout of the whole child process.
lli is already a thin wrapper around llvm library functions, just use those instead. The main() function in tools/lli/lli.cpp is long only because it supports tons of flags to control every possible setting. After you strip it down it should be less than 10 lines to create an ExecutionEngine using an EngineBuilder and use it to run a llvm::Function.
You might also find chapter 4 of the Kaleidoscope tutorial helpful, where they add JIT support to the language. This also demonstrates how to use an EngineBuilder, though the ExecutionEngine they choose to build is a JIT instead of an Interpreter, you can customize it for your use case.
Now for the other part of your question, how do you trap stdin and stdout? LLVM is not a VM, the code is running in your process and using your stdin and stdout. My first suggestion is that since you already have the function in LLVM IR format, just run a transformation pass that replaces standard I/O functions with your own I/O functions. A simpler way to do that if you can get the ABI to line up, is to do the remapping with the ExecutionEngine. Call EE->updateGlobalMapping(functionDeclInIR, &replacementFunctionInNativeCode) to tell the ExecutionEngine that the Function* for functionDeclInIR is represented in native code by replacementFunctionInNativeCode. You would need to provide your own implementation of _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc (aka. ostream::operator<<) which uses your GUI.