Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ environment:

matrix:
# Since appveyor is quite slow, we only use a single configuration
- PYTHON: "3.8"
- PYTHON: "3.6"
ARCH: "64"
CONDA_ENV: testenv

Expand Down
18 changes: 16 additions & 2 deletions ffi/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,13 +469,27 @@ LLVMPY_GetEnumAttributeKindForName(const char *name, size_t len)
}

API_EXPORT(void)
LLVMPY_AddFunctionAttr(LLVMValueRef Fn, unsigned AttrKind)
LLVMPY_AddFunctionEnumAttr(LLVMValueRef Fn, unsigned AttrKindID, uint64_t AttrVal)
{
LLVMContextRef ctx = LLVMGetModuleContext(LLVMGetGlobalParent(Fn));
LLVMAttributeRef attr_ref = LLVMCreateEnumAttribute(ctx, AttrKindID, AttrVal);
LLVMAddAttributeAtIndex(Fn, LLVMAttributeReturnIndex, attr_ref);
}

API_EXPORT(void)
LLVMPY_AddFunctionStringAttr(LLVMValueRef Fn, const char * AttrName, unsigned AttrNameLen, const char * AttrVal, unsigned AttrValLen)
{
LLVMContextRef ctx = LLVMGetModuleContext(LLVMGetGlobalParent(Fn));
LLVMAttributeRef attr_ref = LLVMCreateEnumAttribute(ctx, AttrKind, 0);
LLVMAttributeRef attr_ref = LLVMCreateStringAttribute(ctx, AttrName, AttrNameLen, AttrVal, AttrValLen);
LLVMAddAttributeAtIndex(Fn, LLVMAttributeReturnIndex, attr_ref);
}

API_EXPORT(void)
LLVMPY_AddFunctionAttr(LLVMValueRef Fn, unsigned AttrKind)
{
LLVMPY_AddFunctionEnumAttr(Fn, AttrKind, 0);
}

API_EXPORT(int)
LLVMPY_IsDeclaration(LLVMValueRef GV)
{
Expand Down
33 changes: 27 additions & 6 deletions llvmlite/binding/value.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from ctypes import POINTER, c_char_p, c_int, c_size_t, c_uint, c_bool, c_void_p
from ctypes import (POINTER, c_char_p, c_int, c_size_t, c_uint, c_uint64,
c_bool, c_void_p)
import enum

from llvmlite.binding import ffi
Expand Down Expand Up @@ -178,7 +179,7 @@ def storage_class(self, value):
value = StorageClass[value]
ffi.lib.LLVMPY_SetDLLStorageClass(self, value)

def add_function_attribute(self, attr):
def add_function_attribute(self, attr, val=None):
"""Only works on function value

Parameters
Expand All @@ -189,11 +190,27 @@ def add_function_attribute(self, attr):
if not self.is_function:
raise ValueError('expected function value, got %s' % (self._kind,))
attrname = str(attr)
attrval = ffi.lib.LLVMPY_GetEnumAttributeKindForName(
# assume attribute is an EnumAttribute
attrkind_id = ffi.lib.LLVMPY_GetEnumAttributeKindForName(
_encode_string(attrname), len(attrname))
if attrval == 0:
raise ValueError('no such attribute {!r}'.format(attrname))
ffi.lib.LLVMPY_AddFunctionAttr(self, attrval)
if attrkind_id != 0:
if val is not None:
raise ValueError(
"attribute '%s' only takes 'None' as value" % (attrname, ))
ffi.lib.LLVMPY_AddFunctionEnumAttr(self, attrkind_id, 0)
else:
# if attribute is not an EnumAttribute, add it as a StringAttribute
val = 'true' if val is True or val is None else val
val = 'false' if val is False else val
if not isinstance(val, str):
raise ValueError(
f"attribute '{attrname}' takes only string or boolean "
f"values, got '{type(val)}'")
ffi.lib.LLVMPY_AddFunctionStringAttr(
self,
_encode_string(attrname), len(attrname),
_encode_string(val), len(val),
)

@property
def type(self):
Expand Down Expand Up @@ -454,6 +471,10 @@ def _next(self):
ffi.lib.LLVMPY_GetEnumAttributeKindForName.restype = c_uint

ffi.lib.LLVMPY_AddFunctionAttr.argtypes = [ffi.LLVMValueRef, c_uint]
ffi.lib.LLVMPY_AddFunctionEnumAttr.argtypes = [ffi.LLVMValueRef, c_uint,
c_uint64]
ffi.lib.LLVMPY_AddFunctionStringAttr.argtypes = [ffi.LLVMValueRef, c_char_p,
c_uint, c_char_p, c_uint]

ffi.lib.LLVMPY_IsDeclaration.argtypes = [ffi.LLVMValueRef]
ffi.lib.LLVMPY_IsDeclaration.restype = c_int
Expand Down
16 changes: 14 additions & 2 deletions llvmlite/tests/test_binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,9 +841,21 @@ def test_add_function_attribute(self):
mod = self.module()
fn = mod.get_function("sum")
fn.add_function_attribute("nocapture")
fn.add_function_attribute("no-nans-fp-math")
fn.add_function_attribute("no-nans-fp-math", True)
fn.add_function_attribute("no-nans-fp-math", False)
fn.add_function_attribute("no-nans-fp-math", "true")
with self.assertRaises(ValueError) as raises:
fn.add_function_attribute("zext")
self.assertEqual(str(raises.exception), "no such attribute 'zext'")
fn.add_function_attribute("nocapture", 0)
self.assertEqual(
str(raises.exception),
"attribute 'nocapture' only takes 'None' as value")
with self.assertRaises(ValueError) as raises:
fn.add_function_attribute("no-nans-fp-math", 1)
self.assertEqual(
str(raises.exception),
"attribute 'no-nans-fp-math' takes only string or boolean "
"values, got '<class 'int'>'")

def test_module(self):
mod = self.module()
Expand Down