Merge pull request #20 from laanwj/2012_09_module_named_metadata

Add support for module named metadata
This commit is contained in:
Ilan Schnell 2012-09-12 12:27:55 -07:00
commit 28c659ec90
5 changed files with 113 additions and 1 deletions

View file

@ -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 )

View file

@ -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,

View file

@ -149,6 +149,23 @@ LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs,
return wrap(node);
}
LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index)
{
return wrap(llvm::unwrap<llvm::MDNode>(mdref)->getOperand(index));
}
unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref)
{
return llvm::unwrap<llvm::MDNode>(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<llvm::ConstantExpr>(inst)->getOpcodeName();

View file

@ -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()
*/

View file

@ -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__)