From 3e0dc2507010b8f655ff07c698de387ac1ffb187 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 10 May 2013 10:58:51 -0500 Subject: [PATCH 001/149] Silent capsule memory logger. --- llvmpy/capsule.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 9c1e86a..f66836f 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -3,6 +3,15 @@ from collections import defaultdict import logging logger = logging.getLogger(__name__) +def silent_logger(): + ''' + Silent logger for unless we have a error message. + ''' + logger.setLevel(logging.ERROR) + +# comment out the line below to re-enable logging at DEBUG level. +silent_logger() + def set_debug(enabled): ''' Side-effect: configure logger with it is not configured. From c1184271188a0c7d4cea1a74d241fc2e53b89936 Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Tue, 14 May 2013 04:26:10 -0500 Subject: [PATCH 002/149] Don't get name field from literal structure and avoid a segfault. --- llvm/core.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index 478728b..453f1a8 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -879,7 +879,10 @@ class StructType(Type): self._ptr.setName(name) def _get_name(self): - return self._ptr.getName() + if self._ptr.isLiteral(): + return "" + else: + return self._ptr.getName() name = property(_get_name, _set_name) From 08bed7dd7432692e681f2a2e9d3fe773d7943162 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 14 May 2013 10:32:37 -0500 Subject: [PATCH 003/149] Fix bug with Module.to_bitcode() (Reported by Jun Koi) --- llvm/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index 453f1a8..b085339 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -535,7 +535,7 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = BytesIO + fileobj = BytesIO() api.llvm.WriteBitcodeToFile(self._ptr, fileobj) if ret: return fileobj.getvalue() From f4b320ff09e7b9756e1b799b4df20fd4e7482520 Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Tue, 14 May 2013 00:51:45 -0500 Subject: [PATCH 004/149] Fix a few erros. Add an array type --- llvm_array/__init__.py | 2 + llvm_array/array.py | 144 +++++++++++++++++++++++++++++++++ llvmpy/src/Function.py | 7 +- llvmpy/src/Value.py | 1 + llvmpy/src/ValueSymbolTable.py | 13 +++ setup.py | 1 + 6 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 llvm_array/__init__.py create mode 100644 llvm_array/array.py create mode 100644 llvmpy/src/ValueSymbolTable.py diff --git a/llvm_array/__init__.py b/llvm_array/__init__.py new file mode 100644 index 0000000..f6a0f3f --- /dev/null +++ b/llvm_array/__init__.py @@ -0,0 +1,2 @@ +from __future__ import absolute_imports +from .array.py import * diff --git a/llvm_array/array.py b/llvm_array/array.py new file mode 100644 index 0000000..12df60e --- /dev/null +++ b/llvm_array/array.py @@ -0,0 +1,144 @@ +# This should be moved to llvmpy +# +# There are different array kinds parameterized by eltype and nd +# +# Contiguous or Fortran +# struct { +# eltype *data; +# intp shape[nd]; +# } contiguous_array(eltype, nd) +# +# struct { +# eltype *data; +# diminfo shape[nd]; +# } strided_array(eltype, nd) +# +# struct { +# eltype *data; +# intp shape[nd]; +# intp stride[nd]; +# } strided_soa_array(eltype, nd) +# +# struct { +# intp dim; +# intp stride; +#} diminfo +# + +import llvm.core as lc +from llvm.core import Type +import llvm_cbuilder.shortnames as C + +CONTIGUOUS = 1 << 8 +STRIDED = CONTIGUOUS + 1 +STRIDED_SOA = CONTIGUOUS + 2 + +array_kinds = (CONTIGUOUS, STRIDED, STRIDED_SOA) + +void_type = C.void +int_type = C.int +char_type = C.char +int16_type = C.int16 +intp_type = C.intp + +diminfo_type = Type.struct([intp_type, # shape + intp_type # stride + ], name='diminfo') + +# This is the way we define LLVM arrays. +def cont_array_type(nd, el_type=char_type, name=''): + terms = [Type.pointer(el_type), # data + Type.array(intp_type, nd) # shape + ] + return Type.struct(terms, name=name) + +def strided_array_type(nd, el_type=char_type, name=''): + terms = [Type.pointer(el_type), # data + Type.array(diminfo_type, nd) # diminfo + ] + return Type.struct(terms, name=name) + +def strided_soa_type(nd, el_type=char_type, name=''): + terms = [Type.pointer(el_type), # data + Type.array(intp_type, nd), # shape[nd] + Type.array(intp_type, nd) # strides[nd] + ] + return Type.struct(terms, name=name) + +def check_array(arrtyp): + if not isinstance(arrtyp, lc.StructType): + return None + if arrtyp.element_count not in [2, 3]: + return None + if not isinstance(arrtyp.elements[0], lc.PointerType) or \ + not isinstance(arrtyp.elements[1], lc.ArrayType): + return None + + data_type = arrtyp.elements[0].pointee + s1 = arrtyp.elements[1] + nd = s1.count + + if arrtyp.element_count == 3: + if not isinstance(arrtyp.elements[2], lc.ArrayType): + return None + s2 = arrtyp.elements[2] + if s1.element != intp_type or s2.element != intp_type: + return None + if s1.count != s2.count: + return None + return STRIDED_SOA, nd, data_type + + if s1.element == diminfo_type: + return STRIDED, nd, data_type + elif s1.element == intp_type: + return CONTIGUOUS, nd, data_type + else: + return None + +def is_cont_array(arrtyp): + if not isinstance(arrtyp, lc.StructType): + return False + if arrtyp.element_count != 2 or \ + not isinstance(arrtyp.elements[0], lc.PointerType) or \ + not isinstance(arrtyp.elements[1], lc.ArrayType): + return False + if arrtyp.elements[1].element != intp_type: + return False + return True + +def is_strided_array(arrtyp, kind=diminfo_type): + if not isinstance(arrtyp, lc.StructType): + return False + if arrtyp.element_count != 2 or \ + not isinstance(arrtyp.elements[0], lc.PointerType) or \ + not isinstance(arrtyp.elements[1], lc.ArrayType): + return False + if arrtyp.elements[1].element != kind: + return False + return True + +def is_strided_soa_array(arrtyp): + if not isinstance(arrtyp, lc.StructType): + return False + if arrtyp.element_count != 3 or \ + not isinstance(arrtyp.elements[0], lc.PointerType) or \ + not isinstance(arrtyp.elements[1], lc.ArrayType) or \ + not isinstance(arrtyp.elements[2], lc.ArrayType): + return False + s1, s2 = arrtyp.elements[1:] + if s1.element != intp_type or s2.element != intp_type: + return False + if s1.count != s2.count: + return False + return True + +def test(): + arr = cont_array_type(5) + assert check_array(arr) == (CONTIGUOUS, 5, char_type) + arr = strided_array_type(4) + assert check_array(arr) == (STRIDED, 4, char_type) + arr = strided_soa_type(3) + assert check_array(arr) == (STRIDED_SOA, 3, char_type) + +if __name__ == '__main__': + test() \ No newline at end of file diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index 55a50d9..c453fd1 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -2,6 +2,7 @@ from binding import * from .namespace import llvm from .Value import GlobalValue, Constant, Function, Argument, Value from .BasicBlock import BasicBlock +from .ValueSymbolTable import ValueSymbolTable from .Attributes import Attributes from .Type import Type from .DerivedTypes import FunctionType @@ -23,7 +24,7 @@ class Function: getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) - hasGC = Method(cast(bool, Bool)) + hasGC = Method(cast(Bool, bool)) getGC = Method(cast(ConstCharPtr, str)) setGC = Method(Void, cast(str, ConstCharPtr)) @@ -31,6 +32,7 @@ class Function: getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr) getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr) getEntryBlock = Method(ref(BasicBlock)) + getValueSymbolTable = Method(ref(ValueSymbolTable)) copyAttributesFrom = Method(Void, ptr(GlobalValue)) @@ -49,6 +51,9 @@ class Function: addFnAttr = Method(Void, Attributes.AttrVal) removeFnAttr = Method(Void, ref(Attributes)) + #hasFnAttribute = Method(cast(Bool, bool), Attributes.AttrVal) + + Create = Method(ptr(Function)) eraseFromParent = Method() eraseFromParent.disowning = True diff --git a/llvmpy/src/Value.py b/llvmpy/src/Value.py index fb9c3cc..922850f 100644 --- a/llvmpy/src/Value.py +++ b/llvmpy/src/Value.py @@ -8,6 +8,7 @@ MDNode = llvm.Class(Value) MDString = llvm.Class(Value) User = llvm.Class(Value) BasicBlock = llvm.Class(Value) +ValueSymbolTable = llvm.Class() Constant = llvm.Class(User) GlobalValue = llvm.Class(Constant) Function = llvm.Class(GlobalValue) diff --git a/llvmpy/src/ValueSymbolTable.py b/llvmpy/src/ValueSymbolTable.py new file mode 100644 index 0000000..862febc --- /dev/null +++ b/llvmpy/src/ValueSymbolTable.py @@ -0,0 +1,13 @@ +from binding import * +from .Value import ValueSymbolTable, Value +from .ADT.StringRef import StringRef + +@ValueSymbolTable +class ValueSymbolTable: + new = Constructor() + delete = Destructor() + lookup = Method(ptr(Value), cast(str, StringRef)) + empty = Method(cast(Bool, bool)) + size = Method(cast(Unsigned, int)) + dump = Method(Void) + diff --git a/setup.py b/setup.py index b74ec71..1dc8af8 100644 --- a/setup.py +++ b/setup.py @@ -180,6 +180,7 @@ setup( packages = ['llvm', 'llvm.workaround', 'llvm_cbuilder', 'llpython', + 'llvm_array', 'llvmpy.api', 'llvmpy.api.llvm'], py_modules = ['llvmpy', 'llvmpy._capsule', From db7323771fbc72b9dd08781445797f906be43915 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 14 May 2013 11:23:50 -0500 Subject: [PATCH 005/149] Fix PR --- llvmpy/src/Function.py | 7 ++++++- llvmpy/src/ValueSymbolTable.py | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index c453fd1..04c3e65 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -1,6 +1,7 @@ from binding import * from .namespace import llvm from .Value import GlobalValue, Constant, Function, Argument, Value +from .Module import Module from .BasicBlock import BasicBlock from .ValueSymbolTable import ValueSymbolTable from .Attributes import Attributes @@ -53,7 +54,11 @@ class Function: removeFnAttr = Method(Void, ref(Attributes)) #hasFnAttribute = Method(cast(Bool, bool), Attributes.AttrVal) - Create = Method(ptr(Function)) + Create = StaticMethod(ptr(Function), + ptr(FunctionType), + GlobalValue.LinkageTypes, + cast(str, ConstCharPtr), + ptr(Module)).require_only(2) eraseFromParent = Method() eraseFromParent.disowning = True diff --git a/llvmpy/src/ValueSymbolTable.py b/llvmpy/src/ValueSymbolTable.py index 862febc..7e8890c 100644 --- a/llvmpy/src/ValueSymbolTable.py +++ b/llvmpy/src/ValueSymbolTable.py @@ -4,6 +4,7 @@ from .ADT.StringRef import StringRef @ValueSymbolTable class ValueSymbolTable: + _include_ = 'llvm/ValueSymbolTable.h' new = Constructor() delete = Destructor() lookup = Method(ptr(Value), cast(str, StringRef)) From 331f71f26f13431b07c9c5d37dda935fdbcd8059 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 16 May 2013 11:34:27 -0500 Subject: [PATCH 006/149] Fix hashing of llvm type --- llvm/core.py | 4 +++- llvm/test_llvmpy.py | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index b085339..d25dec1 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -800,6 +800,9 @@ class Type(llvm.Wrapper): def __str__(self): return str(self._ptr) + def __hash__(self): + return hash(self._ptr) + def __eq__(self, rhs): return self._ptr is rhs._ptr @@ -901,7 +904,6 @@ class StructType(Type): def is_layout_identical(self, other): return self._ptr.isLayoutIdentical(other._ptr) - class ArrayType(Type): """Represents an array type.""" _type_ = api.llvm.ArrayType diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index b228138..36ea022 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1258,6 +1258,32 @@ class TestStruct(TestCase): tests.append(TestStruct) +# --------------------------------------------------------------------------- + +class TestTypeHash(TestCase): + def test_scalar_type(self): + i32a = Type.int(32) + i32b = Type.int(32) + i64a = Type.int(64) + i64b = Type.int(64) + ts = set([i32a, i32b, i64a, i64b]) + self.assertTrue(len(ts)) + self.assertTrue(i32a in ts) + self.assertTrue(i64b in ts) + + def test_struct_type(self): + ta = Type.struct([Type.int(32), Type.float()]) + tb = Type.struct([Type.int(32), Type.float()]) + tc = Type.struct([Type.int(32), Type.int(32), Type.float()]) + ts = set([ta, tb, tc]) + self.assertTrue(len(ts) == 2) + self.assertTrue(ta in ts) + self.assertTrue(tb in ts) + self.assertTrue(tc in ts) + +tests.append(TestTypeHash) + + # --------------------------------------------------------------------------- def run(verbosity=1): From 592f9c698819e9efacd7d340eb27a03fd887770f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 16 May 2013 13:45:59 -0500 Subject: [PATCH 007/149] Allow retrieving argument attributes --- llvm/core.py | 38 ++++++++++++++++++++++++++++++++++++++ llvm/test_llvmpy.py | 18 ++++++++++++++++++ llvmpy/src/Argument.py | 10 ++++++++++ 3 files changed, 66 insertions(+) diff --git a/llvm/core.py b/llvm/core.py index d25dec1..74d7101 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1372,6 +1372,8 @@ class GlobalVariable(GlobalValue): class Argument(Value): _type_ = api.llvm.Argument + _valid_attrs = frozenset([ATTR_BY_VAL, ATTR_NEST, ATTR_NO_ALIAS, + ATTR_NO_CAPTURE, ATTR_STRUCT_RET]) def add_attribute(self, attr): context = api.llvm.getGlobalContext() @@ -1379,6 +1381,9 @@ class Argument(Value): attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttr(attrs) + if attr not in self: + raise ValueError("Attribute %s is not valid for arg %s" % + (attr, self)) def remove_attribute(self, attr): context = api.llvm.getGlobalContext() @@ -1400,6 +1405,39 @@ class Argument(Value): alignment = property(_get_alignment, _set_alignment) + def __contains__(self, attr): + if attr == ATTR_BY_VAL: + return self.has_by_val() + elif attr == ATTR_NEST: + return self.has_nest() + elif attr == ATTR_NO_ALIAS: + return self.has_no_alias() + elif attr == ATTR_NO_CAPTURE: + return self.has_no_capture() + elif attr == ATTR_STRUCT_RET: + return self.has_struct_ret() + else: + raise ValueError('invalid attribute for argument') + + @property + def arg_no(self): + return self._ptr.getArgNo() + + def has_by_val(self): + return self._ptr.hasByValAttr() + + def has_nest(self): + return self._ptr.hasNestAttr() + + def has_no_alias(self): + return self._ptr.hasNoAliasAttr() + + def has_no_capture(self): + return self._ptr.hasNoCaptureAttr() + + def has_struct_ret(self): + return self._ptr.hasStructRetAttr() + class Function(GlobalValue): _type_ = api.llvm.Function diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 36ea022..3ecffff 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1283,6 +1283,24 @@ class TestTypeHash(TestCase): tests.append(TestTypeHash) +# --------------------------------------------------------------------------- + +class TestArgAttr(TestCase): + def test_arg_attr(self): + m = Module.new('oifjda') + vptr = Type.pointer(Type.float()) + sptr = Type.pointer(Type.struct([])) + fnty = Type.function(Type.void(), [vptr] * 5) + func = m.add_function(fnty, 'foo') + attrs = [lc.ATTR_STRUCT_RET, lc.ATTR_BY_VAL, lc.ATTR_NEST, + lc.ATTR_NO_ALIAS, lc.ATTR_NO_CAPTURE] + for i, attr in enumerate(attrs): + arg = func.args[i] + self.assertEqual(i, arg.arg_no) + arg.add_attribute(attr) + self.assertTrue(attr in func.args[i]) + +tests.append(TestArgAttr) # --------------------------------------------------------------------------- diff --git a/llvmpy/src/Argument.py b/llvmpy/src/Argument.py index babbd1c..6262147 100644 --- a/llvmpy/src/Argument.py +++ b/llvmpy/src/Argument.py @@ -13,3 +13,13 @@ class Argument: removeAttr = Method(Void, ref(Attributes)) getParamAlignment = Method(cast(Unsigned, int)) + getArgNo = Method(cast(Unsigned, int)) + + hasByValAttr = Method(cast(Bool, bool)) + hasNestAttr = Method(cast(Bool, bool)) + hasNoAliasAttr = Method(cast(Bool, bool)) + hasNoCaptureAttr = Method(cast(Bool, bool)) + hasStructRetAttr = Method(cast(Bool, bool)) + + if LLVM_VERSION > (3, 2): + hasReturnedAttr = Method(cast(Bool, bool)) From 96dc9076134a7507e88cdf7d715f937d09a8a083 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 16 May 2013 13:46:57 -0500 Subject: [PATCH 008/149] Make enum integer constants prints name --- llvm/core.py | 451 +++++++++++++++++++++++++++++---------------------- 1 file changed, 256 insertions(+), 195 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 74d7101..9cb1946 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -47,144 +47,189 @@ from llvmpy import api #===----------------------------------------------------------------------=== # Enumerations #===----------------------------------------------------------------------=== +class Enum(int): + '''Overload integer to print the name of the enum. + ''' + def __repr__(self): + return '%s(%d)' % (type(self).__name__, self) + + @classmethod + def declare(cls): + scope = globals() + for name in filter(lambda s: s.startswith(cls.prefix), dir(cls)): + n = getattr(cls, name) + typ = type(name, (cls,), {}) + scope[name] = typ(n) + # type id (llvm::Type::TypeID) -TYPE_VOID = api.llvm.Type.TypeID.VoidTyID -TYPE_HALF = api.llvm.Type.TypeID.HalfTyID -TYPE_FLOAT = api.llvm.Type.TypeID.FloatTyID -TYPE_DOUBLE = api.llvm.Type.TypeID.DoubleTyID -TYPE_X86_FP80 = api.llvm.Type.TypeID.X86_FP80TyID -TYPE_FP128 = api.llvm.Type.TypeID.FP128TyID -TYPE_PPC_FP128 = api.llvm.Type.TypeID.PPC_FP128TyID -TYPE_LABEL = api.llvm.Type.TypeID.LabelTyID -TYPE_INTEGER = api.llvm.Type.TypeID.IntegerTyID -TYPE_FUNCTION = api.llvm.Type.TypeID.FunctionTyID -TYPE_STRUCT = api.llvm.Type.TypeID.StructTyID -TYPE_ARRAY = api.llvm.Type.TypeID.ArrayTyID -TYPE_POINTER = api.llvm.Type.TypeID.PointerTyID -TYPE_VECTOR = api.llvm.Type.TypeID.VectorTyID -TYPE_METADATA = api.llvm.Type.TypeID.MetadataTyID -TYPE_X86_MMX = api.llvm.Type.TypeID.X86_MMXTyID +class TypeEnum(Enum): + prefix = 'TYPE_' + TypeID = api.llvm.Type.TypeID + + TYPE_VOID = TypeID.VoidTyID + TYPE_HALF = TypeID.HalfTyID + TYPE_FLOAT = TypeID.FloatTyID + TYPE_DOUBLE = TypeID.DoubleTyID + TYPE_X86_FP80 = TypeID.X86_FP80TyID + TYPE_FP128 = TypeID.FP128TyID + TYPE_PPC_FP128 = TypeID.PPC_FP128TyID + TYPE_LABEL = TypeID.LabelTyID + TYPE_INTEGER = TypeID.IntegerTyID + TYPE_FUNCTION = TypeID.FunctionTyID + TYPE_STRUCT = TypeID.StructTyID + TYPE_ARRAY = TypeID.ArrayTyID + TYPE_POINTER = TypeID.PointerTyID + TYPE_VECTOR = TypeID.VectorTyID + TYPE_METADATA = TypeID.MetadataTyID + TYPE_X86_MMX = TypeID.X86_MMXTyID + +TypeEnum.declare() # value IDs (llvm::Value::ValueTy enum) # According to the doxygen docs, it is not a good idea to use these enums. # There are more values than those declared. -VALUE_ARGUMENT = api.llvm.Value.ValueTy.ArgumentVal -VALUE_BASIC_BLOCK = api.llvm.Value.ValueTy.BasicBlockVal -VALUE_FUNCTION = api.llvm.Value.ValueTy.FunctionVal -VALUE_GLOBAL_ALIAS = api.llvm.Value.ValueTy.GlobalAliasVal -VALUE_GLOBAL_VARIABLE = api.llvm.Value.ValueTy.GlobalVariableVal -VALUE_UNDEF_VALUE = api.llvm.Value.ValueTy.UndefValueVal -VALUE_BLOCK_ADDRESS = api.llvm.Value.ValueTy.BlockAddressVal -VALUE_CONSTANT_EXPR = api.llvm.Value.ValueTy.ConstantExprVal -VALUE_CONSTANT_AGGREGATE_ZERO = api.llvm.Value.ValueTy.ConstantAggregateZeroVal -VALUE_CONSTANT_DATA_ARRAY = api.llvm.Value.ValueTy.ConstantDataArrayVal -VALUE_CONSTANT_DATA_VECTOR = api.llvm.Value.ValueTy.ConstantDataVectorVal -VALUE_CONSTANT_INT = api.llvm.Value.ValueTy.ConstantIntVal -VALUE_CONSTANT_FP = api.llvm.Value.ValueTy.ConstantFPVal -VALUE_CONSTANT_ARRAY = api.llvm.Value.ValueTy.ConstantArrayVal -VALUE_CONSTANT_STRUCT = api.llvm.Value.ValueTy.ConstantStructVal -VALUE_CONSTANT_VECTOR = api.llvm.Value.ValueTy.ConstantVectorVal -VALUE_CONSTANT_POINTER_NULL = api.llvm.Value.ValueTy.ConstantPointerNullVal -VALUE_MD_NODE = api.llvm.Value.ValueTy.MDNodeVal -VALUE_MD_STRING = api.llvm.Value.ValueTy.MDStringVal -VALUE_INLINE_ASM = api.llvm.Value.ValueTy.InlineAsmVal -VALUE_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.PseudoSourceValueVal -VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.FixedStackPseudoSourceValueVal -VALUE_INSTRUCTION = api.llvm.Value.ValueTy.InstructionVal +class ValueEnum(Enum): + prefix = 'VALUE_' + ValueTy = api.llvm.Value.ValueTy + + VALUE_ARGUMENT = ValueTy.ArgumentVal + VALUE_BASIC_BLOCK = ValueTy.BasicBlockVal + VALUE_FUNCTION = ValueTy.FunctionVal + VALUE_GLOBAL_ALIAS = ValueTy.GlobalAliasVal + VALUE_GLOBAL_VARIABLE = ValueTy.GlobalVariableVal + VALUE_UNDEF_VALUE = ValueTy.UndefValueVal + VALUE_BLOCK_ADDRESS = ValueTy.BlockAddressVal + VALUE_CONSTANT_EXPR = ValueTy.ConstantExprVal + VALUE_CONSTANT_AGGREGATE_ZERO = ValueTy.ConstantAggregateZeroVal + VALUE_CONSTANT_DATA_ARRAY = ValueTy.ConstantDataArrayVal + VALUE_CONSTANT_DATA_VECTOR = ValueTy.ConstantDataVectorVal + VALUE_CONSTANT_INT = ValueTy.ConstantIntVal + VALUE_CONSTANT_FP = ValueTy.ConstantFPVal + VALUE_CONSTANT_ARRAY = ValueTy.ConstantArrayVal + VALUE_CONSTANT_STRUCT = ValueTy.ConstantStructVal + VALUE_CONSTANT_VECTOR = ValueTy.ConstantVectorVal + VALUE_CONSTANT_POINTER_NULL = ValueTy.ConstantPointerNullVal + VALUE_MD_NODE = ValueTy.MDNodeVal + VALUE_MD_STRING = ValueTy.MDStringVal + VALUE_INLINE_ASM = ValueTy.InlineAsmVal + VALUE_PSEUDO_SOURCE_VALUE = ValueTy.PseudoSourceValueVal + VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = ValueTy.FixedStackPseudoSourceValueVal + VALUE_INSTRUCTION = ValueTy.InstructionVal + +ValueEnum.declare() # instruction opcodes (from include/llvm/Instruction.def) -OPCODE_RET = 1 -OPCODE_BR = 2 -OPCODE_SWITCH = 3 -OPCODE_INDIRECT_BR = 4 -OPCODE_INVOKE = 5 -OPCODE_RESUME = 6 -OPCODE_UNREACHABLE = 7 -OPCODE_ADD = 8 -OPCODE_FADD = 9 -OPCODE_SUB = 10 -OPCODE_FSUB = 11 -OPCODE_MUL = 12 -OPCODE_FMUL = 13 -OPCODE_UDIV = 14 -OPCODE_SDIV = 15 -OPCODE_FDIV = 16 -OPCODE_UREM = 17 -OPCODE_SREM = 18 -OPCODE_FREM = 19 -OPCODE_SHL = 20 -OPCODE_LSHR = 21 -OPCODE_ASHR = 22 -OPCODE_AND = 23 -OPCODE_OR = 24 -OPCODE_XOR = 25 -OPCODE_ALLOCA = 26 -OPCODE_LOAD = 27 -OPCODE_STORE = 28 -OPCODE_GETELEMENTPTR = 29 -OPCODE_FENCE = 30 -OPCODE_ATOMICCMPXCHG = 31 -OPCODE_ATOMICRMW = 32 -OPCODE_TRUNC = 33 -OPCODE_ZEXT = 34 -OPCODE_SEXT = 35 -OPCODE_FPTOUI = 36 -OPCODE_FPTOSI = 37 -OPCODE_UITOFP = 38 -OPCODE_SITOFP = 39 -OPCODE_FPTRUNC = 40 -OPCODE_FPEXT = 41 -OPCODE_PTRTOINT = 42 -OPCODE_INTTOPTR = 43 -OPCODE_BITCAST = 44 -OPCODE_ICMP = 45 -OPCODE_FCMP = 46 -OPCODE_PHI = 47 -OPCODE_CALL = 48 -OPCODE_SELECT = 49 -OPCODE_USEROP1 = 50 -OPCODE_USEROP2 = 51 -OPCODE_VAARG = 52 -OPCODE_EXTRACTELEMENT = 53 -OPCODE_INSERTELEMENT = 54 -OPCODE_SHUFFLEVECTOR = 55 -OPCODE_EXTRACTVALUE = 56 -OPCODE_INSERTVALUE = 57 -OPCODE_LANDINGPAD = 58 +class OpcodeEnum(Enum): + prefix = 'OPCODE_' + + OPCODE_RET = 1 + OPCODE_BR = 2 + OPCODE_SWITCH = 3 + OPCODE_INDIRECT_BR = 4 + OPCODE_INVOKE = 5 + OPCODE_RESUME = 6 + OPCODE_UNREACHABLE = 7 + OPCODE_ADD = 8 + OPCODE_FADD = 9 + OPCODE_SUB = 10 + OPCODE_FSUB = 11 + OPCODE_MUL = 12 + OPCODE_FMUL = 13 + OPCODE_UDIV = 14 + OPCODE_SDIV = 15 + OPCODE_FDIV = 16 + OPCODE_UREM = 17 + OPCODE_SREM = 18 + OPCODE_FREM = 19 + OPCODE_SHL = 20 + OPCODE_LSHR = 21 + OPCODE_ASHR = 22 + OPCODE_AND = 23 + OPCODE_OR = 24 + OPCODE_XOR = 25 + OPCODE_ALLOCA = 26 + OPCODE_LOAD = 27 + OPCODE_STORE = 28 + OPCODE_GETELEMENTPTR = 29 + OPCODE_FENCE = 30 + OPCODE_ATOMICCMPXCHG = 31 + OPCODE_ATOMICRMW = 32 + OPCODE_TRUNC = 33 + OPCODE_ZEXT = 34 + OPCODE_SEXT = 35 + OPCODE_FPTOUI = 36 + OPCODE_FPTOSI = 37 + OPCODE_UITOFP = 38 + OPCODE_SITOFP = 39 + OPCODE_FPTRUNC = 40 + OPCODE_FPEXT = 41 + OPCODE_PTRTOINT = 42 + OPCODE_INTTOPTR = 43 + OPCODE_BITCAST = 44 + OPCODE_ICMP = 45 + OPCODE_FCMP = 46 + OPCODE_PHI = 47 + OPCODE_CALL = 48 + OPCODE_SELECT = 49 + OPCODE_USEROP1 = 50 + OPCODE_USEROP2 = 51 + OPCODE_VAARG = 52 + OPCODE_EXTRACTELEMENT = 53 + OPCODE_INSERTELEMENT = 54 + OPCODE_SHUFFLEVECTOR = 55 + OPCODE_EXTRACTVALUE = 56 + OPCODE_INSERTVALUE = 57 + OPCODE_LANDINGPAD = 58 + +OpcodeEnum.declare() # calling conventions -CC_C = api.llvm.CallingConv.ID.C -CC_FASTCALL = api.llvm.CallingConv.ID.Fast -CC_COLDCALL = api.llvm.CallingConv.ID.Cold -CC_GHC = api.llvm.CallingConv.ID.GHC -CC_X86_STDCALL = api.llvm.CallingConv.ID.X86_StdCall -CC_X86_FASTCALL = api.llvm.CallingConv.ID.X86_FastCall -CC_ARM_APCS = api.llvm.CallingConv.ID.ARM_APCS -CC_ARM_AAPCS = api.llvm.CallingConv.ID.ARM_AAPCS -CC_ARM_AAPCS_VFP = api.llvm.CallingConv.ID.ARM_AAPCS_VFP -CC_MSP430_INTR = api.llvm.CallingConv.ID.MSP430_INTR -CC_X86_THISCALL = api.llvm.CallingConv.ID.X86_ThisCall -CC_PTX_KERNEL = api.llvm.CallingConv.ID.PTX_Kernel -CC_PTX_DEVICE = api.llvm.CallingConv.ID.PTX_Device -CC_MBLAZE_INTR = api.llvm.CallingConv.ID.MBLAZE_INTR -CC_MBLAZE_SVOL = api.llvm.CallingConv.ID.MBLAZE_SVOL +class CCEnum(Enum): + prefix = 'CC_' + + ID = api.llvm.CallingConv.ID + + CC_C = ID.C + CC_FASTCALL = ID.Fast + CC_COLDCALL = ID.Cold + CC_GHC = ID.GHC + CC_X86_STDCALL = ID.X86_StdCall + CC_X86_FASTCALL = ID.X86_FastCall + CC_ARM_APCS = ID.ARM_APCS + CC_ARM_AAPCS = ID.ARM_AAPCS + CC_ARM_AAPCS_VFP = ID.ARM_AAPCS_VFP + CC_MSP430_INTR = ID.MSP430_INTR + CC_X86_THISCALL = ID.X86_ThisCall + CC_PTX_KERNEL = ID.PTX_Kernel + CC_PTX_DEVICE = ID.PTX_Device + CC_MBLAZE_INTR = ID.MBLAZE_INTR + CC_MBLAZE_SVOL = ID.MBLAZE_SVOL + +CCEnum.declare() # int predicates -ICMP_EQ = api.llvm.CmpInst.Predicate.ICMP_EQ -ICMP_NE = api.llvm.CmpInst.Predicate.ICMP_NE -ICMP_UGT = api.llvm.CmpInst.Predicate.ICMP_UGT -ICMP_UGE = api.llvm.CmpInst.Predicate.ICMP_UGE -ICMP_ULT = api.llvm.CmpInst.Predicate.ICMP_ULT -ICMP_ULE = api.llvm.CmpInst.Predicate.ICMP_ULE -ICMP_SGT = api.llvm.CmpInst.Predicate.ICMP_SGT -ICMP_SGE = api.llvm.CmpInst.Predicate.ICMP_SGE -ICMP_SLT = api.llvm.CmpInst.Predicate.ICMP_SLT -ICMP_SLE = api.llvm.CmpInst.Predicate.ICMP_SLE +class ICMPEnum(Enum): + prefix = 'ICMP_' + + Predicate = api.llvm.CmpInst.Predicate + ICMP_EQ = Predicate.ICMP_EQ + ICMP_NE = Predicate.ICMP_NE + ICMP_UGT = Predicate.ICMP_UGT + ICMP_UGE = Predicate.ICMP_UGE + ICMP_ULT = Predicate.ICMP_ULT + ICMP_ULE = Predicate.ICMP_ULE + ICMP_SGT = Predicate.ICMP_SGT + ICMP_SGE = Predicate.ICMP_SGE + ICMP_SLT = Predicate.ICMP_SLT + ICMP_SLE = Predicate.ICMP_SLE + +ICMPEnum.declare() # same as ICMP_xx, for backward compatibility + IPRED_EQ = ICMP_EQ IPRED_NE = ICMP_NE IPRED_UGT = ICMP_UGT @@ -197,24 +242,33 @@ IPRED_SLT = ICMP_SLT IPRED_SLE = ICMP_SLE # real predicates -FCMP_FALSE = api.llvm.CmpInst.Predicate.FCMP_FALSE -FCMP_OEQ = api.llvm.CmpInst.Predicate.FCMP_OEQ -FCMP_OGT = api.llvm.CmpInst.Predicate.FCMP_OGT -FCMP_OGE = api.llvm.CmpInst.Predicate.FCMP_OGE -FCMP_OLT = api.llvm.CmpInst.Predicate.FCMP_OLT -FCMP_OLE = api.llvm.CmpInst.Predicate.FCMP_OLE -FCMP_ONE = api.llvm.CmpInst.Predicate.FCMP_ONE -FCMP_ORD = api.llvm.CmpInst.Predicate.FCMP_ORD -FCMP_UNO = api.llvm.CmpInst.Predicate.FCMP_UNO -FCMP_UEQ = api.llvm.CmpInst.Predicate.FCMP_UEQ -FCMP_UGT = api.llvm.CmpInst.Predicate.FCMP_UGT -FCMP_UGE = api.llvm.CmpInst.Predicate.FCMP_UGE -FCMP_ULT = api.llvm.CmpInst.Predicate.FCMP_ULT -FCMP_ULE = api.llvm.CmpInst.Predicate.FCMP_ULE -FCMP_UNE = api.llvm.CmpInst.Predicate.FCMP_UNE -FCMP_TRUE = api.llvm.CmpInst.Predicate.FCMP_TRUE + +class FCMPEnum(Enum): + prefix = 'FCMP_' + + Predicate = api.llvm.CmpInst.Predicate + + FCMP_FALSE = Predicate.FCMP_FALSE + FCMP_OEQ = Predicate.FCMP_OEQ + FCMP_OGT = Predicate.FCMP_OGT + FCMP_OGE = Predicate.FCMP_OGE + FCMP_OLT = Predicate.FCMP_OLT + FCMP_OLE = Predicate.FCMP_OLE + FCMP_ONE = Predicate.FCMP_ONE + FCMP_ORD = Predicate.FCMP_ORD + FCMP_UNO = Predicate.FCMP_UNO + FCMP_UEQ = Predicate.FCMP_UEQ + FCMP_UGT = Predicate.FCMP_UGT + FCMP_UGE = Predicate.FCMP_UGE + FCMP_ULT = Predicate.FCMP_ULT + FCMP_ULE = Predicate.FCMP_ULE + FCMP_UNE = Predicate.FCMP_UNE + FCMP_TRUE = Predicate.FCMP_TRUE + +FCMPEnum.declare() # real predicates + RPRED_FALSE = FCMP_FALSE RPRED_OEQ = FCMP_OEQ RPRED_OGT = FCMP_OGT @@ -233,68 +287,69 @@ RPRED_UNE = FCMP_UNE RPRED_TRUE = FCMP_TRUE # linkages (see llvm::GlobalValue::LinkageTypes) -LINKAGE_EXTERNAL = \ - api.llvm.GlobalValue.LinkageTypes.ExternalLinkage -LINKAGE_AVAILABLE_EXTERNALLY = \ - api.llvm.GlobalValue.LinkageTypes.AvailableExternallyLinkage -LINKAGE_LINKONCE_ANY = \ - api.llvm.GlobalValue.LinkageTypes.LinkOnceAnyLinkage -LINKAGE_LINKONCE_ODR = \ - api.llvm.GlobalValue.LinkageTypes.LinkOnceODRLinkage -LINKAGE_WEAK_ANY = \ - api.llvm.GlobalValue.LinkageTypes.WeakAnyLinkage -LINKAGE_WEAK_ODR = \ - api.llvm.GlobalValue.LinkageTypes.WeakODRLinkage -LINKAGE_APPENDING = \ - api.llvm.GlobalValue.LinkageTypes.AppendingLinkage -LINKAGE_INTERNAL = \ - api.llvm.GlobalValue.LinkageTypes.InternalLinkage -LINKAGE_PRIVATE = \ - api.llvm.GlobalValue.LinkageTypes.PrivateLinkage -LINKAGE_DLLIMPORT = \ - api.llvm.GlobalValue.LinkageTypes.DLLImportLinkage -LINKAGE_DLLEXPORT = \ - api.llvm.GlobalValue.LinkageTypes.DLLExportLinkage -LINKAGE_EXTERNAL_WEAK = \ - api.llvm.GlobalValue.LinkageTypes.ExternalWeakLinkage -LINKAGE_COMMON = \ - api.llvm.GlobalValue.LinkageTypes.CommonLinkage -LINKAGE_LINKER_PRIVATE = \ - api.llvm.GlobalValue.LinkageTypes.LinkerPrivateLinkage -LINKAGE_LINKER_PRIVATE_WEAK = \ - api.llvm.GlobalValue.LinkageTypes.LinkerPrivateWeakLinkage +class LinkageEnum(Enum): + prefix = 'LINKAGE_' + LinkageTypes = api.llvm.GlobalValue.LinkageTypes + + LINKAGE_EXTERNAL = LinkageTypes.ExternalLinkage + LINKAGE_AVAILABLE_EXTERNALLY = LinkageTypes.AvailableExternallyLinkage + LINKAGE_LINKONCE_ANY = LinkageTypes.LinkOnceAnyLinkage + LINKAGE_LINKONCE_ODR = LinkageTypes.LinkOnceODRLinkage + LINKAGE_WEAK_ANY = LinkageTypes.WeakAnyLinkage + LINKAGE_WEAK_ODR = LinkageTypes.WeakODRLinkage + LINKAGE_APPENDING = LinkageTypes.AppendingLinkage + LINKAGE_INTERNAL = LinkageTypes.InternalLinkage + LINKAGE_PRIVATE = LinkageTypes.PrivateLinkage + LINKAGE_DLLIMPORT = LinkageTypes.DLLImportLinkage + LINKAGE_DLLEXPORT = LinkageTypes.DLLExportLinkage + LINKAGE_EXTERNAL_WEAK = LinkageTypes.ExternalWeakLinkage + LINKAGE_COMMON = LinkageTypes.CommonLinkage + LINKAGE_LINKER_PRIVATE = LinkageTypes.LinkerPrivateLinkage + LINKAGE_LINKER_PRIVATE_WEAK = LinkageTypes.LinkerPrivateWeakLinkage + +LinkageEnum.declare() # visibility (see llvm/GlobalValue.h) -VISIBILITY_DEFAULT = api.llvm.GlobalValue.VisibilityTypes.DefaultVisibility -VISIBILITY_HIDDEN = api.llvm.GlobalValue.VisibilityTypes.HiddenVisibility -VISIBILITY_PROTECTED = api.llvm.GlobalValue.VisibilityTypes.ProtectedVisibility +class VisibilityEnum(Enum): + prefix = 'VISIBILITY_' + + VISIBILITY_DEFAULT = api.llvm.GlobalValue.VisibilityTypes.DefaultVisibility + VISIBILITY_HIDDEN = api.llvm.GlobalValue.VisibilityTypes.HiddenVisibility + VISIBILITY_PROTECTED = api.llvm.GlobalValue.VisibilityTypes.ProtectedVisibility + +VisibilityEnum.declare() # parameter attributes llvm::Attributes::AttrVal (see llvm/Attributes.h) -ATTR_NONE = api.llvm.Attributes.AttrVal.None_ -ATTR_ZEXT = api.llvm.Attributes.AttrVal.ZExt -ATTR_SEXT = api.llvm.Attributes.AttrVal.SExt -ATTR_NO_RETURN = api.llvm.Attributes.AttrVal.NoReturn -ATTR_IN_REG = api.llvm.Attributes.AttrVal.InReg -ATTR_STRUCT_RET = api.llvm.Attributes.AttrVal.StructRet -ATTR_NO_UNWIND = api.llvm.Attributes.AttrVal.NoUnwind -ATTR_NO_ALIAS = api.llvm.Attributes.AttrVal.NoAlias -ATTR_BY_VAL = api.llvm.Attributes.AttrVal.ByVal -ATTR_NEST = api.llvm.Attributes.AttrVal.Nest -ATTR_READ_NONE = api.llvm.Attributes.AttrVal.ReadNone -ATTR_READONLY = api.llvm.Attributes.AttrVal.ReadOnly -ATTR_NO_INLINE = api.llvm.Attributes.AttrVal.NoInline -ATTR_ALWAYS_INLINE = api.llvm.Attributes.AttrVal.AlwaysInline -ATTR_OPTIMIZE_FOR_SIZE = api.llvm.Attributes.AttrVal.OptimizeForSize -ATTR_STACK_PROTECT = api.llvm.Attributes.AttrVal.StackProtect -ATTR_STACK_PROTECT_REQ = api.llvm.Attributes.AttrVal.StackProtectReq -ATTR_ALIGNMENT = api.llvm.Attributes.AttrVal.Alignment -ATTR_NO_CAPTURE = api.llvm.Attributes.AttrVal.NoCapture -ATTR_NO_REDZONE = api.llvm.Attributes.AttrVal.NoRedZone -ATTR_NO_IMPLICIT_FLOAT = api.llvm.Attributes.AttrVal.NoImplicitFloat -ATTR_NAKED = api.llvm.Attributes.AttrVal.Naked -ATTR_INLINE_HINT = api.llvm.Attributes.AttrVal.InlineHint -ATTR_STACK_ALIGNMENT = api.llvm.Attributes.AttrVal.StackAlignment +class AttrEnum(Enum): + prefix = 'ATTR_' + AttrVal = api.llvm.Attributes.AttrVal + ATTR_NONE = AttrVal.None_ + ATTR_ZEXT = AttrVal.ZExt + ATTR_SEXT = AttrVal.SExt + ATTR_NO_RETURN = AttrVal.NoReturn + ATTR_IN_REG = AttrVal.InReg + ATTR_STRUCT_RET = AttrVal.StructRet + ATTR_NO_UNWIND = AttrVal.NoUnwind + ATTR_NO_ALIAS = AttrVal.NoAlias + ATTR_BY_VAL = AttrVal.ByVal + ATTR_NEST = AttrVal.Nest + ATTR_READ_NONE = AttrVal.ReadNone + ATTR_READONLY = AttrVal.ReadOnly + ATTR_NO_INLINE = AttrVal.NoInline + ATTR_ALWAYS_INLINE = AttrVal.AlwaysInline + ATTR_OPTIMIZE_FOR_SIZE = AttrVal.OptimizeForSize + ATTR_STACK_PROTECT = AttrVal.StackProtect + ATTR_STACK_PROTECT_REQ = AttrVal.StackProtectReq + ATTR_ALIGNMENT = AttrVal.Alignment + ATTR_NO_CAPTURE = AttrVal.NoCapture + ATTR_NO_REDZONE = AttrVal.NoRedZone + ATTR_NO_IMPLICIT_FLOAT = AttrVal.NoImplicitFloat + ATTR_NAKED = AttrVal.Naked + ATTR_INLINE_HINT = AttrVal.InlineHint + ATTR_STACK_ALIGNMENT = AttrVal.StackAlignment + +AttrEnum.declare() class Module(llvm.Wrapper): """A Module instance stores all the information related to an LLVM module. @@ -1405,6 +1460,12 @@ class Argument(Value): alignment = property(_get_alignment, _set_alignment) + @property + def attributes(self): + '''Returns a set of defined attributes. + ''' + return set(attr for attr in self._valid_attrs if attr in self) + def __contains__(self, attr): if attr == ATTR_BY_VAL: return self.has_by_val() From edab81ed7e75006fbc490e691b212295aef3723f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 17 May 2013 14:05:40 -0500 Subject: [PATCH 009/149] Fix GC problem with Module when it is GCed but re-instantiate from GlobalValue.module. --- llvmpy/src/GlobalValue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmpy/src/GlobalValue.py b/llvmpy/src/GlobalValue.py index ff499f7..d954ed0 100644 --- a/llvmpy/src/GlobalValue.py +++ b/llvmpy/src/GlobalValue.py @@ -46,4 +46,4 @@ class GlobalValue: eraseFromParent = Method() eraseFromParent.disowning = True - getParent = Method(ptr(Module)) + getParent = Method(ownedptr(Module)) From 5b2b878f24cc5e56d8aaf5bf01757ff0594139db Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 22 May 2013 15:17:59 -0500 Subject: [PATCH 010/149] Enable MCJIT --- llvm/ee.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/llvm/ee.py b/llvm/ee.py index e4ee4bc..7ea90d0 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -167,6 +167,11 @@ class EngineBuilder(llvm.Wrapper): ptr = self._ptr.selectTarget() return TargetMachine(ptr) + def mcjit(self, enable): + '''Enable/disable MCJIT + ''' + self._ptr.setUseMCJIT(enable) + return self #===----------------------------------------------------------------------=== # Execution engine From a0eb03b23950b9095f30e0bf15cd48d03166ab6e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 23 May 2013 11:45:15 -0500 Subject: [PATCH 011/149] Fix CompareInstruction.predicate --- llvm/core.py | 18 ++++++++++++++-- llvm/test_llvmpy.py | 51 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 9cb1946..fd72902 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -55,12 +55,18 @@ class Enum(int): @classmethod def declare(cls): + declared = cls._declared_ = {} scope = globals() for name in filter(lambda s: s.startswith(cls.prefix), dir(cls)): n = getattr(cls, name) typ = type(name, (cls,), {}) - scope[name] = typ(n) + obj = typ(n) + declared[n] = obj + scope[name] = obj + @classmethod + def get(cls, num): + return cls._declared_[num] # type id (llvm::Type::TypeID) class TypeEnum(Enum): @@ -1872,16 +1878,24 @@ class PHINode(Instruction): class SwitchInstruction(Instruction): + _type_ = api.llvm.SwitchInst def add_case(self, const, bblk): self._ptr.addCase(const._ptr, bblk._ptr) class CompareInstruction(Instruction): + _type_ = api.llvm.CmpInst @property def predicate(self): - return self._ptr.getPredicate() + n = self._ptr.getPredicate() + try: + return ICMPEnum.get(n) + except KeyError: + return FCMPEnum.get(n) + + #===----------------------------------------------------------------------=== # Basic block #===----------------------------------------------------------------------=== diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 3ecffff..e21a825 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1302,6 +1302,57 @@ class TestArgAttr(TestCase): tests.append(TestArgAttr) +# --------------------------------------------------------------------------- + +class TestSwitch(TestCase): + def test_arg_attr(self): + m = Module.new('oifjda') + fnty = Type.function(Type.void(), [Type.int()]) + func = m.add_function(fnty, 'foo') + bb = func.append_basic_block('') + bbdef = func.append_basic_block('') + bbsw1 = func.append_basic_block('') + bbsw2 = func.append_basic_block('') + bldr = Builder.new(bb) + + swt = bldr.switch(func.args[0], bbdef, n=2) + swt.add_case(Constant.int(Type.int(), 0), bbsw1) + swt.add_case(Constant.int(Type.int(), 1), bbsw2) + + bldr.position_at_end(bbsw1) + bldr.ret_void() + + bldr.position_at_end(bbsw2) + bldr.ret_void() + + bldr.position_at_end(bbdef) + bldr.ret_void() + + func.verify() + +tests.append(TestSwitch) + +# --------------------------------------------------------------------------- + +class TestCmp(TestCase): + def test_arg_attr(self): + m = Module.new('oifjda') + fnty = Type.function(Type.void(), [Type.int()]) + func = m.add_function(fnty, 'foo') + bb = func.append_basic_block('') + bldr = Builder.new(bb) + + cmpinst = bldr.icmp(lc.ICMP_ULE, func.args[0], + Constant.int(Type.int(), 123)) + self.assertTrue(repr(cmpinst.predicate).startswith('ICMP_ULE')) + self.assertEqual(cmpinst.predicate, lc.ICMP_ULE) + bldr.ret_void() + + func.verify() + +tests.append(TestCmp) + + # --------------------------------------------------------------------------- def run(verbosity=1): From 1812cff2d0e23eaaccbe609d1bd9ae69b0af568f Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Sat, 25 May 2013 13:34:14 -0500 Subject: [PATCH 012/149] Fix import problem. --- llvm_array/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm_array/__init__.py b/llvm_array/__init__.py index f6a0f3f..5e807c2 100644 --- a/llvm_array/__init__.py +++ b/llvm_array/__init__.py @@ -1,2 +1,2 @@ from __future__ import absolute_imports -from .array.py import * +from .array import * From 009239713eb97ead506584652325f9ddf260557a Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Sat, 25 May 2013 13:35:37 -0500 Subject: [PATCH 013/149] Update llvm_array concepts. --- llvm_array/array.py | 261 +++++++++++++++++++++++++++++++------------- 1 file changed, 187 insertions(+), 74 deletions(-) diff --git a/llvm_array/array.py b/llvm_array/array.py index 12df60e..3cac244 100644 --- a/llvm_array/array.py +++ b/llvm_array/array.py @@ -24,19 +24,98 @@ # intp stride; #} diminfo # +# These are for low-level array-routines that need to know the number +# of dimensions at run-time (not just code-generation time): +# +# The first two are recommended +# +# struct { +# eltype *data; +# int32 nd; +# intp shape[nd]; +# } contiguous_array_nd(eltype) +# +# struct { +# eltype *data; +# int32 nd; +# diminfo shape[nd]; +# } strided_array_nd(eltype) +# +# +# Backward compatible but deprecated: +# struct { +# eltype *data; +# int32 nd; +# intp shape[nd]; +# intp stride[nd]; +# } strided_soa_array_nd(eltype) +# +# +# The most general (where the kind of array is stored as well as number +# of dimensions) +# Rarely needed. +# +# struct { +# eltype *data; +# int16 nd; +# int16 dimkind; +# ??? +# } array_nd(eltype) +# +# where ??? is run-time interpreted based on the dimkind to either: +# intp shape[nd]; for dimkind = C_CONTIGUOUS or F_CONTIGUOUS +# +# diminfo shape[nd]; for dimkind = STRIDED +# +# intp shape[ind]; +# intp strides[ind]; dimkind = STRIDED_SOA +# import llvm.core as lc from llvm.core import Type import llvm_cbuilder.shortnames as C -CONTIGUOUS = 1 << 8 -STRIDED = CONTIGUOUS + 1 -STRIDED_SOA = CONTIGUOUS + 2 +# Different Array Types +ARRAYBIT = 1<<4 +C_CONTIGUOUS = ARRAYBIT + 0 +F_CONTIGUOUS = ARRAYBIT + 1 +STRIDED = ARRAYBIT + 2 +STRIDED_SOA = ARRAYBIT + 3 -array_kinds = (CONTIGUOUS, STRIDED, STRIDED_SOA) +HAS_ND = 1<<5 +C_CONTIGUOUS_ND = C_CONTIGUOUS + HAS_ND +F_CONTIGUOUS_ND = F_CONTIGUOUS + HAS_ND +STRIDED_ND = STRIDED + HAS_ND +STRIDED_SOA_ND = STRIDED_SOA + HAS_ND + +HAS_DIMKIND = 1<<6 +C_CONTIGUOUS_DK = C_CONTIGUOUS + HAS_DIMKIND +F_CONTIGUOUS_DK = F_CONTIGUOUS + HAS_DIMKIND +STRIDED_DK = STRIDED + HAS_DIMKIND +STRIDED_SOA_DK = STRIDED_SOA + HAS_DIMKIND + +array_kinds = (C_CONTIGUOUS, F_CONTIGUOUS, STRIDED, STRIDED_SOA, + C_CONTIGUOUS_ND, F_CONTIGUOUS_ND, STRIDED_ND, STRIDED_SOA_DK, + C_CONTIGUOUS_DK, F_CONTIGUOUS_DK, STRIDED_DK, STRIDED_SOA_DK) + +_invmap = {} + +def kind_to_str(kind): + global _invmap + if not _invmap: + for key, value in globals().items(): + if isinstance(value, int) and value in array_kinds: + _invmap[value] = key + return _invmap[kind] + +def str_to_kind(str): + trial = eval(str) + if trial not in array_kinds: + raise ValueError("Invalid Array Kind") + return trial void_type = C.void -int_type = C.int +int32_type = C.int32 char_type = C.char int16_type = C.int16 intp_type = C.intp @@ -45,99 +124,133 @@ diminfo_type = Type.struct([intp_type, # shape intp_type # stride ], name='diminfo') -# This is the way we define LLVM arrays. -def cont_array_type(nd, el_type=char_type, name=''): - terms = [Type.pointer(el_type), # data - Type.array(intp_type, nd) # shape - ] - return Type.struct(terms, name=name) +_cache = {} +# This is the way we define LLVM arrays. +# CONTIGUOUS and STRIDED are strongly encouraged... +def array_type(nd, kind, el_type=char_type): + key = (kind, nd, el_type) + if _cache.has_key(key): + return _cache[key] -def strided_array_type(nd, el_type=char_type, name=''): - terms = [Type.pointer(el_type), # data - Type.array(diminfo_type, nd) # diminfo - ] - return Type.struct(terms, name=name) + base = kind & (~(HAS_ND | HAS_DIMKIND)) + if base == C_CONTIGUOUS: + dimstr = 'Array_C' + elif base == F_CONTIGUOUS: + dimstr = 'Array_F' + elif base == STRIDED: + dimstr = 'Array_S' + elif base == STRIDED_SOA: + dimstr = 'Array_A' + else: + raise TypeError("Do not understand Array kind of %d" % kind) + + terms = [Type.pointer(el_type)] # data + + if (kind & HAS_ND): + terms.append(int32_type) # nd + dimstr += '_ND' + elif (kind & HAS_DIMKIND): + terms.extend([int16_type, int16_type]) # nd, dimkind + dimstr += '_DK' + + if base in [C_CONTIGUOUS, F_CONTIGUOUS]: + terms.append(Type.array(intp_type, nd)) # shape + elif base == STRIDED: + terms.append(Type.array(diminfo_type, nd)) # diminfo + elif base == STRIDED_SOA: + terms.extend([Type.array(intp_type, nd), # shape + Type.array(intp_type, nd)]) # strides + + ret = Type.struct(terms, name=dimstr) + _cache[key] = ret + return ret -def strided_soa_type(nd, el_type=char_type, name=''): - terms = [Type.pointer(el_type), # data - Type.array(intp_type, nd), # shape[nd] - Type.array(intp_type, nd) # strides[nd] - ] - return Type.struct(terms, name=name) def check_array(arrtyp): if not isinstance(arrtyp, lc.StructType): return None - if arrtyp.element_count not in [2, 3]: - return None - if not isinstance(arrtyp.elements[0], lc.PointerType) or \ - not isinstance(arrtyp.elements[1], lc.ArrayType): + if arrtyp.element_count not in [2, 3, 4, 5]: return None - data_type = arrtyp.elements[0].pointee - s1 = arrtyp.elements[1] + # Look through _cache and see if it's there + for key, value in _cache.items(): + if arrtyp is value: + return key + + return _raw_check_array(arrtyp) + +# Manual check +def _raw_check_array(arrtyp): + a0 = arrtyp.elements[0] + a1 = arrtyp.elements[1] + if not isinstance(a0, lc.PointerType) or \ + not (isinstance(a1, lc.ArrayType) or + (a1 == int32_type) or (a1 == int16_type)): + return None + + data_type = a0.pointee + + if arrtyp.is_literal: + c_contig = True + else: + if arrtyp.name.startswith('Array_F'): + c_contig = False + else: + c_contig = True + + + if a1 == int32_type: + num = 2 + strided = STRIDED_ND + strided_soa = STRIDED_SOA_ND + c_contiguous = C_CONTIGUOUS_ND + f_contiguous = F_CONTIGUOUS_ND + elif a1 == int16_type: + if arrtyp.element_count < 3 or arrtyp.elements[2] != int16_type: + return None + num = 3 + strided = STRIDED_DK + strided_soa = STRIDED_SOA_DK + c_contiguous = C_CONTIGUOUS_DK + f_contiguous = F_CONTIGUOUS_DK + else: + num = 1 + strided = STRIDED + strided_soa = STRIDED_SOA + c_contiguous = C_CONTIGUOUS + f_contiguous = F_CONTIGUOUS + + elcount = num + 2 + # otherwise we have lc.ArrType as element [1] + if arrtyp.element_count not in [num+1,num+2]: + return None + s1 = arrtyp.elements[num] nd = s1.count - if arrtyp.element_count == 3: - if not isinstance(arrtyp.elements[2], lc.ArrayType): + if arrtyp.element_count == elcount: + if not isinstance(arrtyp.elements[num+1], lc.ArrayType): return None - s2 = arrtyp.elements[2] + s2 = arrtyp.elements[num+1] if s1.element != intp_type or s2.element != intp_type: return None if s1.count != s2.count: return None - return STRIDED_SOA, nd, data_type + return strided_soa, nd, data_type if s1.element == diminfo_type: - return STRIDED, nd, data_type + return strided, nd, data_type elif s1.element == intp_type: - return CONTIGUOUS, nd, data_type + return c_contiguous if c_contig else f_contiguous, nd, data_type else: return None -def is_cont_array(arrtyp): - if not isinstance(arrtyp, lc.StructType): - return False - if arrtyp.element_count != 2 or \ - not isinstance(arrtyp.elements[0], lc.PointerType) or \ - not isinstance(arrtyp.elements[1], lc.ArrayType): - return False - if arrtyp.elements[1].element != intp_type: - return False - return True - -def is_strided_array(arrtyp, kind=diminfo_type): - if not isinstance(arrtyp, lc.StructType): - return False - if arrtyp.element_count != 2 or \ - not isinstance(arrtyp.elements[0], lc.PointerType) or \ - not isinstance(arrtyp.elements[1], lc.ArrayType): - return False - if arrtyp.elements[1].element != kind: - return False - return True - -def is_strided_soa_array(arrtyp): - if not isinstance(arrtyp, lc.StructType): - return False - if arrtyp.element_count != 3 or \ - not isinstance(arrtyp.elements[0], lc.PointerType) or \ - not isinstance(arrtyp.elements[1], lc.ArrayType) or \ - not isinstance(arrtyp.elements[2], lc.ArrayType): - return False - s1, s2 = arrtyp.elements[1:] - if s1.element != intp_type or s2.element != intp_type: - return False - if s1.count != s2.count: - return False - return True def test(): - arr = cont_array_type(5) - assert check_array(arr) == (CONTIGUOUS, 5, char_type) - arr = strided_array_type(4) + arr = array_type(5, C_CONTIGUOUS) + assert check_array(arr) == (C_CONTIGUOUS, 5, char_type) + arr = array_type(4, STRIDED) assert check_array(arr) == (STRIDED, 4, char_type) - arr = strided_soa_type(3) + arr = array_type(3, STRIDED_SOA) assert check_array(arr) == (STRIDED_SOA, 3, char_type) if __name__ == '__main__': From 6b333e84aa249869401ab5c02dd0cf95b43d6984 Mon Sep 17 00:00:00 2001 From: Mark Florisson Date: Mon, 27 May 2013 12:22:13 +0100 Subject: [PATCH 014/149] Use error message string from BytesIO --- llvm/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index fd72902..9c8501e 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -504,7 +504,7 @@ class Module(llvm.Wrapper): mode, errmsg) if failed: - raise llvm.LLVMException(errmsg) + raise llvm.LLVMException(errmsg.getvalue()) def get_type_named(self, name): typ = self._ptr.getTypeByName(name) From 17ec89e457c05b3fdb004fb3636d47ea853484d0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 28 May 2013 19:23:40 -0500 Subject: [PATCH 015/149] Fix win32 build --- llvm-config-win32.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 05fc94f..5f6c401 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -98,6 +98,9 @@ def main(): if option == '--version': print(get_llvm_version()) + elif option == '--targets-built': + print('X86') # just do X86 + elif option == '--libs': libs_options() From 2e8944916c8a95855ec26fcdc07d4094c1681aba Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 29 May 2013 16:16:19 -0500 Subject: [PATCH 016/149] Add DIBuilder binding --- llvmpy/src/DIBuilder.py | 357 +++++++++++++++++++++++ llvmpy/src/DebugInfo.py | 98 +++++++ llvmpy/src/Support/Dwarf.py | 563 ++++++++++++++++++++++++++++++++++++ 3 files changed, 1018 insertions(+) create mode 100644 llvmpy/src/DIBuilder.py create mode 100644 llvmpy/src/DebugInfo.py create mode 100644 llvmpy/src/Support/Dwarf.py diff --git a/llvmpy/src/DIBuilder.py b/llvmpy/src/DIBuilder.py new file mode 100644 index 0000000..9671963 --- /dev/null +++ b/llvmpy/src/DIBuilder.py @@ -0,0 +1,357 @@ +from binding import * +from .namespace import llvm + +DIBuilder = llvm.Class() + +from .Module import Module +from .Value import Value, MDNode, Function, BasicBlock +from .Instruction import Instruction +from .DebugInfo import DIFile, DIEnumerator, DIType, DIBasicType, DIDerivedType +from .DebugInfo import DIDescriptor, DIArray, DISubrange, DIGlobalVariable +from .DebugInfo import DIVariable, DISubprogram, DINameSpace, DILexicalBlockFile +from .DebugInfo import DILexicalBlock +from .ADT.SmallVector import SmallVector_Value +from .ADT.StringRef import StringRef + +unsigned_arg = cast(int, Unsigned) +stringref_arg = cast(str, StringRef) +bool_arg = cast(bool, Bool) +uint64_arg = cast(int, Uint64) +int64_arg = cast(int, Int64) + +@DIBuilder +class DIBuilder: + _include_ = 'llvm/DIBuilder.h' + new = Constructor(ref(Module)) + delete = Destructor() + + getCU = Method(const(ptr(MDNode))) + finalize = Method() + + createCompileUnit = Method(Void, + unsigned_arg, # Lang + stringref_arg, # File + stringref_arg, # Dir + stringref_arg, # Producer + bool_arg, # isOptimized + stringref_arg, # Flags, + unsigned_arg, # RV + # stringref_arg, # SplitName LLVM3.3 + ) #.require_only(7) + + createFile = Method(DIFile, + stringref_arg, # Filename + stringref_arg, # Directory + ) + + createEnumerator = Method(DIEnumerator, + stringref_arg, # Name + uint64_arg, # Val + ) + + createNullPtrType = Method(DIType, + stringref_arg, # Name + ) + + createBasicType = Method(DIType, + stringref_arg, # Name + uint64_arg, # SizeIntBits, + uint64_arg, # AlignInBits, + unsigned_arg, # Encoding + ) + + createQualifiedType = Method(DIType, + unsigned_arg, # Tag + ref(DIType), # FromTy + ) + + createPointerType = Method(DIType, + ref(DIType), # PointeeTy + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + stringref_arg, # Name + ).require_only(2) + + createReferenceType = Method(DIType, + unsigned_arg, # Tag + ref(DIType), # RTy + ) + + createTypedef = Method(DIType, + ref(DIType), # Ty + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIDescriptor), # Context + ) + + createFriend = Method(DIType, + ref(DIType), # Ty + ref(DIType), # FriendTy + ) + + createInheritance = Method(DIType, + ref(DIType), # Ty + ref(DIType), # BaseTy + uint64_arg, # BaseOffset + unsigned_arg, # Flags + ) + + createMemberType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNo + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + uint64_arg, # OffsetInBits + unsigned_arg, # Flags + ref(DIType), # Ty + ) + + createClassType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNum + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + uint64_arg, # OffsetInBits, + unsigned_arg, # Flags + ref(DIType), # DerivedFrom + ref(DIArray), # Elements + ptr(MDNode), # VTableHolder = 0 + ptr(MDNode), # TemplateParms = 0 + ).require_only(10) + + createStructType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNumber + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + unsigned_arg, # Flags + ref(DIArray), # Elements + unsigned_arg, # RunTimeLang = 0 + ).require_only(8) + + createUnionType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNum + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + unsigned_arg, # Flags + ref(DIArray), # Elements + unsigned_arg, # RunTimeLang = 0 + ).require_only(8) + + createArrayType = Method(DIType, + uint64_arg, # Size + uint64_arg, # AlignInBits + ref(DIType), # Ty + ref(DIArray), # Subscripts + ) + + createVectorType = Method(DIType, + uint64_arg, # Size + uint64_arg, # AlignInBits + ref(DIType), # Ty + ref(DIArray), # Subscripts + ) + + createEnumerationType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNumber + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + ref(DIArray), # Elements + ref(DIType), # ClassType + ) + + createSubroutineType = Method(DIType, + ref(DIFile), # File + ref(DIArray), # ParameterTypes + ) + + createArtificialType = Method(DIType, + ref(DIType), # Ty + ) + + createObjectPointerType = Method(DIType, + ref(DIType), # Ty + ) + + createTemporaryType = Method(DIType, ref(DIFile)).require_only(0) + + createForwardDecl = Method(DIType, + unsigned_arg, # Tag + stringref_arg, # Name + ref(DIDescriptor), # scope + ref(DIFile), # F + unsigned_arg, # Line + unsigned_arg, # RuntimeLang=0 + uint64_arg, # SizeInBits=0 + uint64_arg, # AlignInBits=0 + ).require_only(5) + + retainType = Method(Void, ref(DIType)) + + createUnspecifiedParameter = Method(DIDescriptor) + + getOrCreateArray = Method(DIArray, + ref(SmallVector_Value), # Elements + ) + + getOrCreateSubrange = Method(DISubrange, + int64_arg, # Lo + int64_arg, # Hi + ) + + createGlobalVariable = Method(DIGlobalVariable, + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIType), # Ty + bool_arg, # isLocalToUnit + ptr(Value), # Val + ) + + createStaticVariable = Method(DIGlobalVariable, + ref(DIDescriptor), # Context + stringref_arg, # Name + stringref_arg, # LinkageName + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIType), # Ty + bool_arg, # isLocalToUnit + ptr(Value), # Val + ) + + createLocalVariable = Method(DIVariable, + unsigned_arg, # Tag, + ref(DIDescriptor), # Scope, + stringref_arg, # Name, + ref(DIFile), # File, + unsigned_arg, # LineNo, + ref(DIType), # Ty, + bool_arg, # AlwaysPreserve=false, + unsigned_arg, # Flags=0, + unsigned_arg, # ArgNo=0 + ).require_only(6) + + createComplexVariable = Method(DIVariable, + unsigned_arg, # Tag, + ref(DIDescriptor), # Scope, + stringref_arg, # Name, + ref(DIFile), # F, + unsigned_arg, # LineNo, + ref(DIType), # Ty, + ref(SmallVector_Value), # Addr, + unsigned_arg, # ArgNo=0, + ).require_only(7) + + createFunction = Method(DISubprogram, + ref(DIDescriptor), # Scope + stringref_arg, # Name + stringref_arg, # LinkageName + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIType), # Ty + bool_arg, # isLocalToUnit + bool_arg, # isDefinition + unsigned_arg, # ScopeLine + unsigned_arg, # Flags=0 + bool_arg, # isOptimized=false + ptr(Function), # *Fn=0 + ptr(MDNode), # *TParam=0, + ptr(MDNode), # *Decl=0 + ).require_only(9) + + + createMethod = Method(DISubprogram, + ref(DIDescriptor), # Scope + stringref_arg, # Name + stringref_arg, # LinkageName + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIType), # Ty + bool_arg, # isLocalToUnit + bool_arg, # isDefinition + unsigned_arg, # Virtuality=0 + unsigned_arg, # VTableIndex=0 + ptr(MDNode), # *VTableHolder=0 + unsigned_arg, # Flags=0 + bool_arg, # isOptimized=false + ptr(Function), # *Fn=0 + ptr(MDNode), # *TParam=0 + ).require_only(8) + + + createNameSpace = Method(DINameSpace, + ref(DIDescriptor), # Scope, + stringref_arg, # Name, + ref(DIFile), # File, + unsigned_arg, # LineNo + ) + + createLexicalBlockFile = Method(DILexicalBlockFile, + ref(DIDescriptor), # Scope, + ref(DIFile), # File + ) + + createLexicalBlock = Method(DILexicalBlock, + ref(DIDescriptor), # Scope, + ref(DIFile), # File, + unsigned_arg, # Line, + unsigned_arg, # Col + ) + + _insertDeclare_1 = Method(ptr(Instruction), + ptr(Value), # Storage, + ref(DIVariable), # VarInfo + ptr(BasicBlock), # *InsertAtEnd + ) + _insertDeclare_1.realname = 'insertDeclare' + + _insertDeclare_2 = Method(ptr(Instruction), + ptr(Value), # Storage, + ref(DIVariable), # VarInfo + ptr(Instruction), # *InsertBefore + ) + _insertDeclare_2.realname = 'insertDeclare' + + @CustomPythonMethod + def insertDeclare(self, storage, varinfo, insertpt): + if isinstance(insertbefore, _api.llvm.Instruction): + return self._insertDeclare_2(storage, varinfo, insertpt) + else: + return self._insertDeclare_1(storage, varinfo, insertpt) + + _insertDbgValueIntrinsic_1 = Method(ptr(Instruction), + ptr(Value), # *Val + uint64_arg, # Offset + ref(DIVariable), # VarInfo + ptr(BasicBlock), # *InsertAtEnd + ) + _insertDbgValueIntrinsic_1.realname = 'insertDbgValueIntrinsic' + + _insertDbgValueIntrinsic_2 = Method(ptr(Instruction), + ptr(Value), # *Val + uint64_arg, # Offset + ref(DIVariable), # VarInfo + ptr(Instruction), # *InsertAtEnd + ) + _insertDbgValueIntrinsic_2.realname = 'insertDbgValueIntrinsic' + + + @CustomPythonMethod + def insertDbgValueIntrinsic(self, storage, varinfo, insertpt): + if isinstance(insertbefore, _api.llvm.Instruction): + return self._insertDbgValueIntrinsic_2(storage, varinfo, insertpt) + else: + return self._insertDbgValueIntrinsic_1(storage, varinfo, insertpt) diff --git a/llvmpy/src/DebugInfo.py b/llvmpy/src/DebugInfo.py new file mode 100644 index 0000000..81fe168 --- /dev/null +++ b/llvmpy/src/DebugInfo.py @@ -0,0 +1,98 @@ +from binding import * +from .namespace import llvm + +from .ADT.StringRef import StringRef +from .Value import MDNode + +DIDescriptor = llvm.Class(MDNode) +DIEnumerator = llvm.Class(DIDescriptor) +DIScope = llvm.Class(DIDescriptor) +DIType = llvm.Class(DIScope) +DIBasicType = llvm.Class(DIType) +DIDerivedType = llvm.Class(DIType) +DICompositeType = llvm.Class(DIDerivedType) +DIFile = llvm.Class(DIScope) +DIArray = llvm.Class(DIDescriptor) +DISubrange = llvm.Class(DIDescriptor) +DIGlobalVariable = llvm.Class(DIDescriptor) +DIVariable = llvm.Class(DIDescriptor) +DISubprogram = llvm.Class(DIScope) +DINameSpace = llvm.Class(DIScope) +DILexicalBlockFile = llvm.Class(DIScope) +DILexicalBlock = llvm.Class(DIScope) + +llvm.includes.add('llvm/DebugInfo.h') + +return_bool = cast(Bool, bool) +return_stringref = cast(StringRef, str) +return_unsigned = cast(Unsigned, int) + +@DIDescriptor +class DIDescriptor: + pass + +@DIScope +class DIScope: + pass + +@DIFile +class DIFile: + # getFileNode = Method(ptr(MDNode)) # not in LLVM 3.2? + Verify = Method(return_bool) + +@DIEnumerator +class DIEnumerator: + getName = Method(return_stringref) + getEnumValue = Method(cast(Uint64, int)) + Verify = Method(return_bool) + +@DIType +class DIType: + getName = Method(return_stringref) + getLineNumber = Method(return_unsigned) + Verify = Method(return_bool) + +@DIBasicType +class DIBasicType: + pass + +@DIDerivedType +class DIDerivedType: + pass + +@DICompositeType +class DICompositeType: + pass + +@DIArray +class DIArray: + Verify = Method(return_bool) + +@DISubrange +class DISubrange: + Verify = Method(return_bool) + +@DIGlobalVariable +class DIGlobalVariable: + Verify = Method(return_bool) + +@DIVariable +class DIVariable: + Verify = Method(return_bool) + +@DISubprogram +class DISubprogram: + Verify = Method(return_bool) + +@DINameSpace +class DINameSpace: + Verify = Method(return_bool) + +@DILexicalBlockFile +class DILexicalBlockFile: + Verify = Method(return_bool) + +@DILexicalBlock +class DILexicalBlock: + Verify = Method(return_bool) + diff --git a/llvmpy/src/Support/Dwarf.py b/llvmpy/src/Support/Dwarf.py new file mode 100644 index 0000000..caecc24 --- /dev/null +++ b/llvmpy/src/Support/Dwarf.py @@ -0,0 +1,563 @@ +from binding import * +from ..namespace import llvm + +dwarf = llvm.Namespace('dwarf') + +dwarf.includes.add('llvm/Support/Dwarf.h') + +dwarf_constants = dwarf.Enum('dwarf_constants', +''' +DWARF_VERSION +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_entry_point +DW_TAG_enumeration_type +DW_TAG_formal_parameter +DW_TAG_imported_declaration +DW_TAG_label +DW_TAG_lexical_block +DW_TAG_member +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_compile_unit +DW_TAG_string_type +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_unspecified_parameters +DW_TAG_variant +DW_TAG_common_block +DW_TAG_common_inclusion +DW_TAG_inheritance +DW_TAG_inlined_subroutine +DW_TAG_module +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_with_stmt +DW_TAG_access_declaration +DW_TAG_base_type +DW_TAG_catch_block +DW_TAG_const_type +DW_TAG_constant +DW_TAG_enumerator +DW_TAG_file_type +DW_TAG_friend +DW_TAG_namelist +DW_TAG_namelist_item +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_template_type_parameter +DW_TAG_template_value_parameter +DW_TAG_thrown_type +DW_TAG_try_block +DW_TAG_variant_part +DW_TAG_variable +DW_TAG_volatile_type +DW_TAG_dwarf_procedure +DW_TAG_restrict_type +DW_TAG_interface_type +DW_TAG_namespace +DW_TAG_imported_module +DW_TAG_unspecified_type +DW_TAG_partial_unit +DW_TAG_imported_unit +DW_TAG_condition +DW_TAG_shared_type +DW_TAG_type_unit +DW_TAG_rvalue_reference_type +DW_TAG_template_alias +DW_TAG_MIPS_loop +DW_TAG_format_label +DW_TAG_function_template +DW_TAG_class_template +DW_TAG_GNU_template_template_param +DW_TAG_GNU_template_parameter_pack +DW_TAG_GNU_formal_parameter_pack +DW_TAG_lo_user +DW_TAG_APPLE_property +DW_TAG_hi_user +DW_CHILDREN_no +DW_CHILDREN_yes +DW_AT_sibling +DW_AT_location +DW_AT_name +DW_AT_ordering +DW_AT_byte_size +DW_AT_bit_offset +DW_AT_bit_size +DW_AT_stmt_list +DW_AT_low_pc +DW_AT_high_pc +DW_AT_language +DW_AT_discr +DW_AT_discr_value +DW_AT_visibility +DW_AT_import +DW_AT_string_length +DW_AT_common_reference +DW_AT_comp_dir +DW_AT_const_value +DW_AT_containing_type +DW_AT_default_value +DW_AT_inline +DW_AT_is_optional +DW_AT_lower_bound +DW_AT_producer +DW_AT_prototyped +DW_AT_return_addr +DW_AT_start_scope +DW_AT_bit_stride +DW_AT_upper_bound +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_address_class +DW_AT_artificial +DW_AT_base_types +DW_AT_calling_convention +DW_AT_count +DW_AT_data_member_location +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_declaration +DW_AT_discr_list +DW_AT_encoding +DW_AT_external +DW_AT_frame_base +DW_AT_friend +DW_AT_identifier_case +DW_AT_macro_info +DW_AT_namelist_item +DW_AT_priority +DW_AT_segment +DW_AT_specification +DW_AT_static_link +DW_AT_type +DW_AT_use_location +DW_AT_variable_parameter +DW_AT_virtuality +DW_AT_vtable_elem_location +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_byte_stride +DW_AT_entry_pc +DW_AT_use_UTF8 +DW_AT_extension +DW_AT_ranges +DW_AT_trampoline +DW_AT_call_column +DW_AT_call_file +DW_AT_call_line +DW_AT_description +DW_AT_binary_scale +DW_AT_decimal_scale +DW_AT_small +DW_AT_decimal_sign +DW_AT_digit_count +DW_AT_picture_string +DW_AT_mutable +DW_AT_threads_scaled +DW_AT_explicit +DW_AT_object_pointer +DW_AT_endianity +DW_AT_elemental +DW_AT_pure +DW_AT_recursive +DW_AT_signature +DW_AT_main_subprogram +DW_AT_data_bit_offset +DW_AT_const_expr +DW_AT_enum_class +DW_AT_linkage_name +DW_AT_lo_user +DW_AT_hi_user +DW_AT_MIPS_loop_begin +DW_AT_MIPS_tail_loop_begin +DW_AT_MIPS_epilog_begin +DW_AT_MIPS_loop_unroll_factor +DW_AT_MIPS_software_pipeline_depth +DW_AT_MIPS_linkage_name +DW_AT_MIPS_stride +DW_AT_MIPS_abstract_name +DW_AT_MIPS_clone_origin +DW_AT_MIPS_has_inlines +DW_AT_MIPS_stride_byte +DW_AT_MIPS_stride_elem +DW_AT_MIPS_ptr_dopetype +DW_AT_MIPS_allocatable_dopetype +DW_AT_MIPS_assumed_shape_dopetype +DW_AT_MIPS_assumed_size +DW_AT_sf_names +DW_AT_src_info +DW_AT_mac_info +DW_AT_src_coords +DW_AT_body_begin +DW_AT_body_end +DW_AT_APPLE_optimized +DW_AT_APPLE_flags +DW_AT_APPLE_isa +DW_AT_APPLE_block +DW_AT_APPLE_major_runtime_vers +DW_AT_APPLE_runtime_class +DW_AT_APPLE_omit_frame_ptr +DW_AT_APPLE_property_name +DW_AT_APPLE_property_getter +DW_AT_APPLE_property_setter +DW_AT_APPLE_property_attribute +DW_AT_APPLE_objc_complete_type +DW_AT_APPLE_property +DW_FORM_addr +DW_FORM_block2 +DW_FORM_block4 +DW_FORM_data2 +DW_FORM_data4 +DW_FORM_data8 +DW_FORM_string +DW_FORM_block +DW_FORM_block1 +DW_FORM_data1 +DW_FORM_flag +DW_FORM_sdata +DW_FORM_strp +DW_FORM_udata +DW_FORM_ref_addr +DW_FORM_ref1 +DW_FORM_ref2 +DW_FORM_ref4 +DW_FORM_ref8 +DW_FORM_ref_udata +DW_FORM_indirect +DW_FORM_sec_offset +DW_FORM_exprloc +DW_FORM_flag_present +DW_FORM_ref_sig8 +DW_OP_addr +DW_OP_deref +DW_OP_const1u +DW_OP_const1s +DW_OP_const2u +DW_OP_const2s +DW_OP_const4u +DW_OP_const4s +DW_OP_const8u +DW_OP_const8s +DW_OP_constu +DW_OP_consts +DW_OP_dup +DW_OP_drop +DW_OP_over +DW_OP_pick +DW_OP_swap +DW_OP_rot +DW_OP_xderef +DW_OP_abs +DW_OP_and +DW_OP_div +DW_OP_minus +DW_OP_mod +DW_OP_mul +DW_OP_neg +DW_OP_not +DW_OP_or +DW_OP_plus +DW_OP_plus_uconst +DW_OP_shl +DW_OP_shr +DW_OP_shra +DW_OP_xor +DW_OP_skip +DW_OP_bra +DW_OP_eq +DW_OP_ge +DW_OP_gt +DW_OP_le +DW_OP_lt +DW_OP_ne +DW_OP_lit0 +DW_OP_lit1 +DW_OP_lit2 +DW_OP_lit3 +DW_OP_lit4 +DW_OP_lit5 +DW_OP_lit6 +DW_OP_lit7 +DW_OP_lit8 +DW_OP_lit9 +DW_OP_lit10 +DW_OP_lit11 +DW_OP_lit12 +DW_OP_lit13 +DW_OP_lit14 +DW_OP_lit15 +DW_OP_lit16 +DW_OP_lit17 +DW_OP_lit18 +DW_OP_lit19 +DW_OP_lit20 +DW_OP_lit21 +DW_OP_lit22 +DW_OP_lit23 +DW_OP_lit24 +DW_OP_lit25 +DW_OP_lit26 +DW_OP_lit27 +DW_OP_lit28 +DW_OP_lit29 +DW_OP_lit30 +DW_OP_lit31 +DW_OP_reg0 +DW_OP_reg1 +DW_OP_reg2 +DW_OP_reg3 +DW_OP_reg4 +DW_OP_reg5 +DW_OP_reg6 +DW_OP_reg7 +DW_OP_reg8 +DW_OP_reg9 +DW_OP_reg10 +DW_OP_reg11 +DW_OP_reg12 +DW_OP_reg13 +DW_OP_reg14 +DW_OP_reg15 +DW_OP_reg16 +DW_OP_reg17 +DW_OP_reg18 +DW_OP_reg19 +DW_OP_reg20 +DW_OP_reg21 +DW_OP_reg22 +DW_OP_reg23 +DW_OP_reg24 +DW_OP_reg25 +DW_OP_reg26 +DW_OP_reg27 +DW_OP_reg28 +DW_OP_reg29 +DW_OP_reg30 +DW_OP_reg31 +DW_OP_breg0 +DW_OP_breg1 +DW_OP_breg2 +DW_OP_breg3 +DW_OP_breg4 +DW_OP_breg5 +DW_OP_breg6 +DW_OP_breg7 +DW_OP_breg8 +DW_OP_breg9 +DW_OP_breg10 +DW_OP_breg11 +DW_OP_breg12 +DW_OP_breg13 +DW_OP_breg14 +DW_OP_breg15 +DW_OP_breg16 +DW_OP_breg17 +DW_OP_breg18 +DW_OP_breg19 +DW_OP_breg20 +DW_OP_breg21 +DW_OP_breg22 +DW_OP_breg23 +DW_OP_breg24 +DW_OP_breg25 +DW_OP_breg26 +DW_OP_breg27 +DW_OP_breg28 +DW_OP_breg29 +DW_OP_breg30 +DW_OP_breg31 +DW_OP_regx +DW_OP_fbreg +DW_OP_bregx +DW_OP_piece +DW_OP_deref_size +DW_OP_xderef_size +DW_OP_nop +DW_OP_push_object_address +DW_OP_call2 +DW_OP_call4 +DW_OP_call_ref +DW_OP_form_tls_address +DW_OP_call_frame_cfa +DW_OP_bit_piece +DW_OP_implicit_value +DW_OP_stack_value +DW_OP_lo_user +DW_OP_hi_user +DW_ATE_address +DW_ATE_boolean +DW_ATE_complex_float +DW_ATE_float +DW_ATE_signed +DW_ATE_signed_char +DW_ATE_unsigned +DW_ATE_unsigned_char +DW_ATE_imaginary_float +DW_ATE_packed_decimal +DW_ATE_numeric_string +DW_ATE_edited +DW_ATE_signed_fixed +DW_ATE_unsigned_fixed +DW_ATE_decimal_float +DW_ATE_UTF +DW_ATE_lo_user +DW_ATE_hi_user +DW_DS_unsigned +DW_DS_leading_overpunch +DW_DS_trailing_overpunch +DW_DS_leading_separate +DW_DS_trailing_separate +DW_END_default +DW_END_big +DW_END_little +DW_END_lo_user +DW_END_hi_user +DW_ACCESS_public +DW_ACCESS_protected +DW_ACCESS_private +DW_VIS_local +DW_VIS_exported +DW_VIS_qualified +DW_VIRTUALITY_none +DW_VIRTUALITY_virtual +DW_VIRTUALITY_pure_virtual +DW_LANG_C89 +DW_LANG_C +DW_LANG_Ada83 +DW_LANG_C_plus_plus +DW_LANG_Cobol74 +DW_LANG_Cobol85 +DW_LANG_Fortran77 +DW_LANG_Fortran90 +DW_LANG_Pascal83 +DW_LANG_Modula2 +DW_LANG_Java +DW_LANG_C99 +DW_LANG_Ada95 +DW_LANG_Fortran95 +DW_LANG_PLI +DW_LANG_ObjC +DW_LANG_ObjC_plus_plus +DW_LANG_UPC +DW_LANG_D +DW_LANG_Python +DW_LANG_lo_user +DW_LANG_Mips_Assembler +DW_LANG_hi_user +DW_ID_case_sensitive +DW_ID_up_case +DW_ID_down_case +DW_ID_case_insensitive +DW_CC_normal +DW_CC_program +DW_CC_nocall +DW_CC_lo_user +DW_CC_hi_user +DW_INL_not_inlined +DW_INL_inlined +DW_INL_declared_not_inlined +DW_INL_declared_inlined +DW_ORD_row_major +DW_ORD_col_major +DW_DSC_label +DW_DSC_range +DW_LNS_extended_op +DW_LNS_copy +DW_LNS_advance_pc +DW_LNS_advance_line +DW_LNS_set_file +DW_LNS_set_column +DW_LNS_negate_stmt +DW_LNS_set_basic_block +DW_LNS_const_add_pc +DW_LNS_fixed_advance_pc +DW_LNS_set_prologue_end +DW_LNS_set_epilogue_begin +DW_LNS_set_isa +DW_LNE_end_sequence +DW_LNE_set_address +DW_LNE_define_file +DW_LNE_set_discriminator +DW_LNE_lo_user +DW_LNE_hi_user +DW_MACINFO_define +DW_MACINFO_undef +DW_MACINFO_start_file +DW_MACINFO_end_file +DW_MACINFO_vendor_ext +DW_CFA_extended +DW_CFA_nop +DW_CFA_advance_loc +DW_CFA_offset +DW_CFA_restore +DW_CFA_set_loc +DW_CFA_advance_loc1 +DW_CFA_advance_loc2 +DW_CFA_advance_loc4 +DW_CFA_offset_extended +DW_CFA_restore_extended +DW_CFA_undefined +DW_CFA_same_value +DW_CFA_register +DW_CFA_remember_state +DW_CFA_restore_state +DW_CFA_def_cfa +DW_CFA_def_cfa_register +DW_CFA_def_cfa_offset +DW_CFA_def_cfa_expression +DW_CFA_expression +DW_CFA_offset_extended_sf +DW_CFA_def_cfa_sf +DW_CFA_def_cfa_offset_sf +DW_CFA_val_offset +DW_CFA_val_offset_sf +DW_CFA_val_expression +DW_CFA_MIPS_advance_loc8 +DW_CFA_GNU_window_save +DW_CFA_GNU_args_size +DW_CFA_lo_user +DW_CFA_hi_user +DW_EH_PE_absptr +DW_EH_PE_omit +DW_EH_PE_uleb128 +DW_EH_PE_udata2 +DW_EH_PE_udata4 +DW_EH_PE_udata8 +DW_EH_PE_sleb128 +DW_EH_PE_sdata2 +DW_EH_PE_sdata4 +DW_EH_PE_sdata8 +DW_EH_PE_signed +DW_EH_PE_pcrel +DW_EH_PE_textrel +DW_EH_PE_datarel +DW_EH_PE_funcrel +DW_EH_PE_aligned +DW_EH_PE_indirect +DW_APPLE_PROPERTY_readonly +DW_APPLE_PROPERTY_readwrite +DW_APPLE_PROPERTY_assign +DW_APPLE_PROPERTY_retain +DW_APPLE_PROPERTY_copy +DW_APPLE_PROPERTY_nonatomic +''') + +### The following enums are not available in LLVM 3.2 +# DW_AT_GNU_dwo_name +# DW_AT_GNU_vector +# DW_AT_GNU_template_name +# DW_AT_GNU_dwo_id +# DW_AT_GNU_ranges_base +# DW_AT_GNU_addr_base +# DW_AT_GNU_pubnames +# DW_AT_GNU_pubtypes +# DW_FORM_GNU_addr_index +# DW_FORM_GNU_str_index +# DW_OP_GNU_addr_index +# DW_OP_GNU_const_index From 84f1b433def8c4ef9a829c21a14cc26e523117df Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 30 May 2013 14:04:08 -0500 Subject: [PATCH 017/149] Use if-else instead of try-except for perf reason --- llvmpy/capsule.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index f66836f..1b3813b 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -141,9 +141,10 @@ def wrap(cap, owned=False): cls = cap.get_class() addr = cap.pointer name = cap.name - try: # lookup cached object - return _cache[cls][addr] - except KeyError: + # lookup cached object + if cls in _cache and addr in _cache[cls]: + obj = _cache[cls][addr] + else: if not owned and cls._has_dtor(): _addr2dtor[(name, addr)] = cls._delete_ obj = cap.instantiate() @@ -207,11 +208,10 @@ def downcast(obj, cls): logger.debug("Downcast %s to %s" , fromty, toty) fname = 'downcast_%s_to_%s' % (fromty, toty) fname = fname.replace('::', '_') - try: - caster = getattr(_api.downcast, fname) - except AttributeError: + if not hasattr(_api.downcast, fname): fmt = "Downcast from %s to %s is not supported" raise TypeError(fmt % (fromty, toty)) + caster = getattr(_api.downcast, fname) old = unwrap(obj) new = caster(old) used_to_own = has_ownership(old) From 69c75355f4a919fa04ab49a5f933aaa99ec95bfb Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 31 May 2013 11:47:51 -0500 Subject: [PATCH 018/149] fix future import --- llvm_array/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm_array/__init__.py b/llvm_array/__init__.py index 5e807c2..08dd11b 100644 --- a/llvm_array/__init__.py +++ b/llvm_array/__init__.py @@ -1,2 +1,2 @@ -from __future__ import absolute_imports +from __future__ import absolute_import from .array import * From ad287faeb1f4473e112ef428e05610020c5357a1 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 31 May 2013 14:01:57 -0500 Subject: [PATCH 019/149] Fixes a werid case of refct problem --- llvmpy/capsule.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 1b3813b..5efed13 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -56,15 +56,15 @@ class Capsule(object): @property def classname(self): - return Capsule.getClassName(self.capsule) + return self.getClassName(self.capsule) @property def name(self): - return Capsule.getName(self.capsule) + return self.getName(self.capsule) @property def pointer(self): - return Capsule.getPointer(self.capsule) + return self.getPointer(self.capsule) @staticmethod def valid(capsule): From 2415042a2a07e99b24ab6859edb4d5d341ad5ea6 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 31 May 2013 15:01:02 -0500 Subject: [PATCH 020/149] DIDescriptor does not inherit MDNode --- llvmpy/src/DebugInfo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvmpy/src/DebugInfo.py b/llvmpy/src/DebugInfo.py index 81fe168..8ddb1ee 100644 --- a/llvmpy/src/DebugInfo.py +++ b/llvmpy/src/DebugInfo.py @@ -4,7 +4,7 @@ from .namespace import llvm from .ADT.StringRef import StringRef from .Value import MDNode -DIDescriptor = llvm.Class(MDNode) +DIDescriptor = llvm.Class() DIEnumerator = llvm.Class(DIDescriptor) DIScope = llvm.Class(DIDescriptor) DIType = llvm.Class(DIScope) @@ -29,7 +29,8 @@ return_unsigned = cast(Unsigned, int) @DIDescriptor class DIDescriptor: - pass + new = Constructor(ptr(MDNode)) + delete = Destructor() @DIScope class DIScope: From 2338eae5f6a91651125b8180abafa8c9afaa90d8 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 13 Jun 2013 17:17:43 -0500 Subject: [PATCH 021/149] Fix py3 str has no buffer interface --- llvmpy/include/llvm_binding/extra.h | 67 ++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 6626ede..456f75e 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -270,7 +270,12 @@ llvm::ExecutionEngine* ExecutionEngine_create( ExecutionEngine *ee = ExecutionEngine::create(M, ForceInterpreter, &ErrorStr, OptLevel, GVsWithCode); - PyFile_WriteString(ErrorStr.c_str(), errout); + auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str()); + if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){ + return NULL; + } + +// PyFile_WriteString(ErrorStr.c_str(), errout); return ee; } @@ -292,7 +297,11 @@ llvm::ExecutionEngine* ExecutionEngine_createJIT( std::string ErrorStr; ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL, GCsWithCode, RM, CMM); - PyFile_WriteString(ErrorStr.c_str(), errout); + auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str()); + if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){ + return NULL; + } +// PyFile_WriteString(ErrorStr.c_str(), errout); return ee; } @@ -512,9 +521,13 @@ PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf, if (FObj) { std::string ErrStr; Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr); - if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { + auto_pyobject buf = PyBytes_FromString(ErrStr.c_str()); + if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){ return NULL; } +// if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { +// return NULL; +// } } else { Triple = getBitcodeTargetTriple(MB, Ctx); } @@ -585,9 +598,15 @@ PyObject* Linker_LinkInModule(llvm::Linker* Linker, if (! failed) { Py_RETURN_FALSE; } else { - if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); + if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ return NULL; } + +// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { +// return NULL; +// } Py_RETURN_TRUE; } } @@ -603,9 +622,13 @@ PyObject* Linker_LinkModules(llvm::Module* Dest, if (! failed) { Py_RETURN_FALSE; } else { - if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); + if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ return NULL; } +// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { +// return NULL; +// } Py_RETURN_TRUE; } } @@ -665,9 +688,14 @@ PyObject* llvm_verifyModule(const llvm::Module& Fn, bool failed = llvm::verifyModule(Fn, Action, &errmsg); if (failed) { - if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); + if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ return NULL; } + +// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { +// return NULL; +// } Py_RETURN_TRUE; } else { Py_RETURN_FALSE; @@ -790,9 +818,13 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, std::string errmsg; failed = DynamicLibrary::LoadLibraryPermanently(Filename, &errmsg); if (failed) { - if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); + if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ return NULL; } +// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { +// return NULL; +// } } } else { failed = DynamicLibrary::LoadLibraryPermanently(Filename); @@ -835,7 +867,12 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Triple, std::string error; const Target* target = TargetRegistry::lookupTarget(Triple, error); if (!target) { - PyFile_WriteString(error.c_str(), Error); +// PyFile_WriteString(error.c_str(), Error); + auto_pyobject buf = PyBytes_FromString(error.c_str()); + if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + return NULL; + } + Py_RETURN_NONE; } else { return pycapsule_new(const_cast(target), "llvm::Target"); @@ -852,7 +889,12 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Arch, std::string error; const Target* target = TargetRegistry::lookupTarget(Arch, Triple, error); if (!target) { - PyFile_WriteString(error.c_str(), Error); +// PyFile_WriteString(error.c_str(), Error); + auto_pyobject buf = PyBytes_FromString(error.c_str()); + if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + return NULL; + } + Py_RETURN_NONE; } else { return pycapsule_new(const_cast(target), "llvm::Target"); @@ -867,7 +909,12 @@ PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error) std::string error; const Target* target = TargetRegistry::getClosestTargetForJIT(error); if (!target) { - PyFile_WriteString(error.c_str(), Error); + auto_pyobject buf = PyBytes_FromString(error.c_str()); + if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + return NULL; + } + +// PyFile_WriteString(error.c_str(), Error); Py_RETURN_NONE; } else { return pycapsule_new(const_cast(target), "llvm::Target"); From 4c1b9016fb513a96463b68472ec6a5e6c1416912 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 15:12:23 -0500 Subject: [PATCH 022/149] binding compiles with llvm 3.3 --- llvmpy/gen/binding.py | 3 +- llvmpy/include/llvm_binding/extra.h | 83 +++++++++++----- llvmpy/src/Argument.py | 19 +++- llvmpy/src/Attributes.py | 101 +++++++++++++++----- llvmpy/src/DIBuilder.py | 38 +++++--- llvmpy/src/DataLayout.py | 5 +- llvmpy/src/DerivedTypes.py | 5 +- llvmpy/src/Function.py | 22 ++++- llvmpy/src/GlobalValue.py | 5 +- llvmpy/src/IRBuilder.py | 6 +- llvmpy/src/InlineAsm.py | 5 +- llvmpy/src/Instruction.py | 26 +++-- llvmpy/src/LLVMContext.py | 5 +- llvmpy/src/Linker.py | 35 +++---- llvmpy/src/Module.py | 5 +- llvmpy/src/Support/Host.py | 29 ++++-- llvmpy/src/Target/TargetMachine.py | 12 ++- llvmpy/src/TargetTransformInfo.py | 16 +++- llvmpy/src/Transforms/PassManagerBuilder.py | 6 +- llvmpy/src/Type.py | 5 +- llvmpy/src/ValueSymbolTable.py | 5 +- setup.py | 7 +- 22 files changed, 324 insertions(+), 119 deletions(-) diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index 8006fd9..db4fdbf 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -247,7 +247,8 @@ class Class(SubModule, _Type): def __call__(self, defn): assert not self._is_defined # process the definition in "defn" - self.name = defn.__name__ + self.name = getattr(defn, '_name_', defn.__name__) + for k, v in defn.__dict__.items(): if isinstance(v, Method): self.methods.append(v) diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 456f75e..cd1f59c 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -1,8 +1,22 @@ #include #include -#include -#include -#include +#if LLVM_VERSION_MAJOR >= 3 and LLVM_VERSION_MINOR >= 3 + #include + #include + #include + #include + #include + #include + #include +#else + #include + #include + #include + #include + #include + #include + #include +#endif #include #include #include @@ -12,11 +26,7 @@ #include #include #include -#include #include -#include -#include -#include #include #include @@ -56,6 +66,15 @@ namespace extra{ } +static +PyObject* callwrite(PyObject* self, PyObject* arg) +{ + char meth[] = "method"; + char fmt[] = "O"; + return PyObject_CallMethod(self, meth, fmt, arg); +} + + static PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { @@ -271,7 +290,7 @@ llvm::ExecutionEngine* ExecutionEngine_create( &ErrorStr, OptLevel, GVsWithCode); auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str()); - if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){ + if (errout && NULL == callwrite(errout, *buf)){ return NULL; } @@ -298,7 +317,7 @@ llvm::ExecutionEngine* ExecutionEngine_createJIT( ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL, GCsWithCode, RM, CMM); auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str()); - if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){ + if (errout && NULL == callwrite(errout, *buf)){ return NULL; } // PyFile_WriteString(ErrorStr.c_str(), errout); @@ -483,7 +502,7 @@ PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx, std::string ErrStr; M = ParseBitcodeFile(MB, Ctx, &ErrStr); auto_pyobject buf = PyBytes_FromString(ErrStr.c_str()); - if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){ + if (NULL == callwrite(FObj, *buf)){ return NULL; } // if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { @@ -507,7 +526,7 @@ PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj) rso.flush(); StringRef ref = rso.str(); auto_pyobject buf = PyBytes_FromStringAndSize(ref.data(), ref.size()); - return PyObject_CallMethod(FObj, "write", "O", *buf); + return callwrite(FObj, *buf); } static @@ -522,7 +541,7 @@ PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf, std::string ErrStr; Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr); auto_pyobject buf = PyBytes_FromString(ErrStr.c_str()); - if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){ + if (NULL == callwrite(FObj, *buf)){ return NULL; } // if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { @@ -594,19 +613,19 @@ PyObject* Linker_LinkInModule(llvm::Linker* Linker, PyObject* ErrMsg) { std::string errmsg; +#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 3 + bool failed = Linker->linkInModule(Mod, &errmsg); +#else bool failed = Linker->LinkInModule(Mod, &errmsg); +#endif if (! failed) { Py_RETURN_FALSE; } else { auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); - if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ + if (NULL == callwrite(ErrMsg, *buf)){ return NULL; } - -// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { -// return NULL; -// } Py_RETURN_TRUE; } } @@ -623,7 +642,7 @@ PyObject* Linker_LinkModules(llvm::Module* Dest, Py_RETURN_FALSE; } else { auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); - if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ + if (NULL == callwrite(ErrMsg, *buf)){ return NULL; } // if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { @@ -689,7 +708,7 @@ PyObject* llvm_verifyModule(const llvm::Module& Fn, if (failed) { auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); - if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ + if (NULL == callwrite(ErrMsg, *buf)){ return NULL; } @@ -819,7 +838,7 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, failed = DynamicLibrary::LoadLibraryPermanently(Filename, &errmsg); if (failed) { auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); - if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ + if (NULL == callwrite(ErrMsg, *buf)){ return NULL; } // if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { @@ -869,7 +888,7 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Triple, if (!target) { // PyFile_WriteString(error.c_str(), Error); auto_pyobject buf = PyBytes_FromString(error.c_str()); - if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + if (NULL == callwrite(Error, *buf)){ return NULL; } @@ -891,7 +910,7 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Arch, if (!target) { // PyFile_WriteString(error.c_str(), Error); auto_pyobject buf = PyBytes_FromString(error.c_str()); - if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + if (NULL == callwrite(Error, *buf)){ return NULL; } @@ -910,7 +929,7 @@ PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error) const Target* target = TargetRegistry::getClosestTargetForJIT(error); if (!target) { auto_pyobject buf = PyBytes_FromString(error.c_str()); - if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + if (NULL == callwrite(Error, *buf)){ return NULL; } @@ -945,3 +964,21 @@ PyObject* llvm_sys_getHostCPUFeatures(PyObject* Features) } } + +static +PyObject* llvm_sys_isLittleEndianHost() +{ + if (llvm::sys::IsLittleEndianHost) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +static +PyObject* llvm_sys_isBigEndianHost() +{ + if (llvm::sys::IsBigEndianHost) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} \ No newline at end of file diff --git a/llvmpy/src/Argument.py b/llvmpy/src/Argument.py index 6262147..a08cca1 100644 --- a/llvmpy/src/Argument.py +++ b/llvmpy/src/Argument.py @@ -1,16 +1,27 @@ from binding import * from .namespace import llvm from .Value import Argument, Value -from .Attributes import Attributes +if LLVM_VERSION >= (3, 3): + from .Attributes import AttributeSet, Attribute +else: + from .Attributes import Attributes @Argument class Argument: - _include_ = 'llvm/Argument.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/Argument.h' + else: + _include_ = 'llvm/Argument.h' _downcast_ = Value - addAttr = Method(Void, ref(Attributes)) - removeAttr = Method(Void, ref(Attributes)) + if LLVM_VERSION >= (3, 3): + addAttr = Method(Void, ref(AttributeSet)) + removeAttr = Method(Void, ref(AttributeSet)) + else: + addAttr = Method(Void, ref(Attributes)) + removeAttr = Method(Void, ref(Attributes)) + getParamAlignment = Method(cast(Unsigned, int)) getArgNo = Method(cast(Unsigned, int)) diff --git a/llvmpy/src/Attributes.py b/llvmpy/src/Attributes.py index 4fe7651..303d61d 100644 --- a/llvmpy/src/Attributes.py +++ b/llvmpy/src/Attributes.py @@ -2,38 +2,91 @@ from binding import * from .namespace import llvm from .LLVMContext import LLVMContext -llvm.includes.add('llvm/Attributes.h') +if LLVM_VERSION >= (3, 3): + llvm.includes.add('llvm/IR/Attributes.h') +else: + llvm.includes.add('llvm/Attributes.h') + -Attributes = llvm.Class() AttrBuilder = llvm.Class() - -@Attributes -class Attributes: - AttrVal = Enum('''None, AddressSafety, Alignment, AlwaysInline, - ByVal, InlineHint, InReg, MinSize, - Naked, Nest, NoAlias, NoCapture, - NoImplicitFloat, NoInline, NonLazyBind, NoRedZone, - NoReturn, NoUnwind, OptimizeForSize, ReadNone, - ReadOnly, ReturnsTwice, SExt, StackAlignment, - StackProtect, StackProtectReq, StructRet, UWTable, ZExt''') - - delete = Destructor() - - get = StaticMethod(Attributes, ref(LLVMContext), ref(AttrBuilder)) +if LLVM_VERSION >= (3, 3): + Attribute = llvm.Class() + AttributeSet = llvm.Class() +else: + Attributes = llvm.Class() -@AttrBuilder -class AttrBuilder: +if LLVM_VERSION >= (3, 3): + @Attribute + class Attribute: + AttrKind = Enum('''None, Alignment, AlwaysInline, + ByVal, InlineHint, InReg, + MinSize, Naked, Nest, NoAlias, + NoBuiltin, NoCapture, NoDuplicate, NoImplicitFloat, + NoInline, NonLazyBind, NoRedZone, NoReturn, + NoUnwind, OptimizeForSize, ReadNone, ReadOnly, + Returned, ReturnsTwice, SExt, StackAlignment, + StackProtect, StackProtectReq, StackProtectStrong, StructRet, + SanitizeAddress, SanitizeThread, SanitizeMemory, UWTable, + ZExt, EndAttrKinds''') - new = Constructor() - delete = Destructor() + delete = Destructor() - clear = Method() + get = StaticMethod(Attribute, + ref(LLVMContext), + AttrKind, + cast(int, Uint64)).require_only(2) - addAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) - removeAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) + @AttrBuilder + class AttrBuilder: - addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned)) + new = Constructor() + delete = Destructor() + + clear = Method() + + addAttribute = Method(ref(AttrBuilder), Attribute.AttrKind) + removeAttribute = Method(ref(AttrBuilder), Attribute.AttrKind) + + addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned)) + + @AttributeSet + class AttributeSet: + delete = Destructor() + + get = StaticMethod(AttributeSet, + ref(LLVMContext), + cast(int, Unsigned), + ref(AttrBuilder)) + +else: + @Attributes + class Attributes: + AttrVal = Enum('''None, AddressSafety, Alignment, AlwaysInline, + ByVal, InlineHint, InReg, MinSize, + Naked, Nest, NoAlias, NoCapture, + NoImplicitFloat, NoInline, NonLazyBind, NoRedZone, + NoReturn, NoUnwind, OptimizeForSize, ReadNone, + ReadOnly, ReturnsTwice, SExt, StackAlignment, + StackProtect, StackProtectReq, StructRet, UWTable, ZExt''') + + delete = Destructor() + + get = StaticMethod(Attributes, ref(LLVMContext), ref(AttrBuilder)) + + + @AttrBuilder + class AttrBuilder: + + new = Constructor() + delete = Destructor() + + clear = Method() + + addAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) + removeAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) + + addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned)) diff --git a/llvmpy/src/DIBuilder.py b/llvmpy/src/DIBuilder.py index 9671963..cb934d4 100644 --- a/llvmpy/src/DIBuilder.py +++ b/llvmpy/src/DIBuilder.py @@ -124,17 +124,31 @@ class DIBuilder: ptr(MDNode), # TemplateParms = 0 ).require_only(10) - createStructType = Method(DIType, - ref(DIDescriptor), # Scope - stringref_arg, # Name - ref(DIFile), # File - unsigned_arg, # LineNumber - uint64_arg, # SizeInBits - uint64_arg, # AlignInBits - unsigned_arg, # Flags - ref(DIArray), # Elements - unsigned_arg, # RunTimeLang = 0 - ).require_only(8) + if LLVM_VERSION >= (3, 3): + createStructType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNumber + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + unsigned_arg, # Flags + ref(DIType), # DerivedFrom + ref(DIArray), # Elements + unsigned_arg, # RunTimeLang = 0 + ).require_only(9) + else: + createStructType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNumber + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + unsigned_arg, # Flags + ref(DIArray), # Elements + unsigned_arg, # RunTimeLang = 0 + ).require_only(8) createUnionType = Method(DIType, ref(DIDescriptor), # Scope @@ -186,7 +200,7 @@ class DIBuilder: ref(DIType), # Ty ) - createTemporaryType = Method(DIType, ref(DIFile)).require_only(0) + #createTemporaryType = Method(DIType, ref(DIFile)).require_only(0) createForwardDecl = Method(DIType, unsigned_arg, # Tag diff --git a/llvmpy/src/DataLayout.py b/llvmpy/src/DataLayout.py index 812a83d..6741cda 100644 --- a/llvmpy/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -15,7 +15,10 @@ from .GlobalVariable import GlobalVariable @DataLayout class DataLayout: - _include_ = 'llvm/DataLayout.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/DataLayout.h' + else: + _include_ = 'llvm/DataLayout.h' _new_string = Constructor(cast(str, StringRef)) _new_module = Constructor(ptr(Module)) diff --git a/llvmpy/src/DerivedTypes.py b/llvmpy/src/DerivedTypes.py index 02eec8c..fde01f3 100644 --- a/llvmpy/src/DerivedTypes.py +++ b/llvmpy/src/DerivedTypes.py @@ -8,7 +8,10 @@ FunctionType = llvm.Class(Type) @FunctionType class FunctionType: - _include_ = 'llvm/DerivedTypes.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/DerivedTypes.h' + else: + _include_ = 'llvm/DerivedTypes.h' _downcast_ = Type _get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index 04c3e65..9c2c8b7 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -4,7 +4,10 @@ from .Value import GlobalValue, Constant, Function, Argument, Value from .Module import Module from .BasicBlock import BasicBlock from .ValueSymbolTable import ValueSymbolTable -from .Attributes import Attributes +if LLVM_VERSION >= (3, 3): + from .Attributes import Attribute, AttributeSet +else: + from .Attributes import Attributes from .Type import Type from .DerivedTypes import FunctionType from .LLVMContext import LLVMContext @@ -12,7 +15,11 @@ from .CallingConv import CallingConv @Function class Function: - _include_ = 'llvm/Function.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/Function.h' + else: + _include_ = 'llvm/Function.h' + _downcast_ = GlobalValue, Constant, Value getReturnType = Method(ptr(Type)) @@ -48,10 +55,17 @@ class Function: deleteBody = Method() viewCFG = Method() + viewCFGOnly = Method() - addFnAttr = Method(Void, Attributes.AttrVal) - removeFnAttr = Method(Void, ref(Attributes)) + if LLVM_VERSION >= (3, 3): + addFnAttr = Method(Void, Attribute.AttrKind) + addAttributes = Method(Void, cast(int, Unsigned), ref(AttributeSet)) + removeAttributes = Method(Void, cast(int, Unsigned), ref(AttributeSet)) + #removeFnAttr = Method(Void, Attribute.AttrKind) # 3.4? + else: + addFnAttr = Method(Void, Attributes.AttrVal) + removeFnAttr = Method(Void, ref(Attributes)) #hasFnAttribute = Method(cast(Bool, bool), Attributes.AttrVal) Create = StaticMethod(ptr(Function), diff --git a/llvmpy/src/GlobalValue.py b/llvmpy/src/GlobalValue.py index d954ed0..49071e3 100644 --- a/llvmpy/src/GlobalValue.py +++ b/llvmpy/src/GlobalValue.py @@ -6,7 +6,10 @@ from .ADT.StringRef import StringRef @GlobalValue class GlobalValue: - _include_ = 'llvm/GlobalValue.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/GlobalValue.h' + else: + _include_ = 'llvm/GlobalValue.h' LinkageTypes = Enum(''' ExternalLinkage, AvailableExternallyLinkage, LinkOnceAnyLinkage, diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index c0766e9..c4d8a86 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -18,7 +18,11 @@ IRBuilder = llvm.Class() @IRBuilder class IRBuilder: - _include_ = 'llvm/IRBuilder.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/IRBuilder.h' + else: + _include_ = 'llvm/IRBuilder.h' + _realname_ = 'IRBuilder<>' new = Constructor(ref(LLVMContext)) diff --git a/llvmpy/src/InlineAsm.py b/llvmpy/src/InlineAsm.py index 8793343..c96cef0 100644 --- a/llvmpy/src/InlineAsm.py +++ b/llvmpy/src/InlineAsm.py @@ -4,7 +4,10 @@ from .Value import Value from .DerivedTypes import FunctionType from .ADT.StringRef import StringRef -llvm.includes.add('llvm/InlineAsm.h') +if LLVM_VERSION >= (3, 3): + llvm.includes.add('llvm/IR/InlineAsm.h') +else: + llvm.includes.add('llvm/InlineAsm.h') InlineAsm = llvm.Class(Value) diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index e17e8a1..2771015 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -65,7 +65,10 @@ SynchronizationScope = llvm.Enum('SynchronizationScope', from .ADT.StringRef import StringRef from .CallingConv import CallingConv -from .Attributes import Attributes +if LLVM_VERSION >= (3, 3): + from .Attributes import AttributeSet, Attribute +else: + from .Attributes import Attributes from .Type import Type @@ -142,8 +145,12 @@ class CallInst: getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) - addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) - removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + if LLVM_VERSION >= (3, 3): + addAttribute = Method(Void, cast(int, Unsigned), Attribute.AttrKind) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attribute)) + else: + addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) getCalledFunction = Method(ptr(Function)) getCalledValue = Method(ptr(Value)) setCalledFunction = Method(Void, ptr(Function)) @@ -264,7 +271,10 @@ class UnaryInstruction: @IntrinsicInst class IntrinsicInst: - _include_ = 'llvm/IntrinsicInst.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/IntrinsicInst.h' + else: + _include_ = 'llvm/IntrinsicInst.h' _downcast_ = Value, User, Instruction #compare @@ -292,8 +302,12 @@ class InvokeInst: getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) - addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) - removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + if LLVM_VERSION >= (3, 3): + addAttribute = Method(Void, cast(int, Unsigned), Attribute.AttrKind) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attribute)) + else: + addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) getCalledFunction = Method(ptr(Function)) getCalledValue = Method(ptr(Value)) setCalledFunction = Method(Void, ptr(Function)) diff --git a/llvmpy/src/LLVMContext.py b/llvmpy/src/LLVMContext.py index 4a6b49a..8ec1607 100644 --- a/llvmpy/src/LLVMContext.py +++ b/llvmpy/src/LLVMContext.py @@ -3,6 +3,9 @@ from .namespace import llvm @llvm.Class() class LLVMContext: - _include_ = "llvm/LLVMContext.h" + if LLVM_VERSION >= (3, 3): + _include_ = "llvm/IR/LLVMContext.h" + else: + _include_ = "llvm/LLVMContext.h" llvm.Function('getGlobalContext', ref(LLVMContext)) diff --git a/llvmpy/src/Linker.py b/llvmpy/src/Linker.py index 960bd90..5f1b7af 100644 --- a/llvmpy/src/Linker.py +++ b/llvmpy/src/Linker.py @@ -10,30 +10,33 @@ Linker = llvm.Class() @Linker class Linker: - ControlFlags = Enum('Verbose, QuietWarnings, QuietErrors') + #ControlFlags = Enum('Verbose, QuietWarnings, QuietErrors') LinkerMode = Enum('DestroySource, PreserveSource') - _new_w_empty = Constructor(cast(str, StringRef), - cast(str, StringRef), - ref(LLVMContext), - cast(int, Unsigned)).require_only(3) + if LLVM_VERSION >= (3, 3): + new = Constructor(ptr(Module)) + else: + _new_w_empty = Constructor(cast(str, StringRef), + cast(str, StringRef), + ref(LLVMContext), + cast(int, Unsigned)).require_only(3) - _new_w_existing = Constructor(cast(str, StringRef), - ptr(Module), - cast(int, Unsigned)).require_only(2) + _new_w_existing = Constructor(cast(str, StringRef), + ptr(Module), + cast(int, Unsigned)).require_only(2) - @CustomPythonStaticMethod - def new(progname, module_or_name, *args): - if isinstance(module_or_name, Module): - return _new_w_existing(progname, module_or_name, *args) - else: - return _new_w_empty(progname, module_or_name, *args) + @CustomPythonStaticMethod + def new(progname, module_or_name, *args): + if isinstance(module_or_name, Module): + return _new_w_existing(progname, module_or_name, *args) + else: + return _new_w_empty(progname, module_or_name, *args) delete = Destructor() getModule = Method(ptr(Module)) - releaseModule = Method(ptr(Module)) - getLastError = Method(cast(ConstStdString, str)) + #releaseModule = Method(ptr(Module)) + #getLastError = Method(cast(ConstStdString, str)) LinkInModule = CustomMethod('Linker_LinkInModule', PyObjectPtr, # boolean diff --git a/llvmpy/src/Module.py b/llvmpy/src/Module.py index 46fad5a..9dbe754 100644 --- a/llvmpy/src/Module.py +++ b/llvmpy/src/Module.py @@ -16,7 +16,10 @@ from .Metadata import NamedMDNode @Module class Module: - _include_ = "llvm/Module.h" + if LLVM_VERSION >= (3, 3): + _include_ = "llvm/IR/Module.h" + else: + _include_ = "llvm/Module.h" # Enumerators Endianness = Enum('AnyEndianness', 'LittleEndian', 'BigEndian') PointerSize = Enum('AnyPointerSize', 'Pointer32', 'Pointer64') diff --git a/llvmpy/src/Support/Host.py b/llvmpy/src/Support/Host.py index 8163ebe..cd063e8 100644 --- a/llvmpy/src/Support/Host.py +++ b/llvmpy/src/Support/Host.py @@ -1,18 +1,29 @@ from binding import * from src.namespace import sys -isLittleEndianHost = sys.Function('isLittleEndianHost', - cast(Bool, bool)) - -isBigEndianHost = sys.Function('isBigEndianHost', - cast(Bool, bool)) - getDefaultTargetTriple = sys.Function('getDefaultTargetTriple', cast(ConstStdString, str)) -# llvm 3.3 -#getProcessTriple = sys.Function('getProcessTriple', -# cast(ConstStdString, str)) +if LLVM_VERSION >= (3, 3): + getProcessTriple = sys.Function('getProcessTriple', + cast(ConstStdString, str)) + + isLittleEndianHost = sys.CustomFunction('isLittleEndianHost', + 'llvm_sys_isLittleEndianHost', + cast(Bool, bool)) + + isBigEndianHost = sys.CustomFunction('isBigEndianHost', + 'llvm_sys_isBigEndianHost', + cast(Bool, bool)) + +else: + + isLittleEndianHost = sys.Function('isLittleEndianHost', + cast(Bool, bool)) + + isBigEndianHost = sys.Function('isBigEndianHost', + cast(Bool, bool)) + getHostCPUName = sys.Function('getHostCPUName', cast(ConstStdString, str)) diff --git a/llvmpy/src/Target/TargetMachine.py b/llvmpy/src/Target/TargetMachine.py index 1bd6843..84c0d5d 100644 --- a/llvmpy/src/Target/TargetMachine.py +++ b/llvmpy/src/Target/TargetMachine.py @@ -8,8 +8,10 @@ from src.ADT.StringRef import StringRef from src.Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc from src.GlobalValue import GlobalValue from src.DataLayout import DataLayout -from src.TargetTransformInfo import (ScalarTargetTransformInfo, - VectorTargetTransformInfo) + +if LLVM_VERSION < (3, 3): + from src.TargetTransformInfo import (ScalarTargetTransformInfo, + VectorTargetTransformInfo) from src.PassManager import PassManagerBase from src.Support.FormattedStream import formatted_raw_ostream @@ -39,9 +41,11 @@ class TargetMachine: setMCUseDwarfDirectory = Method(Void, cast(bool, Bool)) getDataLayout = Method(const(ownedptr(DataLayout))) - getScalarTargetTransformInfo = Method(const( + + if LLVM_VERSION < (3, 3): + getScalarTargetTransformInfo = Method(const( ownedptr(ScalarTargetTransformInfo))) - getVectorTargetTransformInfo = Method(const( + getVectorTargetTransformInfo = Method(const( ownedptr(VectorTargetTransformInfo))) addPassesToEmitFile = Method(cast(bool, Bool), diff --git a/llvmpy/src/TargetTransformInfo.py b/llvmpy/src/TargetTransformInfo.py index 1208050..d51bc52 100644 --- a/llvmpy/src/TargetTransformInfo.py +++ b/llvmpy/src/TargetTransformInfo.py @@ -2,7 +2,10 @@ from binding import * from src.namespace import llvm from src.Pass import ImmutablePass -llvm.includes.add('llvm/TargetTransformInfo.h') +if LLVM_VERSION >= (3, 3): + llvm.includes.add('llvm/Analysis/TargetTransformInfo.h') +else: + llvm.includes.add('llvm/TargetTransformInfo.h') TargetTransformInfo = llvm.Class(ImmutablePass) ScalarTargetTransformInfo = llvm.Class() @@ -11,14 +14,17 @@ VectorTargetTransformInfo = llvm.Class() @ScalarTargetTransformInfo class ScalarTargetTransformInfo: - delete = Destructor() + if LLVM_VERSION < (3, 3): + delete = Destructor() @VectorTargetTransformInfo class VectorTargetTransformInfo: - delete = Destructor() + if LLVM_VERSION < (3, 3): + delete = Destructor() @TargetTransformInfo class TargetTransformInfo: - new = Constructor(ptr(ScalarTargetTransformInfo), - ptr(VectorTargetTransformInfo)) + if LLVM_VERSION < (3, 3): + new = Constructor(ptr(ScalarTargetTransformInfo), + ptr(VectorTargetTransformInfo)) diff --git a/llvmpy/src/Transforms/PassManagerBuilder.py b/llvmpy/src/Transforms/PassManagerBuilder.py index 86be4fb..146d409 100644 --- a/llvmpy/src/Transforms/PassManagerBuilder.py +++ b/llvmpy/src/Transforms/PassManagerBuilder.py @@ -36,7 +36,11 @@ class PassManagerBuilder: DisableSimplifyLibCalls = _attr_bool() DisableUnitAtATime = _attr_bool() DisableUnrollLoops = _attr_bool() - Vectorize = _attr_bool() + if LLVM_VERSION >= (3, 3): + BBVectorize = _attr_bool() + SLPVectorize = _attr_bool() + else: + Vectorize = _attr_bool() LoopVectorize = _attr_bool() LibraryInfo = Attr(getter=ownedptr(TargetLibraryInfo), diff --git a/llvmpy/src/Type.py b/llvmpy/src/Type.py index afc148c..50c4862 100644 --- a/llvmpy/src/Type.py +++ b/llvmpy/src/Type.py @@ -15,7 +15,10 @@ VectorType = llvm.Class(SequentialType) @Type class Type: - _include_ = 'llvm/Type.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/Type.h' + else: + _include_ = 'llvm/Type.h' TypeID = Enum(''' VoidTyID, HalfTyID, FloatTyID, DoubleTyID, diff --git a/llvmpy/src/ValueSymbolTable.py b/llvmpy/src/ValueSymbolTable.py index 7e8890c..8762156 100644 --- a/llvmpy/src/ValueSymbolTable.py +++ b/llvmpy/src/ValueSymbolTable.py @@ -4,7 +4,10 @@ from .ADT.StringRef import StringRef @ValueSymbolTable class ValueSymbolTable: - _include_ = 'llvm/ValueSymbolTable.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/ValueSymbolTable.h' + else: + _include_ = 'llvm/ValueSymbolTable.h' new = Constructor() delete = Destructor() lookup = Method(ptr(Value), cast(str, StringRef)) diff --git a/setup.py b/setup.py index 1dc8af8..2c3a38f 100644 --- a/setup.py +++ b/setup.py @@ -61,7 +61,12 @@ def auto_intrinsic_gen(incdir): # let's do auto intrinsic generation print("Generate intrinsic IDs") from tools import intrgen - path = "%s/llvm/Intrinsics.gen" % incdir + + if llvm_version >= (3, 3): + path = "%s/llvm/IR/Intrinsics.gen" % incdir + else: + path = "%s/llvm/Intrinsics.gen" % incdir + with open('llvm/_intrinsic_ids.py', 'w') as fout: intrgen.gen(path, fout) From 6d3253e4ea39a857a0f6119f561b8fd3e3ee50c3 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 15:44:01 -0500 Subject: [PATCH 023/149] Add things to make MCJIT working --- llvm-config-win32.py | 2 ++ llvm/ee.py | 2 +- llvmpy/include/llvm_binding/extra.h | 1 + llvmpy/src/ExecutionEngine/ExecutionEngine.py | 2 ++ setup.py | 2 +- 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 5f6c401..e191290 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -53,6 +53,7 @@ LLVMInterpreter LLVMipa LLVMipo LLVMJIT +LLVMMCJIT LLVMLinker LLVMMC LLVMMCParser @@ -71,6 +72,7 @@ LLVMX86Desc LLVMX86Disassembler LLVMX86Info LLVMX86Utils +LLVMDebugInfo Advapi32 Shell32 """.split(): diff --git a/llvm/ee.py b/llvm/ee.py index 7ea90d0..e87777a 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -232,7 +232,7 @@ def initialize_target(target, noraise=False): It is safe to initialize the same target multiple times. """ prefix = 'LLVMInitialize' - postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter'] + postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter', 'AsmParser'] try: for postfix in postfixes: getattr(api, '%s%s%s' % (prefix, target, postfix))() diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index cd1f59c..49ac261 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -30,6 +30,7 @@ #include #include +#include // to make MCJIT working #include "auto_pyobject.h" diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index 3208269..d6dfe43 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -101,3 +101,5 @@ class ExecutionEngine: unwrapped = list(map(capsule.unwrap, args)) return self._runFunction(fn, tuple(unwrapped)) + finalizeObject = Method(Void) + diff --git a/setup.py b/setup.py index 2c3a38f..546e77e 100644 --- a/setup.py +++ b/setup.py @@ -124,7 +124,7 @@ else: extra_components = list(extra_components & enabled_components) libs_core, objs_core = get_libs_and_objs( - ['core', 'analysis', 'scalaropts', 'executionengine', + ['core', 'analysis', 'scalaropts', 'executionengine', 'mcjit', 'jit', 'native', 'interpreter', 'bitreader', 'bitwriter', 'instrumentation', 'ipa', 'ipo', 'transformutils', 'asmparser', 'linker', 'support', 'vectorize'] From 625858aa6fc48975c5f0bf45ffd3aa44f3d3b067 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 16:05:24 -0500 Subject: [PATCH 024/149] fixes --- llvmpy/include/llvm_binding/extra.h | 7 ++++--- setup.py | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 49ac261..161c52e 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -70,7 +70,7 @@ namespace extra{ static PyObject* callwrite(PyObject* self, PyObject* arg) { - char meth[] = "method"; + char meth[] = "write"; char fmt[] = "O"; return PyObject_CallMethod(self, meth, fmt, arg); } @@ -965,7 +965,7 @@ PyObject* llvm_sys_getHostCPUFeatures(PyObject* Features) } } - +#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 3 static PyObject* llvm_sys_isLittleEndianHost() { @@ -982,4 +982,5 @@ PyObject* llvm_sys_isBigEndianHost() Py_RETURN_TRUE; else Py_RETURN_FALSE; -} \ No newline at end of file +} +#endif diff --git a/setup.py b/setup.py index 546e77e..e94a258 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,7 @@ def run_llvm_config(extra_args): return stdout.decode().strip() llvm_version = run_llvm_config(['--version']) + print('LLVM version = %r' % llvm_version) targets_built = run_llvm_config(['--targets-built']) @@ -62,7 +63,7 @@ def auto_intrinsic_gen(incdir): print("Generate intrinsic IDs") from tools import intrgen - if llvm_version >= (3, 3): + if llvm_version.startswith('3.3'): path = "%s/llvm/IR/Intrinsics.gen" % incdir else: path = "%s/llvm/Intrinsics.gen" % incdir From 56a511854a6fd7f6776c58630088498385e5af30 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 16:43:50 -0500 Subject: [PATCH 025/149] update "attribute(s)" ignorance --- llvm/core.py | 78 +++++++++++++++++++++++++++++++++++--------------- llvm/passes.py | 23 +++++++++++---- 2 files changed, 72 insertions(+), 29 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 9c8501e..d413bef 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -325,11 +325,17 @@ class VisibilityEnum(Enum): VisibilityEnum.declare() -# parameter attributes llvm::Attributes::AttrVal (see llvm/Attributes.h) +# parameter attributes +# LLVM 3.2 llvm::Attributes::AttrVal (see llvm/Attributes.h) +# LLVM 3.3 llvm::Attribute::AttrKind (see llvm/Attributes.h) class AttrEnum(Enum): prefix = 'ATTR_' - AttrVal = api.llvm.Attributes.AttrVal + if llvm.version >= (3, 3): + AttrVal = api.llvm.Attribute.AttrKind + else: + AttrVal = api.llvm.Attributes.AttrVal + ATTR_NONE = AttrVal.None_ ATTR_ZEXT = AttrVal.ZExt ATTR_SEXT = AttrVal.SExt @@ -1436,29 +1442,55 @@ class Argument(Value): _valid_attrs = frozenset([ATTR_BY_VAL, ATTR_NEST, ATTR_NO_ALIAS, ATTR_NO_CAPTURE, ATTR_STRUCT_RET]) - def add_attribute(self, attr): - context = api.llvm.getGlobalContext() - attrbldr = api.llvm.AttrBuilder.new() - attrbldr.addAttribute(attr) - attrs = api.llvm.Attributes.get(context, attrbldr) - self._ptr.addAttr(attrs) - if attr not in self: - raise ValueError("Attribute %s is not valid for arg %s" % - (attr, self)) + if llvm.version >= (3, 3): + def add_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.AttributeSet.get(context, 0, attrbldr) + self._ptr.addAttr(attrs) + + if attr not in self: + raise ValueError("Attribute %r is not valid for arg %s" % + (attr, self)) - def remove_attribute(self, attr): - context = api.llvm.getGlobalContext() - attrbldr = api.llvm.AttrBuilder.new() - attrbldr.addAttribute(attr) - attrs = api.llvm.Attributes.get(context, attrbldr) - self._ptr.removeAttr(attrs) + def remove_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.AttributeSet.get(context, 0, attrbldr) + self._ptr.removeAttr(attrs) - def _set_alignment(self, align): - context = api.llvm.getGlobalContext() - attrbldr = api.llvm.AttrBuilder.new() - attrbldr.addAlignmentAttr(align) - attrs = api.llvm.Attributes.get(context, attrbldr) - self._ptr.addAttr(attrs) + def _set_alignment(self, align): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.AttributeSet.get(context, 0, attrbldr) + self._ptr.addAttr(attrs) + else: + def add_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) + if attr not in self: + raise ValueError("Attribute %r is not valid for arg %s" % + (attr, self)) + + def remove_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeAttr(attrs) + + def _set_alignment(self, align): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) def _get_alignment(self): return self._ptr.getParamAlignment() diff --git a/llvm/passes.py b/llvm/passes.py index 068a7a3..b13fa84 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -70,13 +70,24 @@ class PassManagerBuilder(llvm.Wrapper): def size_level(self, sizelevel): self._ptr.SizeLevel = sizelevel - @property - def vectorize(self): - return self._ptr.Vectorize + if llvm.version >= (3, 3): + @property + def bbvectorize(self): + return self._ptr.BBVectorize - @vectorize.setter - def vectorize(self, enable): - self._ptr.Vectorize = enable + @bbvectorize.setter + def bbvectorize(self, enable): + self._ptr.BBVectorize = enable + + vectorize = bbvectorize + else: + @property + def vectorize(self): + return self._ptr.Vectorize + + @vectorize.setter + def vectorize(self, enable): + self._ptr.Vectorize = enable @property From 319984f0e0a69672dc6dd315062c88bdd67987cc Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 16:57:29 -0500 Subject: [PATCH 026/149] add MCJIT test --- llvm/core.py | 6 +++++- llvm/ee.py | 7 ++++++- llvm/test_llvmpy.py | 25 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index d413bef..99657d7 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2454,4 +2454,8 @@ if api.llvm.InitializeNativeTargetAsmPrinter(): # should this be an optional feature? # should user trigger the initialization? raise llvm.LLVMException("No native asm printer!?") - +if api.llvm.InitializeNativeTargetAsmParser(): + # required by MCJIT? + # should this be an optional feature? + # should user trigger the initialization? + raise llvm.LLVMException("No native asm parser!?") diff --git a/llvm/ee.py b/llvm/ee.py index e87777a..583201b 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -152,7 +152,9 @@ class EngineBuilder(llvm.Wrapper): engine = self._ptr.create(tm._ptr) else: engine = self._ptr.create() - return ExecutionEngine(engine) + ee = ExecutionEngine(engine) + ee.finalize_object() # no effect for legacy JIT + return ee def select_target(self, *args): '''get the corresponding target machine @@ -218,6 +220,9 @@ class ExecutionEngine(llvm.Wrapper): def remove_module(self, module): return self._ptr.removeModule(module._ptr) + def finalize_object(self): + return self._ptr.finalizeObject() + @property def target_data(self): ptr = self._ptr.getDataLayout() diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index e21a825..8d38ed0 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1353,6 +1353,31 @@ class TestCmp(TestCase): tests.append(TestCmp) +# --------------------------------------------------------------------------- + +class TestMCJIT(TestCase): + def test_mcjit(self): + m = Module.new('oidfjs') + fnty = Type.function(Type.int(), [Type.int(), Type.int()]) + func = m.add_function(fnty, 'foo') + bb = func.append_basic_block('') + bldr = Builder.new(bb) + bldr.ret(bldr.add(*func.args)) + + func.verify() + + engine = EngineBuilder.new(m).mcjit(True).create() + ptr = engine.get_pointer_to_function(func) + + from ctypes import c_int, CFUNCTYPE + callee = CFUNCTYPE(c_int, c_int, c_int)(ptr) + self.assertEqual(321 + 123, callee(321, 123)) + +if llvm.version >= (3, 3): + # MCJIT broken in 3.2 + # The test will segfault in OSX? + tests.append(TestMCJIT) + # --------------------------------------------------------------------------- def run(verbosity=1): From c0e9dedc9048e7849b767c193542ef507d21f8c0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 17:50:30 -0500 Subject: [PATCH 027/149] add binding to dynamiclibrary namespace for multimodule linking --- llvm/ee.py | 14 ++++++++++++++ llvm/test_llvmpy.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/llvm/ee.py b/llvm/ee.py index 583201b..fe21ea2 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -195,6 +195,9 @@ class ExecutionEngine(llvm.Wrapper): ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args))) return GenericValue(ptr) + def get_pointer_to_named_function(self, name, abort=True): + return self._ptr.getPointerToNamedFunction(name, abort) + def get_pointer_to_function(self, fn): return self._ptr.getPointerToFunction(fn._ptr) @@ -371,3 +374,14 @@ class TargetMachine(llvm.Wrapper): def feature_string(self): return self._ptr.getTargetFeatureString() + + +#===----------------------------------------------------------------------=== +# Dynamic Library +#===----------------------------------------------------------------------=== + +def dylib_add_symbol(name, ptr): + api.llvm.sys.DynamicLibrary.AddSymbol(name, ptr) + +def dylib_address_of_symbol(name): + return api.llvm.sys.DynamicLibrary.SearchForAddressOfSymbol(name) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 8d38ed0..19c402c 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1373,6 +1373,43 @@ class TestMCJIT(TestCase): callee = CFUNCTYPE(c_int, c_int, c_int)(ptr) self.assertEqual(321 + 123, callee(321, 123)) + def test_multi_module_linking(self): + # generate external library module + m = Module.new('external-library-module') + fnty = Type.function(Type.int(), [Type.int(), Type.int()]) + libfname = 'myadd' + func = m.add_function(fnty, libfname) + bb = func.append_basic_block('') + bldr = Builder.new(bb) + bldr.ret(bldr.add(*func.args)) + func.verify() + + # JIT the lib module and bind dynamic symbol + libengine = EngineBuilder.new(m).mcjit(True).create() + myadd_ptr = libengine.get_pointer_to_function(func) + le.dylib_add_symbol(libfname, myadd_ptr) + + # reference external library + m = Module.new('user') + fnty = Type.function(Type.int(), [Type.int(), Type.int()]) + func = m.add_function(fnty, 'foo') + bb = func.append_basic_block('') + bldr = Builder.new(bb) + extadd = m.get_or_insert_function(fnty, name=libfname) + bldr.ret(bldr.call(extadd, func.args)) + func.verify() + + # JIT the user module + engine = EngineBuilder.new(m).mcjit(True).create() + ptr = engine.get_pointer_to_function(func) + self.assertEqual(myadd_ptr, + engine.get_pointer_to_named_function(libfname)) + + from ctypes import c_int, CFUNCTYPE + callee = CFUNCTYPE(c_int, c_int, c_int)(ptr) + self.assertEqual(321 + 123, callee(321, 123)) + + if llvm.version >= (3, 3): # MCJIT broken in 3.2 # The test will segfault in OSX? From c4db61c7f53b513645761dadfdc19a105aa410e0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 1 Aug 2013 13:02:45 -0500 Subject: [PATCH 028/149] add test for basic arith operators and problems for div and mod on 32bit platforms --- llvm/test_llvmpy.py | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 19c402c..e51c406 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1415,6 +1415,68 @@ if llvm.version >= (3, 3): # The test will segfault in OSX? tests.append(TestMCJIT) + +class TestArith(TestCase): + ''' + Test basic arithmetic support with LLVM old-JIT + ''' + def func_template(self, ty, op): + m = Module.new('dofjaa') + fnty = Type.function(ty, [ty, ty]) + fn = m.add_function(fnty, 'foo') + bldr = Builder.new(fn.append_basic_block('')) + bldr.ret(getattr(bldr, op)(*fn.args)) + + engine = EngineBuilder.new(m).mcjit(True).create() + ptr = engine.get_pointer_to_function(fn) + + from ctypes import c_uint32, c_uint64, c_float, c_double, CFUNCTYPE + + maptypes = { + Type.int(32): c_uint32, + Type.int(64): c_uint64, + Type.float(): c_float, + Type.double(): c_double, + } + cty = maptypes[ty] + prototype = CFUNCTYPE(*[cty] * 3) + callee = prototype(ptr) + callee(12, 23) + + def template(self, iop, fop): + inttys = [Type.int(32), Type.int(64)] + flttys = [Type.float(), Type.double()] + + for ty in inttys: + self.func_template(ty, iop) + for ty in flttys: + self.func_template(ty, fop) + + def test_add(self): + self.template('add', 'fadd') + + def test_sub(self): + self.template('sub', 'fsub') + + def test_mul(self): + self.template('mul', 'fmul') + + def test_div(self): + if BITS == 32: + print('skipped test for div') + print('known failure due to unresolved external symbol __udivdi3') + return + self.template('udiv', 'fdiv') + + def test_rem(self): + if BITS == 32: + print('skipped test for rem') + print('known failure due to unresolved external symbol __umoddi3') + return + self.template('urem', 'frem') + +tests.append(TestArith) + # --------------------------------------------------------------------------- def run(verbosity=1): From 2a25b1c2b3819bb11fe330dfd64674c06d5db00d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 1 Aug 2013 11:50:36 -0500 Subject: [PATCH 029/149] fix avx detection for py3 --- llvm/workaround/avx_support.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/workaround/avx_support.py b/llvm/workaround/avx_support.py index 81cb936..0b1c2da 100644 --- a/llvm/workaround/avx_support.py +++ b/llvm/workaround/avx_support.py @@ -50,8 +50,7 @@ def detect_osx_like(): stdout=subprocess.PIPE) except OSError: return False - - features = info.stdout.read() + features = info.stdout.read().decode('UTF8') features = features.split() return 'AVX1.0' in features and 'OSXSAVE' in features and 'XSAVE' in features From 0421ad8456fe86facbd6d975cf47ea05845f2671 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 2 Aug 2013 12:12:35 -0500 Subject: [PATCH 030/149] add dev docs --- llvmpy/README | 5 -- llvmpy/README.md | 151 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 5 deletions(-) delete mode 100644 llvmpy/README create mode 100644 llvmpy/README.md diff --git a/llvmpy/README b/llvmpy/README deleted file mode 100644 index 2bfabcd..0000000 --- a/llvmpy/README +++ /dev/null @@ -1,5 +0,0 @@ -# README - -This is a reimplementation of the LLVM binding, aiming to provide a more familiar interface to the C++ API whenever possible. - -The implementation uses a custom DSL in python to describe the interface (under binding directory). The DSL serves as input to *gen.py* for generation of the .cpp and .py files for the actual binding. diff --git a/llvmpy/README.md b/llvmpy/README.md new file mode 100644 index 0000000..4e444f8 --- /dev/null +++ b/llvmpy/README.md @@ -0,0 +1,151 @@ +# README + +This is a reimplementation of the LLVM binding, aiming to provide a more +familiar interface to the C++ API whenever possible. + +The implementation uses a custom DSL in python to describe the interface. +The DSL serves as input to *gen/gen.py* for generation of the .cpp and .py files +for the actual binding. + +# How to Add New Class + +Let's use the `llvm::Module` as an example because it should be one of the most +familiar class in LLVM. + +Reference code in https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Module.py +and see LLVM documentation at http://llvm.org/docs/doxygen/html/classllvm_1_1Module.html + +1) Import binding helpers + +```python +from binding import * +# Yes, it is bad practice to import star. +# I will fix it one day. +``` + +2) Import LLVM namespace + +```python +from .namespace import llvm +``` + +3) Declare the class + +```python +Module = llvm.Class() +``` + +4) Import all the dependencies for the definition + +5) Define the class + +```python +@Module +class Module: + ... +``` + +## Inside the definition... + +5.1) Use the ``_include_`` attribute to add include files. + +5.2) Use ``Enum`` to create an enumerator type. + +5.3) Make constructor + +Not every class needs to have a binding for the constructor. +Only add things that will be used. + +```python +new = Constructor(cast(str, StringRef), ref(LLVMContext)) +``` + +The constructor must be named as "new". + +The args to ``Constructor`` are parameters of the signature. +The first parameter means cast Python string to a StringRef. +The second parameter means pass LLVMContext object as a value reference. + +5.4) Make destructor + +Not every class needs to have a binding for the destructor. +Only add things that will be used. +If it is always owned by another object, it usually does not need to have one. + +```python +delete = Destructor() +``` + +The destructor must be named as "delete". + +5.5) Add Simple Methods + +```python +getFunction = Method(ptr(Function), cast(str, StringRef)) +``` + +The first arg is the return type: a ponter to Function. +The rest of the args are for the parameters. + +Note: ``cast(fromtype, totype)`` can be used as return-type as well. +In that case, the ``fromtype`` will usually refer to a LLVM object +and the ``totype`` will refer to the Python object. + +5.6) Add custom methods defined in C++ + +The ``list_functions`` is created as a ``CustomMethod``. + +```python +list_functions = CustomMethod('Module_list_functions', PyObjectPtr) +``` + +The first arg is the name that appears in C++. +The second argument is the return-type. +The rest of the arguments are parameters. + +The definition of ``Module_list_functions`` is located in +"include/llvm_binding/extra.h". + +5.7) Add custom python method + +One can also add custom methods in Python, e.g. ``__str__``. + +```python +@CustomPythonMethod +def __str__(self): + from llvmpy import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os, None) + return os.str() +``` + +The body of ``__str__`` is directly copied to the Python output file. +Thus, it can't reference to anything in current file scope. + +# Static Methods + +``StaticMethod`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/PassRegistry.py + +``CustomStaticMethod`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Support/TargetRegistry.py + + +# Namespace + +``Namespace`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Support/CodeGen.py + +# Functions + +``Function`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Assembly/Parser.py + +``CustomFunction`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Bitcode/ReaderWriter.py + + + + + +# Other Things from the binding.py + +https://github.com/llvmpy/llvmpy/blob/master/llvmpy/gen/binding.py + +The list of C++ types: https://github.com/llvmpy/llvmpy/blob/master/llvmpy/gen/binding.py#L218 + From 84a95945ea7ec06ff361fc3aa62ca623bb00f516 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Tue, 6 Aug 2013 14:17:14 -0500 Subject: [PATCH 031/149] update marker header file --- llvm-config-win32.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index e191290..8c268cb 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -108,7 +108,7 @@ def main(): elif option == '--includedir': incdir = join(find_llvm_prefix(), 'include') - ensure_file(join(incdir, 'llvm' , 'BasicBlock.h')) + ensure_file(join(incdir, 'llvm' , 'Linker.h')) print(incdir) elif option == '--libdir': From c20c4d776f9b44475cae61b7da8922895dd09817 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 14:42:49 -0500 Subject: [PATCH 032/149] fix exception handling for TargetMachine --- llvm/ee.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/ee.py b/llvm/ee.py index fe21ea2..832f422 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -282,7 +282,7 @@ class TargetMachine(llvm.Wrapper): with contextlib.closing(BytesIO()) as error: target = api.llvm.TargetRegistry.lookupTarget(triple, error) if not target: - raise llvm.LLVMException(error) + raise llvm.LLVMException(error.getvalue()) if not target.hasTargetMachine(): raise llvm.LLVMException(target, "No target machine.") target_options = api.llvm.TargetOptions.new() From b4d943a6717ff2431c4df6578d6afccbed3f9f62 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 14:43:23 -0500 Subject: [PATCH 033/149] add autoselect ELF generation for MCJIT --- llvm/ee.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/llvm/ee.py b/llvm/ee.py index 832f422..4090a0f 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -30,6 +30,7 @@ "Execution Engine and related classes." +import sys from io import BytesIO import contextlib @@ -150,6 +151,12 @@ class EngineBuilder(llvm.Wrapper): ''' if tm is not None: engine = self._ptr.create(tm._ptr) + elif (sys.prefix.startswith('win32') and + getattr(self, '_use_mcjit', False)): + # force ELF generation on MCJIT on win32 + triple = get_default_triple() + tm = TargetMachine.new('%s-elf' % triple) + engine = self._ptr.create(tm) else: engine = self._ptr.create() ee = ExecutionEngine(engine) @@ -173,6 +180,7 @@ class EngineBuilder(llvm.Wrapper): '''Enable/disable MCJIT ''' self._ptr.setUseMCJIT(enable) + self._use_mcjit = True return self #===----------------------------------------------------------------------=== From eb4fc653f2ca3e8d9c4f31817b791070a75886d3 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 14:52:16 -0500 Subject: [PATCH 034/149] ensure MCJIT ELF autoselect works --- llvm/ee.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/ee.py b/llvm/ee.py index 4090a0f..b91c4cb 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -151,12 +151,12 @@ class EngineBuilder(llvm.Wrapper): ''' if tm is not None: engine = self._ptr.create(tm._ptr) - elif (sys.prefix.startswith('win32') and + elif (sys.platform.startswith('win32') and getattr(self, '_use_mcjit', False)): # force ELF generation on MCJIT on win32 triple = get_default_triple() tm = TargetMachine.new('%s-elf' % triple) - engine = self._ptr.create(tm) + engine = self._ptr.create(tm._ptr) else: engine = self._ptr.create() ee = ExecutionEngine(engine) From 1e9d37a64e489efdd9c06a2b365e7b6063336652 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 15:59:17 -0500 Subject: [PATCH 035/149] add no-signed-wrap and no-unsigned-wrap flags to IRBuilder --- llvm/core.py | 20 ++++++++++++-------- llvm/test_llvmpy.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 99657d7..0fbd5ab 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2124,20 +2124,23 @@ class Builder(llvm.Wrapper): # arithmethic, bitwise and logical - def add(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name)) + def add(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def fadd(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name)) - def sub(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name)) + def sub(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def fsub(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name)) - def mul(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name)) + def mul(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def fmul(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) @@ -2160,8 +2163,9 @@ class Builder(llvm.Wrapper): def frem(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name)) - def shl(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name)) + def shl(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def lshr(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index e51c406..9c3e695 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1477,6 +1477,40 @@ class TestArith(TestCase): tests.append(TestArith) +class TestNUWNSW(TestCase): + def make_module(self): + mod = Module.new('asdfa') + fnty = Type.function(Type.void(), [Type.int()] * 2) + func = mod.add_function(fnty, 'foo') + bldr = Builder.new(func.append_basic_block('')) + return mod, func, bldr + + def has_nsw(self, inst, op): + self.assertTrue(('%s nsw' % op) in str(inst), "NSW flag does not work") + + def has_nuw(self, inst, op): + self.assertTrue(('%s nuw' % op) in str(inst), "NUW flag does not work") + + def _test_template(self, opf, opname): + mod, func, bldr = self.make_module() + a, b = func.args + self.has_nsw(opf(bldr, a, b, nsw=True), opname) + self.has_nuw(opf(bldr, a, b, nuw=True), opname) + + def test_add_nuw_nsw(self): + self._test_template(Builder.add, 'add') + + def test_sub_nuw_nsw(self): + self._test_template(Builder.sub, 'sub') + + def test_mul_nuw_nsw(self): + self._test_template(Builder.mul, 'mul') + + def test_shl_nuw_nsw(self): + self._test_template(Builder.shl, 'shl') + +tests.append(TestNUWNSW) + # --------------------------------------------------------------------------- def run(verbosity=1): From cfe5e9ea92f617b5a3e02b70aff5f26963f03393 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 16:11:24 -0500 Subject: [PATCH 036/149] add exact flag to IRBuilder --- llvm/core.py | 20 ++++++++++++-------- llvm/test_llvmpy.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 0fbd5ab..7535b0f 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2145,11 +2145,13 @@ class Builder(llvm.Wrapper): def fmul(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) - def udiv(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name)) + def udiv(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name, + exact)) - def sdiv(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name)) + def sdiv(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name, + exact)) def fdiv(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) @@ -2167,11 +2169,13 @@ class Builder(llvm.Wrapper): return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name, nuw, nsw)) - def lshr(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) + def lshr(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name, + exact)) - def ashr(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name)) + def ashr(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name, + exact)) def and_(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 9c3e695..250e404 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1511,6 +1511,37 @@ class TestNUWNSW(TestCase): tests.append(TestNUWNSW) + +class TestExact(TestCase): + def make_module(self): + mod = Module.new('asdfa') + fnty = Type.function(Type.void(), [Type.int()] * 2) + func = mod.add_function(fnty, 'foo') + bldr = Builder.new(func.append_basic_block('')) + return mod, func, bldr + + def has_exact(self, inst, op): + self.assertTrue(('%s exact' % op) in str(inst), "exact flag does not work") + + def _test_template(self, opf, opname): + mod, func, bldr = self.make_module() + a, b = func.args + self.has_exact(opf(bldr, a, b, exact=True), opname) + + def test_udiv_exact(self): + self._test_template(Builder.udiv, 'udiv') + + def test_sdiv_exact(self): + self._test_template(Builder.sdiv, 'sdiv') + + def test_lshr_exact(self): + self._test_template(Builder.lshr, 'lshr') + + def test_ashr_exact(self): + self._test_template(Builder.ashr, 'ashr') + +tests.append(TestExact) + # --------------------------------------------------------------------------- def run(verbosity=1): From 1ed3c773103a09d126a645c6af9f4bb5809a4d99 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 16:16:38 -0500 Subject: [PATCH 037/149] add neg nuw nsw --- llvm/core.py | 4 ++-- llvm/test_llvmpy.py | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 7535b0f..945dd86 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2186,8 +2186,8 @@ class Builder(llvm.Wrapper): def xor(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) - def neg(self, val, name=""): - return _make_value(self._ptr.CreateNeg(val._ptr, name)) + def neg(self, val, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateNeg(val._ptr, name, nuw, nsw)) def not_(self, val, name=""): return _make_value(self._ptr.CreateNot(val._ptr, name)) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 250e404..2a5c1f5 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1509,6 +1509,13 @@ class TestNUWNSW(TestCase): def test_shl_nuw_nsw(self): self._test_template(Builder.shl, 'shl') + def test_neg_nuw_nsw(self): + mod, func, bldr = self.make_module() + a, b = func.args + self.has_nsw(bldr.neg(a, nsw=True), 'sub') + self.has_nuw(bldr.neg(a, nuw=True), 'sub') + + tests.append(TestNUWNSW) From d060c10096ea97d091a8cced5610a5bc887971a9 Mon Sep 17 00:00:00 2001 From: majidaldo Date: Tue, 13 Aug 2013 14:42:54 -0500 Subject: [PATCH 038/149] add conda build script --- buildscripts/condarecipe/bld.bat | 6 ++++++ buildscripts/condarecipe/build.sh | 13 +++++++++++++ buildscripts/condarecipe/meta.yaml | 27 +++++++++++++++++++++++++++ buildscripts/condarecipe/run_test.py | 19 +++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 buildscripts/condarecipe/bld.bat create mode 100644 buildscripts/condarecipe/build.sh create mode 100644 buildscripts/condarecipe/meta.yaml create mode 100644 buildscripts/condarecipe/run_test.py diff --git a/buildscripts/condarecipe/bld.bat b/buildscripts/condarecipe/bld.bat new file mode 100644 index 0000000..45ef910 --- /dev/null +++ b/buildscripts/condarecipe/bld.bat @@ -0,0 +1,6 @@ +set LLVMPY_DYNLINK=0 +set INCLUDE=%LIBRARY_INC% +set LIBPATH=%LIBRARY_LIB% +set LIB=%LIBRARY_LIB% +python setup.py install +if errorlevel 1 exit 1 diff --git a/buildscripts/condarecipe/build.sh b/buildscripts/condarecipe/build.sh new file mode 100644 index 0000000..5c98fde --- /dev/null +++ b/buildscripts/condarecipe/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if [[ (`uname` == Linux) && (`uname -m` != armv6l) ]] +then + export CC=gcc + #gcc44 + export CXX=g++ + #g++44 +fi + +export LLVMPY_DYNLINK=$DISTRO_BUILD + +$PYTHON setup.py install diff --git a/buildscripts/condarecipe/meta.yaml b/buildscripts/condarecipe/meta.yaml new file mode 100644 index 0000000..05007f3 --- /dev/null +++ b/buildscripts/condarecipe/meta.yaml @@ -0,0 +1,27 @@ +package: + name: llvmpy + version: master + +source: + git_url: git@github.com:llvmpy/llvmpy.git +# git_tag: 0.12.0 + +requirements: + build: + - llvm + - python + run: + - llvm [unix] + - python + +test: + imports: + - llvm + - llvmpy + - llvmpy._api + - llvmpy._capsule + - llpython + - llvm_array + - llvm_cbuilder + + diff --git a/buildscripts/condarecipe/run_test.py b/buildscripts/condarecipe/run_test.py new file mode 100644 index 0000000..281a599 --- /dev/null +++ b/buildscripts/condarecipe/run_test.py @@ -0,0 +1,19 @@ +import sys +import platform +import llvm + +from llvm.core import Module +from llvm.ee import EngineBuilder +m = Module.new('fjoidajfa') +eb = EngineBuilder.new(m) +target = eb.select_target() + +print('target.triple=%r' % target.triple) +if sys.platform == 'darwin': + s = {'64bit': 'x86_64', '32bit': 'x86'}[platform.architecture()[0]] + assert target.triple.startswith(s + '-apple-darwin') + +assert llvm.test(verbosity=2) == 0 + +print('llvm.__version__: %s' % llvm.__version__) +#assert llvm.__version__ == '0.12.0' From bf0253c9f9d96bb922f4c88ecffc85d01f0ecbb1 Mon Sep 17 00:00:00 2001 From: majidaldo Date: Tue, 13 Aug 2013 14:55:13 -0500 Subject: [PATCH 039/149] add chrpath --- buildscripts/condarecipe/meta.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/buildscripts/condarecipe/meta.yaml b/buildscripts/condarecipe/meta.yaml index 05007f3..15d9f8a 100644 --- a/buildscripts/condarecipe/meta.yaml +++ b/buildscripts/condarecipe/meta.yaml @@ -10,6 +10,7 @@ requirements: build: - llvm - python + - chrpath run: - llvm [unix] - python From 3a289ccace2efe5d3f898f59441768c5865445ff Mon Sep 17 00:00:00 2001 From: majidaldo Date: Tue, 13 Aug 2013 14:55:42 -0500 Subject: [PATCH 040/149] add percent python --- buildscripts/condarecipe/bld.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildscripts/condarecipe/bld.bat b/buildscripts/condarecipe/bld.bat index 45ef910..e9177c5 100644 --- a/buildscripts/condarecipe/bld.bat +++ b/buildscripts/condarecipe/bld.bat @@ -2,5 +2,5 @@ set LLVMPY_DYNLINK=0 set INCLUDE=%LIBRARY_INC% set LIBPATH=%LIBRARY_LIB% set LIB=%LIBRARY_LIB% -python setup.py install +%PYTHON% setup.py install if errorlevel 1 exit 1 From 1be8b07cedfff7a73aaad59e4b076a75dde8f03d Mon Sep 17 00:00:00 2001 From: majidaldo Date: Tue, 13 Aug 2013 14:59:33 -0500 Subject: [PATCH 041/149] charpath just for linux --- buildscripts/condarecipe/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildscripts/condarecipe/meta.yaml b/buildscripts/condarecipe/meta.yaml index 15d9f8a..b079986 100644 --- a/buildscripts/condarecipe/meta.yaml +++ b/buildscripts/condarecipe/meta.yaml @@ -10,7 +10,7 @@ requirements: build: - llvm - python - - chrpath + - chrpath [linux] run: - llvm [unix] - python From d10b182479b58a25bb45a6bd5c8d1a6aa8ee468c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 13 Aug 2013 15:27:49 -0500 Subject: [PATCH 042/149] dislabe MCJIT tests for LLVM3.2 --- llvm/test_llvmpy.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 2a5c1f5..f8d6adb 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1418,7 +1418,7 @@ if llvm.version >= (3, 3): class TestArith(TestCase): ''' - Test basic arithmetic support with LLVM old-JIT + Test basic arithmetic support with LLVM MCJIT ''' def func_template(self, ty, op): m = Module.new('dofjaa') @@ -1475,7 +1475,9 @@ class TestArith(TestCase): return self.template('urem', 'frem') -tests.append(TestArith) +if llvm.version >= (3, 3): + # MCJIT is broken in 3.2 + tests.append(TestArith) class TestNUWNSW(TestCase): def make_module(self): From 07c64779d8e3a86d0ac64139bf0bafd26b629e1e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 13 Aug 2013 18:38:41 -0500 Subject: [PATCH 043/149] begin low-level runtime implementation --- llrtc/Makefile | 21 ++++++++++ llrtc/README.md | 25 +++++++++++ llrtc/common.mk | 26 ++++++++++++ llrtc/lib/Makefile | 44 +++++++++++++++++++ llrtc/lib/test_udivmod64.c | 22 ++++++++++ llrtc/lib/test_udivmod64.py | 53 +++++++++++++++++++++++ llrtc/lib/udivmod64.c | 84 +++++++++++++++++++++++++++++++++++++ llrtc/lib/udivmod64.h | 11 +++++ llrtc/tools/striptriple.py | 15 +++++++ 9 files changed, 301 insertions(+) create mode 100644 llrtc/Makefile create mode 100644 llrtc/README.md create mode 100644 llrtc/common.mk create mode 100644 llrtc/lib/Makefile create mode 100644 llrtc/lib/test_udivmod64.c create mode 100644 llrtc/lib/test_udivmod64.py create mode 100644 llrtc/lib/udivmod64.c create mode 100644 llrtc/lib/udivmod64.h create mode 100644 llrtc/tools/striptriple.py diff --git a/llrtc/Makefile b/llrtc/Makefile new file mode 100644 index 0000000..c271d0e --- /dev/null +++ b/llrtc/Makefile @@ -0,0 +1,21 @@ +DIRECTORIES = divmod + +all: + for mydir in $(DIRECTORIES); do \ + make -C $$mydir; \ + done + +test: + for mydir in $(DIRECTORIES); do \ + make -C $$mydir test; \ + done + +clean-test: + for mydir in $(DIRECTORIES); do \ + make -C $$mydir clean-test; \ + done + +clean: + for mydir in $(DIRECTORIES); do \ + make -C $$mydir clean; \ + done \ No newline at end of file diff --git a/llrtc/README.md b/llrtc/README.md new file mode 100644 index 0000000..539d9c3 --- /dev/null +++ b/llrtc/README.md @@ -0,0 +1,25 @@ +# LLRT: Low Level Runtime + +## Why? + +The same reason for LLVM compiler-rt. LLVM generates libgcc symbols, such as +__divdi3 for 64-bit division on 32-bit platform. They are not also available. +We need to ship compiler-rt but it is not Windows ready. +This subproject aims to provide a small portable subset of compiler-rt. +Start small and add only the things we really needed. +Performance is not crucial but should not be terrible. +Functionality and usefullness should be more important than performance. + +## Developer Instructions + +LLRT implements some functionalities in compiler-rt in ANSI C. +The C files are compiled using clang to produce LLVM IR which are shipped. +The IR files are committed in the repository. +So, remember to build the IR files commit them after modifying the C files. + +## Build Requirement + +- Make +- Clang +- Python + diff --git a/llrtc/common.mk b/llrtc/common.mk new file mode 100644 index 0000000..3de9c12 --- /dev/null +++ b/llrtc/common.mk @@ -0,0 +1,26 @@ +CLANG = clang +CF = -Wall -ansi +OUTDIR = .. + +all: ir + +$(OUTPUT).c: $(OUTPUT).h + +$(OUTPUT): test.c $(OUTPUT).c + $(CLANG) $(CF) -ftrapv -o $@ $+ + +test: $(OUTPUT) + python test.py + +ir: + CLANG -m32 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86/$(OUTPUT).ll + CLANG -m64 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86_64/$(OUTPUT).ll + python ../tools/striptriple.py $(OUTDIR)/x86/$(OUTPUT).ll + python ../tools/striptriple.py $(OUTDIR)/x86_64/$(OUTPUT).ll + +clean-test: + rm -f $(OUTPUT) + +clean: clean-test + rm -f $(OUTDIR)/x86/$(OUTPUT).ll + rm -f $(OUTDIR)/x86_64/$(OUTPUT).ll diff --git a/llrtc/lib/Makefile b/llrtc/lib/Makefile new file mode 100644 index 0000000..1bb325f --- /dev/null +++ b/llrtc/lib/Makefile @@ -0,0 +1,44 @@ +OUTPUT = llrt +SOURCES = udivmod64.c + +CLANG = clang +CF = -Wall -ansi +CF_TEST = $(CF) -ftrapv +CF_BUILD = $(CF) -O0 -emit-llvm +OUTDIR = .. + +all: ir + +ir: $(SOURCES) + $(CLANG) -m32 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86.ll -c $(SOURCES) + python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86.ll + $(CLANG) -m64 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86_64.ll -c $(SOURCES) + python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86_64.ll + +lib$(OUTPUT).a: $(SOURCES) + $(CLANG) $(CF) -o $@ -c $+ + +build-test: lib$(OUTPUT).a + for src in $(SOURCES); do \ + $(CLANG) $(CF_TEST) -o test_$${src%.*} test_$$src -L. -lllrt; \ + done; + +test: build-test + for src in $(SOURCES); do \ + echo "testing $${src%.*}"; \ + python test_$${src%.*}.py > test_$${src%.*}.out; \ + done; + +clean-test: + rm -f *.out + rm -f *.a + for src in $(SOURCES); do \ + rm -f test_$${src%.*} ;\ + done; + +clean-dist: + rm $(OUTDIR)/*.ll + +clean: clean-test clean-dist + +udivmod64.c: udivmod64.h diff --git a/llrtc/lib/test_udivmod64.c b/llrtc/lib/test_udivmod64.c new file mode 100644 index 0000000..e2935c5 --- /dev/null +++ b/llrtc/lib/test_udivmod64.c @@ -0,0 +1,22 @@ +#include +#include + +extern uint64_t +udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); + +int main(int argc, char * argv[]){ + uint64_t n, d, q, r; + if (argc != 3) { + printf("invalid argument: %s dividend divisor", argv[0]); + return 1; + } + sscanf(argv[1], "%llu", &n); + sscanf(argv[2], "%llu", &d); + + q = udivmod64(n, d, &r); + + printf("%llu\n", q); + printf("%llu\n", r); + + return 0; +} \ No newline at end of file diff --git a/llrtc/lib/test_udivmod64.py b/llrtc/lib/test_udivmod64.py new file mode 100644 index 0000000..487a458 --- /dev/null +++ b/llrtc/lib/test_udivmod64.py @@ -0,0 +1,53 @@ +import math +import os +import subprocess +udt = os.path.join('.', 'test_udivmod64') + +def testcase(dividend, divisor): + print 'divmod64(%d, %d)' % (dividend, divisor) + + procargs = ('%s %s %s' % (udt, dividend, divisor)).split() + result = subprocess.check_output(procargs) + gotQ, gotR = map(int, result.splitlines()) + + expectQ = dividend // divisor + expectR = dividend % divisor + + print 'Q = %d, R = %d' % (gotQ, gotR) + + if expectQ != gotQ: + raise ValueError("invalid quotient: got=%d but expect=%d" % + (gotQ, expectQ)) + if expectR != gotR: + raise ValueError("invalid remainder: got=%d but expect=%d" % + (gotR, expectR)) + print 'OK' + +def testsequence(): + subjects = [ + (0, 1), + (0, 0xffffffffffffffff), + (1, 2), + (1, 983219), + (2, 2), + (3, 2), + (1024, 2), + (2048, 512), + (21321, 512), + (9329189, 1031), + (0xffffffff, 2), + (0xffffffff, 0xffff), + (0x1ffffffff, 2), + (0x1ffffffff, 0xffff), + (0xffff, 0xffffffff), + (0xffffffffffffffff, 0xffff), + (0xffffffffffffffff, 0x7fffffffffffffff), + (0xffffffffffffffff, 0xfffffffffffffff0), + (0xffffffffffffffff, 87655678587161901), + ] + + for dvd, dvr in subjects: + testcase(dvd, dvr) + +if __name__ == '__main__': + testsequence() diff --git a/llrtc/lib/udivmod64.c b/llrtc/lib/udivmod64.c new file mode 100644 index 0000000..a028aea --- /dev/null +++ b/llrtc/lib/udivmod64.c @@ -0,0 +1,84 @@ +/* +Implements unsigned divmod using for platform missing 64-bit division and/or +modulo functions. +*/ +#include "udivmod64.h" + +/* +count left zero for 64-bit words + +*/ +static +int clz64(uint64_t x) +{ + const int total_bits = sizeof(x) * BITS_PER_BYTE; + int zc = 0; + + while (zc < total_bits && ((x >> (total_bits - zc - 1)) & 1) == 0) { + ++zc; + } + return zc; +} + +typedef struct div_state_ +{ + uint64_t tmp, dvd; +} div_state; + +/* +Left shift div_state by 1 bit +*/ +static +void div_state_lshift(div_state *state) +{ + state->tmp = (state->tmp << 1) | (state->dvd >> 63); + state->dvd = state->dvd << 1; +} + +/* +Division of unsigned 64-bit word using 64-bit addition and subtration following +the shift-restore division algorithm. +For those interested in 32-bit implementation, +mapping of 64-bit addition and subtraction to 32-bit should be trivial. + +Reference: + - IBM. The PowerPC Compiler Writer's Guide + - LLVM compiler-rt + +Assumptions: + - all operands and results are positive + - unsigned wrapped around +*/ +uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder) +{ + div_state state = {0, dividend}; + uint64_t quotient = 0; + int i; + int skipahead; + + if (divisor == 0) { + return 1 / 0; /* intentionally div by zero */ + } + + /* + skipahead to reduce iteration + */ + skipahead = clz64(dividend); + + for (i = 0; i < skipahead; ++i) { + div_state_lshift(&state); + } + + /* + division loop + */ + for (i = skipahead; i < 64; ++i) { + div_state_lshift(&state); + if (state.tmp >= divisor) { + state.tmp = state.tmp - divisor; + quotient |= 1ull << (63 - i); + } + } + *remainder = state.tmp; + return quotient; +} diff --git a/llrtc/lib/udivmod64.h b/llrtc/lib/udivmod64.h new file mode 100644 index 0000000..9cbcd8c --- /dev/null +++ b/llrtc/lib/udivmod64.h @@ -0,0 +1,11 @@ +#ifndef LLRT_UDIVMOD_H_ +#define LLRT_UDIVMOD_H_ + +#include + +#define BITS_PER_BYTE 8 + +uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); + +#endif /* LLRT_UDIVMOD_H_ */ + diff --git a/llrtc/tools/striptriple.py b/llrtc/tools/striptriple.py new file mode 100644 index 0000000..a20ba34 --- /dev/null +++ b/llrtc/tools/striptriple.py @@ -0,0 +1,15 @@ +import sys +import re + +buf = [] +with open(sys.argv[1], 'r') as fin: + tripleline = re.compile('^target\s+triple\s+=\s+') + for line in fin.readlines(): + if not tripleline.match(line): + buf.append(line) + +with open(sys.argv[1], 'w') as fout: + for line in buf: + fout.write(line) + + From 7d1c4c18a0539f61d1aba1e55fdea537a8300ec5 Mon Sep 17 00:00:00 2001 From: majidaldo Date: Wed, 14 Aug 2013 14:39:10 -0500 Subject: [PATCH 044/149] high version number --- buildscripts/condarecipe/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildscripts/condarecipe/meta.yaml b/buildscripts/condarecipe/meta.yaml index b079986..2b05015 100644 --- a/buildscripts/condarecipe/meta.yaml +++ b/buildscripts/condarecipe/meta.yaml @@ -1,6 +1,6 @@ package: name: llvmpy - version: master + version: 99.9.9 source: git_url: git@github.com:llvmpy/llvmpy.git From 8480d55faf0e671326b37576a05d0e1fbd7cb79b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 14 Aug 2013 15:29:13 -0500 Subject: [PATCH 045/149] add sdivmod; improve build system; --- llrtc/Makefile | 29 ++++++------- llrtc/common.mk | 26 ------------ llrtc/lib/.gitignore | 4 ++ llrtc/lib/Makefile | 68 ++++++++++++++++++++----------- llrtc/lib/{udivmod64.h => llrt.h} | 7 ++-- llrtc/lib/sdivmod64.c | 40 ++++++++++++++++++ llrtc/lib/test_sdivmod64.c | 21 ++++++++++ llrtc/lib/test_sdivmod64.py | 56 +++++++++++++++++++++++++ llrtc/lib/test_udivmod64.c | 6 +-- llrtc/lib/test_udivmod64.py | 2 +- llrtc/lib/udivmod64.c | 4 +- 11 files changed, 190 insertions(+), 73 deletions(-) delete mode 100644 llrtc/common.mk create mode 100644 llrtc/lib/.gitignore rename llrtc/lib/{udivmod64.h => llrt.h} (50%) create mode 100644 llrtc/lib/sdivmod64.c create mode 100644 llrtc/lib/test_sdivmod64.c create mode 100644 llrtc/lib/test_sdivmod64.py diff --git a/llrtc/Makefile b/llrtc/Makefile index c271d0e..bde100e 100644 --- a/llrtc/Makefile +++ b/llrtc/Makefile @@ -1,21 +1,22 @@ -DIRECTORIES = divmod - all: - for mydir in $(DIRECTORIES); do \ - make -C $$mydir; \ - done + make -C lib + +ir: + make -C lib ir test: - for mydir in $(DIRECTORIES); do \ - make -C $$mydir test; \ - done + make -C lib test clean-test: - for mydir in $(DIRECTORIES); do \ - make -C $$mydir clean-test; \ - done + make -C lib clean-test + +clean-temp: + make -C lib clean-temp clean: - for mydir in $(DIRECTORIES); do \ - make -C $$mydir clean; \ - done \ No newline at end of file + make -C lib clean + +install: ir + make -C lib clean-test + make -C lib clean-temp + \ No newline at end of file diff --git a/llrtc/common.mk b/llrtc/common.mk deleted file mode 100644 index 3de9c12..0000000 --- a/llrtc/common.mk +++ /dev/null @@ -1,26 +0,0 @@ -CLANG = clang -CF = -Wall -ansi -OUTDIR = .. - -all: ir - -$(OUTPUT).c: $(OUTPUT).h - -$(OUTPUT): test.c $(OUTPUT).c - $(CLANG) $(CF) -ftrapv -o $@ $+ - -test: $(OUTPUT) - python test.py - -ir: - CLANG -m32 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86/$(OUTPUT).ll - CLANG -m64 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86_64/$(OUTPUT).ll - python ../tools/striptriple.py $(OUTDIR)/x86/$(OUTPUT).ll - python ../tools/striptriple.py $(OUTDIR)/x86_64/$(OUTPUT).ll - -clean-test: - rm -f $(OUTPUT) - -clean: clean-test - rm -f $(OUTDIR)/x86/$(OUTPUT).ll - rm -f $(OUTDIR)/x86_64/$(OUTPUT).ll diff --git a/llrtc/lib/.gitignore b/llrtc/lib/.gitignore new file mode 100644 index 0000000..fbcf76a --- /dev/null +++ b/llrtc/lib/.gitignore @@ -0,0 +1,4 @@ +*.o +*.run +*.out +*.ll diff --git a/llrtc/lib/Makefile b/llrtc/lib/Makefile index 1bb325f..8c9361d 100644 --- a/llrtc/lib/Makefile +++ b/llrtc/lib/Makefile @@ -1,44 +1,66 @@ OUTPUT = llrt -SOURCES = udivmod64.c +SOURCES = udivmod64.c sdivmod64.c +TESTS = test_udivmod64.c test_sdivmod64.c CLANG = clang +LLVM_LINK = llvm-link CF = -Wall -ansi CF_TEST = $(CF) -ftrapv CF_BUILD = $(CF) -O0 -emit-llvm OUTDIR = .. +STRIPPER = ../tools/striptriple.py all: ir -ir: $(SOURCES) - $(CLANG) -m32 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86.ll -c $(SOURCES) - python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86.ll - $(CLANG) -m64 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86_64.ll -c $(SOURCES) - python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86_64.ll +ir: $(OUTDIR)/$(OUTPUT)_x86.ll $(OUTDIR)/$(OUTPUT)_x86_64.ll -lib$(OUTPUT).a: $(SOURCES) - $(CLANG) $(CF) -o $@ -c $+ +$(OUTDIR)/$(OUTPUT)_x86.ll: $(SOURCES:.c=_x86.bc) + $(LLVM_LINK) -S $+ -o $@ + python $(STRIPPER) $@ -build-test: lib$(OUTPUT).a - for src in $(SOURCES); do \ - $(CLANG) $(CF_TEST) -o test_$${src%.*} test_$$src -L. -lllrt; \ - done; +$(OUTDIR)/$(OUTPUT)_x86_64.ll: $(SOURCES:.c=_x86_64.bc) + $(LLVM_LINK) -S $+ -o $@ + python $(STRIPPER) $@ -test: build-test - for src in $(SOURCES); do \ - echo "testing $${src%.*}"; \ - python test_$${src%.*}.py > test_$${src%.*}.out; \ +build-test: $(SOURCES:.c=.o) $(TESTS:.c=.run) + +lib$(OUTPUT).a: $(SOURCES:.c=.o) + $(CLANG) -static $+ -o $@ + +test: $(TESTS:.c=.run) + for src in $+; do \ + echo "testing $${src}"; \ + python $${src%.*}.py > $${src%.*}.out; \ done; clean-test: rm -f *.out - rm -f *.a - for src in $(SOURCES); do \ - rm -f test_$${src%.*} ;\ - done; + rm -f *.o + rm -f *.run -clean-dist: - rm $(OUTDIR)/*.ll +clean-dist: clean-temp + rm -f *.ll + +clean-temp: + rm -f *.bc + rm -f *.o + rm -f *.out clean: clean-test clean-dist -udivmod64.c: udivmod64.h +%.c: llrt.h + +%_x86.bc: %.c + $(CLANG) -m32 $(CF_BUILD) -c $< -o $@ + +%_x86_64.bc: %.c + $(CLANG) -m64 $(CF_BUILD) -c $< -o $@ + +%.o: %.c + $(CLANG) $(CF_TEST) -c $< + +%.run: %.c + $(CLANG) $(CF_TEST) -o $@ $+ + +test_udivmod64.run: udivmod64.o +test_sdivmod64.run: udivmod64.o sdivmod64.o diff --git a/llrtc/lib/udivmod64.h b/llrtc/lib/llrt.h similarity index 50% rename from llrtc/lib/udivmod64.h rename to llrtc/lib/llrt.h index 9cbcd8c..0d26309 100644 --- a/llrtc/lib/udivmod64.h +++ b/llrtc/lib/llrt.h @@ -1,11 +1,12 @@ -#ifndef LLRT_UDIVMOD_H_ -#define LLRT_UDIVMOD_H_ +#ifndef LLRT_H_ +#define LLRT_H_ #include #define BITS_PER_BYTE 8 uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); +int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder); -#endif /* LLRT_UDIVMOD_H_ */ +#endif /* LLRT_H_ */ diff --git a/llrtc/lib/sdivmod64.c b/llrtc/lib/sdivmod64.c new file mode 100644 index 0000000..df294b3 --- /dev/null +++ b/llrtc/lib/sdivmod64.c @@ -0,0 +1,40 @@ +#include "llrt.h" +#include + +/* +Calls to udivmod64 internally. +Note: remainder uses sign of divisor. +*/ +int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder) +{ + int signbitidx = BITS_PER_BYTE * sizeof(dividend) - 1; + int signed_dividend = dividend < 0; + int signed_divisor = divisor < 0; + int signed_result = signed_divisor ^ signed_dividend; + + int64_t quotient; + uint64_t udvd, udvr, uquotient, uremainder; + + udvd = signed_dividend ? -dividend : dividend; + udvr = signed_divisor ? -divisor : divisor; + uquotient = udivmod64(udvd, udvr, &uremainder); + + if (signed_result){ + if (uremainder) { + quotient = -(int64_t)uquotient - 1; + } else { + quotient = -(int64_t)uquotient; + } + if (remainder) { + /* if signed, there could be unsigned overflow + causing undefined behavior */ + *remainder = (uint64_t)dividend - (uint64_t)quotient * (uint64_t)divisor; + } + } else { + quotient = (int64_t)uquotient; + if (remainder) { + *remainder = signed_divisor ? -uremainder : uremainder; + } + } + return quotient; +} diff --git a/llrtc/lib/test_sdivmod64.c b/llrtc/lib/test_sdivmod64.c new file mode 100644 index 0000000..1e804d6 --- /dev/null +++ b/llrtc/lib/test_sdivmod64.c @@ -0,0 +1,21 @@ +#include +#include +#include "llrt.h" + +int main(int argc, char * argv[]){ + int64_t n, d, q, r; + + if (argc != 3) { + printf("invalid argument: %s dividend divisor", argv[0]); + return 1; + } + sscanf(argv[1], "%lld", &n); + sscanf(argv[2], "%lld", &d); + + q = sdivmod64(n, d, &r); + + printf("%lld\n", q); + printf("%lld\n", r); + + return 0; +} diff --git a/llrtc/lib/test_sdivmod64.py b/llrtc/lib/test_sdivmod64.py new file mode 100644 index 0000000..4aa49a9 --- /dev/null +++ b/llrtc/lib/test_sdivmod64.py @@ -0,0 +1,56 @@ +import math +import os +import subprocess +udt = os.path.join('.', 'test_sdivmod64.run') + +def testcase(dividend, divisor): + print 'divmod64(%d, %d)' % (dividend, divisor) + + procargs = ('%s %s %s' % (udt, dividend, divisor)).split() + result = subprocess.check_output(procargs) + gotQ, gotR = map(int, result.splitlines()) + + expectQ = dividend // divisor + expectR = dividend % divisor + + print 'Q = %d, R = %d' % (gotQ, gotR) + + if expectQ != gotQ: + raise ValueError("invalid quotient: got=%d but expect=%d" % + (gotQ, expectQ)) + if expectR != gotR: + raise ValueError("invalid remainder: got=%d but expect=%d" % + (gotR, expectR)) + print 'OK' + +def testsequence(): + subjects = [ + (0, 1), + (0, 0xffffffff), + (1, 2), + (1, 983219), + (2, 2), + (3, 2), + (1024, 2), + (2048, 512), + (21321, 512), + (9329189, 1031), + (0xffffffff, 2), + (0xffffffff, 0xffff), + (0x1ffffffff, 2), + (0x1ffffffff, 0xffff), + (0xffff, 0xffffffff), + (0x0fffffffffffffff, 0xffff), + (0x7fffffffffffffff, 0x7fffffffffffffff), + (0x7fffffffffffffff, 0x7ffffffffffffff0), + (0x7fffffffffffffff, 87655678587161901), + ] + + for dvd, dvr in subjects: + testcase(dvd, dvr) + testcase(dvd, -dvr) + testcase(-dvd, dvr) + testcase(-dvd, -dvr) + +if __name__ == '__main__': + testsequence() diff --git a/llrtc/lib/test_udivmod64.c b/llrtc/lib/test_udivmod64.c index e2935c5..70b44aa 100644 --- a/llrtc/lib/test_udivmod64.c +++ b/llrtc/lib/test_udivmod64.c @@ -1,8 +1,6 @@ #include #include - -extern uint64_t -udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); +#include "llrt.h" int main(int argc, char * argv[]){ uint64_t n, d, q, r; @@ -19,4 +17,4 @@ int main(int argc, char * argv[]){ printf("%llu\n", r); return 0; -} \ No newline at end of file +} diff --git a/llrtc/lib/test_udivmod64.py b/llrtc/lib/test_udivmod64.py index 487a458..da07ccb 100644 --- a/llrtc/lib/test_udivmod64.py +++ b/llrtc/lib/test_udivmod64.py @@ -1,7 +1,7 @@ import math import os import subprocess -udt = os.path.join('.', 'test_udivmod64') +udt = os.path.join('.', 'test_udivmod64.run') def testcase(dividend, divisor): print 'divmod64(%d, %d)' % (dividend, divisor) diff --git a/llrtc/lib/udivmod64.c b/llrtc/lib/udivmod64.c index a028aea..5936f98 100644 --- a/llrtc/lib/udivmod64.c +++ b/llrtc/lib/udivmod64.c @@ -2,7 +2,7 @@ Implements unsigned divmod using for platform missing 64-bit division and/or modulo functions. */ -#include "udivmod64.h" +#include "llrt.h" /* count left zero for 64-bit words @@ -79,6 +79,6 @@ uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder) quotient |= 1ull << (63 - i); } } - *remainder = state.tmp; + if (remainder) *remainder = state.tmp; return quotient; } From e69048ad3dd6bdf541796e4f64e699962fe5006b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 14 Aug 2013 17:24:34 -0500 Subject: [PATCH 046/149] add div64 and mod64 --- llrtc/Makefile | 2 +- llrtc/lib/Makefile | 2 +- llrtc/lib/div64.c | 11 +++++++++++ llrtc/lib/llrt.h | 7 +++++++ llrtc/lib/mod64.c | 15 +++++++++++++++ 5 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 llrtc/lib/div64.c create mode 100644 llrtc/lib/mod64.c diff --git a/llrtc/Makefile b/llrtc/Makefile index bde100e..b15eac5 100644 --- a/llrtc/Makefile +++ b/llrtc/Makefile @@ -17,6 +17,6 @@ clean: make -C lib clean install: ir - make -C lib clean-test + cp llrt_*.ll ../llvm/llrt make -C lib clean-temp \ No newline at end of file diff --git a/llrtc/lib/Makefile b/llrtc/lib/Makefile index 8c9361d..9dbfb27 100644 --- a/llrtc/lib/Makefile +++ b/llrtc/lib/Makefile @@ -1,5 +1,5 @@ OUTPUT = llrt -SOURCES = udivmod64.c sdivmod64.c +SOURCES = udivmod64.c sdivmod64.c div64.c mod64.c TESTS = test_udivmod64.c test_sdivmod64.c CLANG = clang diff --git a/llrtc/lib/div64.c b/llrtc/lib/div64.c new file mode 100644 index 0000000..8466965 --- /dev/null +++ b/llrtc/lib/div64.c @@ -0,0 +1,11 @@ +#include "llrt.h" + +uint64_t udiv64(uint64_t dividend, uint64_t divisor) +{ + return udivmod64(dividend, divisor, NULL); +} + +int64_t sdiv64(int64_t dividend, int64_t divisor) +{ + return sdivmod64(dividend, divisor, NULL); +} diff --git a/llrtc/lib/llrt.h b/llrtc/lib/llrt.h index 0d26309..4e9e348 100644 --- a/llrtc/lib/llrt.h +++ b/llrtc/lib/llrt.h @@ -3,10 +3,17 @@ #include +#define NULL 0 #define BITS_PER_BYTE 8 uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder); +uint64_t udiv64(uint64_t dividend, uint64_t divisor); +int64_t sdiv64(int64_t dividend, int64_t divisor); + +uint64_t umod64(uint64_t dividend, uint64_t divisor); +int64_t smod64(int64_t dividend, int64_t divisor); + #endif /* LLRT_H_ */ diff --git a/llrtc/lib/mod64.c b/llrtc/lib/mod64.c new file mode 100644 index 0000000..875f6b9 --- /dev/null +++ b/llrtc/lib/mod64.c @@ -0,0 +1,15 @@ +#include "llrt.h" + +uint64_t umod64(uint64_t dividend, uint64_t divisor) +{ + uint64_t rem; + udivmod64(dividend, divisor, &rem); + return rem; +} + +int64_t smod64(int64_t dividend, int64_t divisor) +{ + int64_t rem; + sdivmod64(dividend, divisor, &rem); + return rem; +} From bf8693bb806be4192810b740c08300876d76cb34 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 14 Aug 2013 17:45:38 -0500 Subject: [PATCH 047/149] disable float div/mod test temporarily --- llvm/core.py | 3 + llvm/llrt.py | 77 ++++++++ llvm/llrt/llrt_x86.ll | 371 +++++++++++++++++++++++++++++++++++++++ llvm/llrt/llrt_x86_64.ll | 371 +++++++++++++++++++++++++++++++++++++++ llvm/test_llvmpy.py | 42 ++++- 5 files changed, 858 insertions(+), 6 deletions(-) create mode 100644 llvm/llrt.py create mode 100644 llvm/llrt/llrt_x86.ll create mode 100644 llvm/llrt/llrt_x86_64.ll diff --git a/llvm/core.py b/llvm/core.py index 945dd86..c4fe560 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1848,6 +1848,9 @@ class Instruction(User): def erase_from_parent(self): return self._ptr.eraseFromParent() + def replace_all_uses_with(self, inst): + self._ptr.replaceAllUsesWith(inst) + class CallOrInvokeInstruction(Instruction): _type_ = api.llvm.CallInst, api.llvm.InvokeInst diff --git a/llvm/llrt.py b/llvm/llrt.py new file mode 100644 index 0000000..b80914e --- /dev/null +++ b/llvm/llrt.py @@ -0,0 +1,77 @@ +import os +import llvm.core as lc +import llvm.passes as lp +import llvm.ee as le + +def replace_divmod64(lfunc): + '''Replaces all 64-bit integer division (sdiv, udiv) and modulo (srem, urem) + ''' + int64 = lc.Type.int(64) + int64ptr = lc.Type.pointer(lc.Type.int(64)) + + functy = lc.Type.function(int64, [int64, int64]) + udiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_udiv64') + sdiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_sdiv64') + umod64 = lfunc.module.get_or_insert_function(functy, '__llrt_umod64') + smod64 = lfunc.module.get_or_insert_function(functy, '__llrt_smod64') + + builder = lc.Builder.new(lfunc.entry_basic_block) + for bb in lfunc.basic_blocks: + for inst in bb.instructions: + if inst.opcode_name == 'sdiv' and inst.type == int64: + _replace_with(builder, inst, sdiv64) + elif inst.opcode_name == 'udiv' and inst.type == int64: + _replace_with(builder, inst, udiv64) + elif inst.opcode_name == 'srem' and inst.type == int64: + _replace_with(builder, inst, smod64) + elif inst.opcode_name == 'urem' and inst.type == int64: + _replace_with(builder, inst, umod64) + +def _replace_with(builder, inst, func): + '''Replace instruction with a call to the function with the same operands + as arguments. + ''' + builder.position_before(inst) + replacement = builder.call(func, inst.operands) + inst.replace_all_uses_with(replacement._ptr) + inst.erase_from_parent() + +def load(arch): + '''Load the LLRT module corresponding to the given architecture + Creates a new module and optimizes it using the information from + the host machine. + ''' + path = os.path.join(os.path.dirname(__file__), 'llrt', 'llrt_%s.ll' % arch) + with open(path) as fin: + lib = lc.Module.from_assembly(fin) + + # run passes to optimize + tm = le.TargetMachine.new() + pms = lp.build_pass_managers(tm, opt=3, fpm=False) + pms.pm.run(lib) + return lib + +class LLRT(object): + def __init__(self): + arch = le.get_default_triple().split('-', 1)[0] + self.module = load(arch) + self.engine = le.EngineBuilder.new(self.module).opt(3).create() + self.installed_symbols = set() + + def install_symbols(self): + '''Bind all the external symbols to the global symbol map. + Any future reference to these symbols will be automatically resolved + by LLVM. + ''' + for lfunc in self.module.functions: + if lfunc.linkage == lc.LINKAGE_EXTERNAL: + mangled = '__llrt_' + lfunc.name + self.installed_symbols.add(mangled) + ptr = self.engine.get_pointer_to_function(lfunc) + le.dylib_add_symbol(mangled, ptr) + + def uninstall_symbols(self): + for sym in self.installed_symbols: + le.dylib_add_symbol(sym, 0) + + diff --git a/llvm/llrt/llrt_x86.ll b/llvm/llrt/llrt_x86.ll new file mode 100644 index 0000000..5096214 --- /dev/null +++ b/llvm/llrt/llrt_x86.ll @@ -0,0 +1,371 @@ +; ModuleID = 'udivmod64_x86.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32-S128" + +%struct.div_state_ = type { i64, i64 } + +define i64 @udivmod64(i64 %dividend, i64 %divisor, i64* %remainder) nounwind ssp { + %1 = alloca i64, align 4 + %2 = alloca i64, align 8 + %3 = alloca i64, align 8 + %4 = alloca i64*, align 4 + %state = alloca %struct.div_state_, align 4 + %quotient = alloca i64, align 8 + %i = alloca i32, align 4 + %skipahead = alloca i32, align 4 + store i64 %dividend, i64* %2, align 8 + store i64 %divisor, i64* %3, align 8 + store i64* %remainder, i64** %4, align 4 + %5 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0 + store i64 0, i64* %5, align 4 + %6 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 1 + %7 = load i64* %2, align 8 + store i64 %7, i64* %6, align 4 + store i64 0, i64* %quotient, align 8 + %8 = load i64* %3, align 8 + %9 = icmp eq i64 %8, 0 + br i1 %9, label %10, label %11 + +;