[llvm-commits] Patch for llvm-c to expose targetmachine & allow emit obj/asm files
Hans Wennborg
hwennborg at google.com
Tue Apr 10 12:41:36 PDT 2012
(Including the list this time, sorry for the mess.)
On Fri, Apr 6, 2012 at 14:34, Carlo Kok <ck at remobjects.com> wrote:
> Attached is a fairly simple patch for llvm-c that exposes:
> * Target class
> * TargetMachine class
>
> To allow for emitting binary and assembly.
>
> This is the first time I try to contribute to llvm, if there's something
> wrong with my patch, let me know.
Hi Carlo,
Thanks for this! I've been annoyed in a project of my own that I
couldn't use the C bindings to emit objects or assembly.
I'm not very familiar with the classes you are wrapping, so someone
else should take a look too, but I have read through your patch and
made some comments below.
Thanks,
Hans
> +/*===-- llvm-c/TargetMachine.h - Target Machine Library C Interface - C++ -*-=*\
Shouldn't it be C rather than C++ at the top?
> +|* This header declares the C interface to libLLVMBitReader.a, which *|
> +|* implements input of the LLVM bitcode format. *|
> +|* *|
> +|* Many exotic languages can interoperate with C code but have a harder time *|
> +|* with C++ due to name mangling. So in addition to C, this interface enables *|
> +|* tools written in such languages. *|
I don't think this second paragraph is necessary?
> +typedef enum {
> + LLVMRelocDefault = 0,
> + LLVMRelocStatic = 1,
> + LLVMRelocPIC = 2,
> + LLVMRelocDynamicNoPic = 3
Looks like tabs have been used here instead of spaces.
Is there a reason that you set values for the enumerators here but not
in other enumerations such as LLVMCodeGenOptLevel?
> +// Target
Rather than this type of comments, I think proper Doxygen comments
would be awesome.
> +const char * LLVMGetTargetName(LLVMTargetRef T);
> +const char * LLVMGetTargetDescription(LLVMTargetRef T);
I think it's more common not to have a space between the * and the
function name.
> +// Target Machine
> +LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, char* Triple, char* CPU, char* Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel);
The * should go on the variable, not the type. This applies throughout
the patch (below, and in the .cpp file as well).
> +#ifdef __cplusplus
Maybe put some newlines before this, to separate it from the API.
> +namespace llvm {
> + class TargetMachine;
> + class Target;
> +
Trailing space on this line?
> + inline TargetMachine *unwrap(LLVMTargetMachineRef P) {
> + return reinterpret_cast<TargetMachine *>(P);
I think it's more common to leave out the space between the type and
the * here. This applies in the other (un)wrap methods below as well.
> +//===-- TargetMachine.cpp ----------------------------------------------------------===//
This line looks too long.
> +LLVMTargetRef LLVMGetFirstTarget()
> +{
The opening curly brace usually goes on the same line as the function
name in LLVM. This applies throughout this file.
> + const Target* target = &*TargetRegistry::begin();
> + return wrap(target);
> +}
I think there should be a blank line between each functions. This
applies below as well.
> +// Target
I don't think this comment adds much value.
> +const char * LLVMGetTargetName(LLVMTargetRef T)
There's a trailing whitespace at the end of this line, and also for
the function declarations below.
> +LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, char* Triple, char* CPU, char* Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel)
> +{
> + Reloc::Model RM = (Reloc::Model)Reloc;
> + CodeModel::Model CM = (CodeModel::Model)CodeModel;
> + CodeGenOpt::Level OL = (CodeGenOpt::Level)Level;
I think it's more common to use static_cast here rather than c-style casts.
> +LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, char* Filename, LLVMCodeGenFileType codegen, char** ErrorMessage)
> +{ // Inspired by the D binding
> + TargetMachine* TM = unwrap(T);
> + Module* Mod = unwrap(M);
> +
> + FunctionPassManager pass(Mod);
Wouldn't it be better to use a PassManager here, that you can run over the
Module once, rather than iterating over each function?
> + if (!td) {
> + error = "No TargetData in TargetMachine";
> + *ErrorMessage = strdup(error.c_str());
> + return true;
Looks like tabs on the two previous lines.
> + pass.add(new TargetData(*td));
> +
Trailing whitespace.
> + TargetMachine::CodeGenFileType ft = (TargetMachine::CodeGenFileType)codegen;
static_cast instead of c-style cast
> + raw_fd_ostream dest(Filename, error, raw_fd_ostream::F_Binary);
> + formatted_raw_ostream destf(dest);
> + if (!error.empty()) {
> + *ErrorMessage = strdup(error.c_str());
> + return true;
Tab
> + }
> +
Trailing whitespace
> + if (TM->addPassesToEmitFile(pass, destf, ft)) {
> + error = "No TargetData in TargetMachine";
> + *ErrorMessage = strdup(error.c_str());
> + return true;
Tabs
> + }
> +
> + pass.doInitialization();
> +
> + for (llvm::Module::iterator it = Mod->begin(), end = Mod->end(); it != end; ++it){
If you had a PassManager instead of a FunctionPassManager, you could just do
PM.run(*Mod);
> + errs() << "Did 1 iteration";
> + if (!it->isDeclaration()) {
> + errs() << "Did 1 proper iterations";
> + pass.run(*it);
> + }
Tabs.
> + }
> + errs() << "Done";
You probably want to remove the printouts to errs :)
More information about the llvm-commits
mailing list