// Written in the D programming language by Tomas Lindquist Olsen 2008 // Binding of llvm.c.Core values for D. // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // module llvm.llvm; import llvm.c.Core; import llvm.c.Ext; import llvm.c.BitWriter; import llvm.c.BitReader; import llvm.c.Analysis; import llvm.c.Target; public import llvm.type; public import llvm.builder; import llvm.util; /// class LLVMException : Exception { this(char[] msg) { super(msg); } } version(Tango) { import tango.stdc.stdlib; } else { import std.c.stdlib; } /// alias LLVMLinkage Linkage; /// alias LLVMIntPredicate IntPredicate; /// alias LLVMRealPredicate RealPredicate; /// alias LLVMCallConv CallConv; /// alias LLVMVisibility Visibility; /// alias LLVMValueKind ValueKind; /// class Module { /// global registry for 1:1 mapping of ModuleRef's -> Module's private static Module[LLVMModuleRef] registry; /// private LLVMModuleRef mod; const char[] name; /// this(char[] nam) { name = nam; mod = LLVMModuleCreateWithName(to_stringz(nam)); registry[mod] = this; } /// private this(LLVMModuleRef m) { name = null; mod = m; registry[m] = this; } /// static package Module GetExisting(LLVMModuleRef m) { if (auto p = m in registry) { return *p; } return new Module(m); } /// Create a module from bitcode. Returns the Module on success, null on failure. static Module GetFromBitcode(char[] bitcodepath, ref char[] errmsg) { LLVMModuleRef mref; LLVMMemoryBufferRef bref; char* msg; if (LLVMCreateMemoryBufferWithContentsOfFile(to_stringz(bitcodepath), &bref, &msg)) { errmsg = from_stringz(msg).dup; LLVMDisposeMessage(msg); throw new LLVMException(errmsg); } scope(exit) LLVMDisposeMemoryBuffer(bref); if (LLVMParseBitcode(bref, &mref, &msg)) { errmsg = from_stringz(msg).dup; LLVMDisposeMessage(msg); LLVMDisposeMemoryBuffer(bref); throw new LLVMException(errmsg); } return new Module(mref); } /// important to call this when done void dispose() { if (mod) { registry.remove(mod); LLVMDisposeModule(mod); mod = null; } } /// char[] dataLayout() { assert(mod !is null); return from_stringz(LLVMGetDataLayout(mod)); } /// void dataLayout(char[] dl) { assert(mod !is null); LLVMSetDataLayout(mod, to_stringz(dl)); } /// char[] target() { assert(mod !is null); return from_stringz(LLVMGetTarget(mod)); } /// void target(char[] dl) { assert(mod !is null); LLVMSetTarget(mod, to_stringz(dl)); } /// bool addTypeName(char[] nam, Type t) { assert(mod !is null); return LLVMAddTypeName(mod, to_stringz(nam), t.ll) != 0; } /// Type getTypeByName(char[] name) { return getTypeOf(LLVMGetTypeByName(mod, to_stringz(name))); } /// void deleteTypeName(char[] nam) { assert(mod !is null); LLVMDeleteTypeName(mod, to_stringz(nam)); } /// GlobalVariable addGlobal(Type t, char[] nam) { assert(mod !is null); auto c = LLVMAddGlobal(mod, t.ll, to_stringz(nam)); assert(c !is null); return new GlobalVariable(c, getTypeOf(c)); } /// Convenience method, type is taken to be that of the initializer GlobalVariable addGlobal(Constant initializer, char[] name) { auto global = addGlobal(initializer.type, name); global.initializer = initializer; return global; } /// GlobalValue getNamedGlobal(char[] nam) { assert(mod !is null); auto c = LLVMGetNamedGlobal(mod, to_stringz(nam)); if (c is null) return null; return cast(GlobalValue)getValueOf(c); } /// Function addFunction(Type t, char[] nam) { assert(mod !is null); auto c = LLVMAddFunction(mod, to_stringz(nam), t.ll); assert(c !is null); return new Function(c, getTypeOf(c)); } /// Function getNamedFunction(char[] nam) { assert(mod !is null); auto c = LLVMGetNamedFunction(mod, to_stringz(nam)); if (c is null) return null; return cast(Function)getValueOf(c); } /// Function getOrInsertFunction(Type t, char[] nam) { assert(mod !is null); auto c = LLVMGetOrInsertFunction(mod, to_stringz(nam), t.ll); assert(c !is null); return cast(Function)getValueOf(c); } /// Performs the same optimizations as `opt -std-compile-opts ...' would on the module. /// If inline is true, function inlining will be performed. void optimize(bool inline) { LLVMOptimizeModule(mod, inline); } /// Writes the module to an open file descriptor. Returns true on success. bool writeBitcodeToFileHandle(int handle) { return (LLVMWriteBitcodeToFileHandle(mod, handle) == 0); } /// Writes the module to the specified path. Returns 0 on success. bool writeBitcodeToFile(char[] path) { return (LLVMWriteBitcodeToFile(mod, to_stringz(path)) == 0); } /// Throws an exception if the module doesn't pass the LLVM verifier. void verify() { char* msg; if (LLVMVerifyModule(mod, LLVMVerifierFailureAction.ReturnStatus, &msg)) { auto errmsg = from_stringz(msg).dup; LLVMDisposeMessage(msg); throw new LLVMException(errmsg); } } } class ModuleProvider { /// private LLVMModuleProviderRef mp; /// private this(LLVMModuleProviderRef mp) { this.mp = mp; } /// Takes ownership of module, returns a ModuleProvider for it. static ModuleProvider GetForModule(Module m) { auto mp = LLVMCreateModuleProviderForExistingModule(m.mod); return new ModuleProvider(mp); } /// Destroys the provided module, unless this MP was passed to an ExecutionEngine. void dispose() { LLVMDisposeModuleProvider(mp); mp = null; } /// Returns a lazily-deserializing ModuleProvider static ModuleProvider GetFromBitcode(char[] filename) { LLVMMemoryBufferRef buf; char* msg; if (LLVMCreateMemoryBufferWithContentsOfFile(to_stringz(filename), &buf, &msg)) { auto errmsg = from_stringz(msg).dup; LLVMDisposeMessage(msg); throw new LLVMException(errmsg); } LLVMModuleProviderRef mp; // Takes ownership of buffer ... if (LLVMGetBitcodeModuleProvider(buf, &mp, &msg)) { // ... unless it fails, in which case we need to clean it up ourselves LLVMDisposeMemoryBuffer(buf); auto errmsg = from_stringz(msg).dup; LLVMDisposeMessage(msg); throw new LLVMException(errmsg); } return new ModuleProvider(mp); } /// package LLVMModuleProviderRef ll() { return mp; } } /// class Value { /// const LLVMValueRef value; /// const Type type; /// this(LLVMValueRef v, Type t=null) { value = v; if (t is null) t = getTypeOf(v); type = t; } /// char[] toString() { auto cstr = LLVMValueToString(value); auto result = from_stringz(cstr).dup; free(cstr); return result; } /// ValueKind kind() { return LLVMGetValueKind(value); } /// char[] name() { return from_stringz(LLVMGetValueName(value)); } /// void name(char[] s) { LLVMSetValueName(value, to_stringz(s)); } /// void dump() { LLVMDumpValue(value); } /// bool isConstant() { return LLVMIsConstant(value) != 0; } /// int opEquals(Object o) { auto v = cast(Value)o; if (v is null) return 0; if (value is v.value) return 1; return 0; } /// invalidates object void eraseFromParent() { LLVMEraseFromParent(value); } /// ditto void replaceAllUsesWith(Value newval) { LLVMReplaceAllUsesWith(value, newval.value); } /// only for call's void callConv(uint CC) { LLVMSetInstructionCallConv(value, CC); } /// ditto uint callConv() { return LLVMGetInstructionCallConv(value); } /// only for phi's void addIncoming(Value[] inValues, BasicBlock[] inBlocks) { auto n = inValues.length; assert(n == inBlocks.length); auto v = new LLVMValueRef[n]; auto b = new LLVMBasicBlockRef[n]; for (size_t i=0; i