From da85049eb9efbb6174dc73e07914e2060fc50f15 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 13:44:59 -0600 Subject: [PATCH] Add support to emit assembly. --- newbinding/include/llvm_binding/extra.h | 31 ++++++++++++++++++++ newbinding/src/Support/FormattedStream.py | 9 ++++++ newbinding/src/Support/TargetSelect.py | 9 ++++++ newbinding/src/Support/raw_ostream.py | 1 + newbinding/src/Target/TargetMachine.py | 17 +++++++++++ newbinding/test_binding.py | 35 +++++++++++++++++++++++ 6 files changed, 102 insertions(+) create mode 100644 newbinding/src/Support/FormattedStream.py diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index e8f39cb..77b399d 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -465,3 +466,33 @@ PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf, delete MB; return PyString_FromString(Triple.c_str()); } + +static +PyObject* TargetMachine_addPassesToEmitFile( + llvm::TargetMachine *TM, + llvm::PassManagerBase & PM, + PyObject* Out, + llvm::TargetMachine::CodeGenFileType FTy, + bool disableVerify=true) +{ + using namespace llvm; + llvm::SmallVector sv; + raw_svector_ostream rso(sv); + formatted_raw_ostream fso(rso); + fso.flush(); + bool status = TM->addPassesToEmitFile(PM, fso, FTy, disableVerify); + if (status) { + StringRef sr = rso.str(); + PyObject* buf = PyString_FromStringAndSize(sr.data(), sr.size()); + if (!buf) { + return NULL; + } + if ( -1 == PyFile_WriteObject(buf, Out, Py_PRINT_RAW) ){ + return NULL; + } + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + diff --git a/newbinding/src/Support/FormattedStream.py b/newbinding/src/Support/FormattedStream.py new file mode 100644 index 0000000..17c259b --- /dev/null +++ b/newbinding/src/Support/FormattedStream.py @@ -0,0 +1,9 @@ +from binding import * +from ..namespace import llvm +from raw_ostream import raw_ostream + +@llvm.Class(raw_ostream) +class formatted_raw_ostream: + _include_ = 'llvm/Support/FormattedStream.h' + new = Constructor(ref(raw_ostream), cast(bool, Bool)) + diff --git a/newbinding/src/Support/TargetSelect.py b/newbinding/src/Support/TargetSelect.py index 4a2b171..208ef4b 100644 --- a/newbinding/src/Support/TargetSelect.py +++ b/newbinding/src/Support/TargetSelect.py @@ -6,3 +6,12 @@ llvm.includes.add('llvm/Support/TargetSelect.h') InitializeNativeTarget = llvm.Function('InitializeNativeTarget') #llvm.Function('InitializeAllTargets') +InitializeNativeTargetAsmPrinter = llvm.Function( + 'InitializeNativeTargetAsmPrinter', cast(Bool, bool)) + +InitializeNativeTargetAsmParser = llvm.Function( + 'InitializeNativeTargetAsmParser', cast(Bool, bool)) + +InitializeNativeTargetDisassembler = llvm.Function( + 'InitializeNativeTargetDisassembler', cast(Bool, bool)) + diff --git a/newbinding/src/Support/raw_ostream.py b/newbinding/src/Support/raw_ostream.py index ecf3614..dcce73f 100644 --- a/newbinding/src/Support/raw_ostream.py +++ b/newbinding/src/Support/raw_ostream.py @@ -7,6 +7,7 @@ from ..ADT.StringRef import StringRef class raw_ostream: _include_ = "llvm/Support/raw_ostream.h" delete = Destructor() + flush = Method() @llvm.Class(raw_ostream) class raw_svector_ostream: diff --git a/newbinding/src/Target/TargetMachine.py b/newbinding/src/Target/TargetMachine.py index 3fc16e2..e60ed5c 100644 --- a/newbinding/src/Target/TargetMachine.py +++ b/newbinding/src/Target/TargetMachine.py @@ -7,12 +7,20 @@ from ..Support.Target import Target from ..DataLayout import DataLayout from ..TargetTransformInfo import (ScalarTargetTransformInfo, VectorTargetTransformInfo) +from ..PassManager import PassManagerBase +from ..Support.FormattedStream import formatted_raw_ostream TargetMachine = llvm.Class() @TargetMachine class TargetMachine: _include_ = 'llvm/Target/TargetMachine.h' + + CodeGenFileType = Enum(''' + CGFT_AssemblyFile + CGFT_ObjectFile + CGFT_Null''') + delete = Destructor() getTarget = Method(const(ref(Target))) @@ -34,3 +42,12 @@ class TargetMachine: ownedptr(ScalarTargetTransformInfo))) getVectorTargetTransformInfo = Method(const( ownedptr(VectorTargetTransformInfo))) + + addPassesToEmitFile = Method(cast(bool, Bool), + ref(PassManagerBase), + ref(formatted_raw_ostream), + CodeGenFileType, + cast(bool, Bool) + ).require_only(3) + + diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 8a72aef..1321eb6 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -6,6 +6,7 @@ api.capsule.set_debug(True) def test_basic_jit_use(): api.InitializeNativeTarget() + api.InitializeNativeTargetAsmPrinter() context = api.getGlobalContext() m = api.Module.new("modname", context) @@ -157,6 +158,16 @@ def test_engine_builder(): m = api.Module.new("modname", context) + int32ty = api.Type.getIntNTy(context, 32) + fnty = api.FunctionType.get(int32ty, [int32ty], False) + fn = m.getOrInsertFunction("foo", fnty)._downcast(api.Function) + bb = api.BasicBlock.Create(context, "entry", fn, None) + builder = api.IRBuilder.new(context) + builder.SetInsertPoint(bb) + builder.CreateRet(fn.getArgumentList()[0]) + + print fn + eb = api.EngineBuilder.new(m) eb2 = eb.setEngineKind(api.EngineKind.Kind.JIT) assert eb is eb2 @@ -192,6 +203,30 @@ def test_engine_builder(): pm.add(api.DataLayout.new(str(tm.getDataLayout()))) pm.add(api.TargetLibraryInfo.new()) + # write assembly + pm = api.PassManager.new() + pm.add(api.DataLayout.new(str(tm.getDataLayout()))) + + raw = extra.make_raw_ostream_for_printing() + formatted = api.formatted_raw_ostream.new(raw, False) + + cgft = api.TargetMachine.CodeGenFileType.CGFT_AssemblyFile + failed = tm.addPassesToEmitFile(pm, formatted, cgft, False) + assert not failed + + pm.run(m) + + formatted.flush() + raw.flush() + asm = raw.str() + print asm + assert 'foo' in asm + + + + + + def main(): for name, value in globals().items():