diff --git a/llvm/_core.cpp b/llvm/_core.cpp index 99642e8..a833982 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -607,6 +607,30 @@ _wrap_obj2none(LLVMDeleteBasicBlock, LLVMBasicBlockRef) /*===-- MetaData -----------------------------------------------------===*/ _wrap_objlist2obj(LLVMMetaDataGet, LLVMModuleRef, LLVMValueRef, LLVMValueRef) +_wrap_objstrobj2none(LLVMAddNamedMetadataOperand, LLVMModuleRef, LLVMValueRef) +_wrap_objint2obj(LLVMMetaDataGetOperand, LLVMValueRef, LLVMValueRef) +_wrap_obj2obj(LLVMMetaDataGetNumOperands, LLVMValueRef, int) +_wrap_objstr2obj(LLVMMetaDataStringGet, LLVMModuleRef, LLVMValueRef) + +static PyObject * +_wLLVMGetNamedMetadataOperands(PyObject *self, PyObject *args) +{ + PyObject *obj_module; + const char *name; + + if (!PyArg_ParseTuple(args, "Os", &obj_module, &name)) + return NULL; + + LLVMModuleRef module = (LLVMModuleRef)PyCapsule_GetPointer(obj_module, NULL); + unsigned num_operands = LLVMGetNamedMetadataNumOperands(module, name); + LLVMValueRef *operands = (LLVMValueRef*)malloc(sizeof(LLVMValueRef)*num_operands); + LLVMGetNamedMetadataOperands(module, name, operands); + + PyObject *list = make_list_from_LLVMValueRef_array(operands, num_operands); + free(operands); + + return list; +} /*===-- Instructions -----------------------------------------------------===*/ @@ -1660,6 +1684,11 @@ static PyMethodDef core_methods[] = { /* MetaData */ _method( LLVMMetaDataGet ) + _method( LLVMGetNamedMetadataOperands ) + _method( LLVMAddNamedMetadataOperand ) + _method( LLVMMetaDataGetOperand ) + _method( LLVMMetaDataGetNumOperands ) + _method( LLVMMetaDataStringGet ) /* Instructions */ _method( LLVMGetInstructionParent ) diff --git a/llvm/core.py b/llvm/core.py index 215252a..a9c707e 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1457,6 +1457,38 @@ class MetaData(Value): ptr = _core.LLVMMetaDataGet(module.ptr, vs) return MetaData(ptr) + @staticmethod + def get_named_operands(module, name): + lst = _core.LLVMGetNamedMetadataOperands(module.ptr, name) + return [MetaData(ptr) for ptr in lst] + + @staticmethod + def add_named_operand(module, name, operand): + _core.LLVMAddNamedMetadataOperand(module.ptr, name, operand.ptr) + + @property + def operand_count(self): + return _core.LLVMMetaDataGetNumOperands(self.ptr) + + @property + def operands(self): + """Yields operands of this metadata.""" + return [self._get_operand(i) for i in range(self.operand_count)] + + def _get_operand(self, i): + return _make_value(_core.LLVMMetaDataGetOperand(self.ptr, i)) + +class MetaDataString(Value): + @staticmethod + def get(module, s): + ptr = _core.LLVMMetaDataStringGet(module.ptr, s) + return MetaDataString(ptr) + + @property + def string(self): + '''Same as MDString::getString''' + return self.name + #===----------------------------------------------------------------------=== # Instruction #===----------------------------------------------------------------------=== @@ -1627,6 +1659,8 @@ __class_for_valueid = { VALUE_CONSTANT_STRUCT : ConstantStruct, VALUE_CONSTANT_VECTOR : ConstantVector, VALUE_CONSTANT_POINTER_NULL : ConstantPointerNull, + VALUE_MD_NODE : MetaData, + VALUE_MD_STRING : MetaDataString, VALUE_INSTRUCTION + OPCODE_PHI : PHINode, VALUE_INSTRUCTION + OPCODE_CALL : CallOrInvokeInstruction, VALUE_INSTRUCTION + OPCODE_INVOKE : CallOrInvokeInstruction, diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 9925028..3cf0fb4 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -149,6 +149,23 @@ LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, return wrap(node); } +LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index) +{ + return wrap(llvm::unwrap(mdref)->getOperand(index)); +} + +unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref) +{ + return llvm::unwrap(mdref)->getNumOperands(); +} + +LLVMValueRef LLVMMetaDataStringGet(LLVMModuleRef modref, const char *s) +{ + LLVMContext & context = unwrap(modref)->getContext(); + MDString * const mdstring = MDString::get(context, s); + return wrap(mdstring); +} + const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst) { return llvm::unwrap(inst)->getOpcodeName(); diff --git a/llvm/extra.h b/llvm/extra.h index dc0a029..1772878 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -65,6 +65,21 @@ void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind, LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, unsigned valct); +/* + * Wraps MDNode::getOperand() + */ +LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index); + +/* + * Wraps MDNode::getNumOperands() + */ +unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref); + +/* + * Wraps MDString::get() + */ +LLVMValueRef LLVMMetaDataStringGet(LLVMModuleRef modref, const char *s); + /* * Wraps ConstantExpr::getOpcodeName() */ diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 6c85d93..8a9f155 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -16,7 +16,7 @@ else: from llvm import __version__ from llvm.core import (Module, Type, GlobalVariable, Function, Builder, - Constant) + Constant, MetaData, MetaDataString) import llvm.passes as lp import llvm.ee as le @@ -390,6 +390,23 @@ tests.append(TestUses) # --------------------------------------------------------------------------- +class TestMetaData(unittest.TestCase): + # test module metadata + def test_metadata(self): + m = Module.new('a') + t = Type.int() + metadata = MetaData.get(m, [Constant.int(t, 100), MetaDataString.get(m, 'abcdef')]) + MetaData.add_named_operand(m, 'foo', metadata) + self.assertEqual(MetaData.get_named_operands(m, 'foo'), [metadata]) + self.assertEqual(MetaData.get_named_operands(m, 'bar'), []) + self.assertEqual(len(metadata.operands), 2) + self.assertEqual(metadata.operands[0].z_ext_value, 100) + self.assertEqual(metadata.operands[1].string, 'abcdef') + +tests.append(TestMetaData) + +# --------------------------------------------------------------------------- + def run(verbosity=1): print('llvmpy is installed in: ' + os.path.dirname(__file__)) print('llvmpy version: ' + __version__)