diff --git a/llvm/_core.cpp b/llvm/_core.cpp index d6e781f..b7de471 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -618,6 +618,11 @@ _wrap_objstr2obj(LLVMAppendBasicBlock, LLVMValueRef, LLVMBasicBlockRef) _wrap_objstr2obj(LLVMInsertBasicBlock, LLVMBasicBlockRef, LLVMBasicBlockRef) _wrap_obj2none(LLVMDeleteBasicBlock, LLVMBasicBlockRef) + +/*===-- MetaData -----------------------------------------------------===*/ + +_wrap_objlist2obj(LLVMMetaDataGet, LLVMModuleRef, LLVMValueRef, LLVMValueRef) + /*===-- Instructions -----------------------------------------------------===*/ _wrap_obj2obj(LLVMGetInstructionParent, LLVMValueRef, LLVMBasicBlockRef) @@ -636,6 +641,8 @@ _wrap_objint2none(LLVMSetVolatile, LLVMValueRef) _wrap_obj2obj(LLVMInstGetOpcode, LLVMValueRef, int) _wrap_obj2str(LLVMInstGetOpcodeName, LLVMValueRef) +_wrap_objstrobj2none(LLVMInstSetMetaData, LLVMValueRef, LLVMValueRef) + /*===-- Call Sites (Call or Invoke) --------------------------------------===*/ _wrap_objint2none(LLVMSetInstructionCallConv, LLVMValueRef) @@ -1691,6 +1698,9 @@ static PyMethodDef core_methods[] = { _method( LLVMInsertBasicBlock ) _method( LLVMDeleteBasicBlock ) + /* MetaData */ + _method( LLVMMetaDataGet ) + /* Instructions */ _method( LLVMGetInstructionParent ) _method( LLVMGetFirstInstruction ) @@ -1708,6 +1718,8 @@ static PyMethodDef core_methods[] = { _method( LLVMInstGetOpcode ) _method( LLVMInstGetOpcodeName ) + _method( LLVMInstSetMetaData ) + /* Call Sites (Call or Invoke) */ _method( LLVMSetInstructionCallConv ) _method( LLVMGetInstructionCallConv ) diff --git a/llvm/core.py b/llvm/core.py index efcc672..f6007c3 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1427,6 +1427,17 @@ class Function(GlobalValue): # failure, it appears to print result to stderr and abort. return _core.LLVMVerifyFunction(self.ptr) != 0 +#===----------------------------------------------------------------------=== +# MetaData +#===----------------------------------------------------------------------=== + +class MetaData(Value): + @staticmethod + def get(module, values): + vs = unpack_values(values) + ptr = _core.LLVMMetaDataGet(module.ptr, vs) + return MetaData(ptr) + #===----------------------------------------------------------------------=== # Instruction #===----------------------------------------------------------------------=== @@ -1477,6 +1488,9 @@ class Instruction(User): def set_volatile(self, flag): return _core.LLVMSetVolatile(self.ptr, int(bool(flag))) + def set_metadata(self, kind, metadata): + return _core.LLVMInstSetMetaData(self.ptr, kind, metadata.ptr) + @property def opcode(self): return _core.LLVMInstGetOpcode(self.ptr) diff --git a/llvm/extra.cpp b/llvm/extra.cpp index e79755b..aa98a17 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -83,11 +83,11 @@ #include "extra.h" #include "llvm_c_extra.h" - namespace llvm{ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(EngineBuilder, LLVMEngineBuilderRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) } + /* * For use in LLVMDumpPasses to dump passes. */ @@ -127,7 +127,27 @@ const CodeGenOpt::Level OptLevelMap[] = { } // end anony namespace +void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind, + LLVMValueRef metaref) +{ + using namespace llvm; + unwrap(instref)->setMetadata(mdkind, unwrap(metaref)); +} +LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, + unsigned valct) +{ + using namespace llvm; + LLVMContext & context = unwrap(modref)->getContext(); + std::vector vals; + vals.reserve(valct); + for(unsigned i = 0; i < valct; ++i ){ + vals.push_back(unwrap(valrefs[i])); + } + + MDNode * const node = MDNode::get(context, vals); + return wrap(node); +} const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst) { diff --git a/llvm/extra.h b/llvm/extra.h index b428ed5..87e0759 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -53,15 +53,25 @@ extern "C" { #endif - +/* + * Wraps Instruction::setMetadata() + */ +void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind, + LLVMValueRef metaref); /* - * Wraps ConstantExpr::getOpcodeName(); + * Wraps MDNode::get() + */ +LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, + unsigned valct); + +/* + * Wraps ConstantExpr::getOpcodeName() */ const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst); /* - * Wraps ConstantExpr::getOpcode(); + * Wraps ConstantExpr::getOpcode() */ unsigned LLVMGetConstExprOpcode(LLVMValueRef inst); diff --git a/llvm/wrap.h b/llvm/wrap.h index 8104820..830ff91 100644 --- a/llvm/wrap.h +++ b/llvm/wrap.h @@ -635,6 +635,30 @@ _w ## func (PyObject *self, PyObject *args) \ return ctor_ ## outtype ( func (arg1, arg2, arg3)); \ } +/** + * Wrap LLVM functions of the type + * void func(intype1 arg1, const char *arg2, intype3 arg3) + */ +#define _wrap_objstrobj2none(func, intype1, intype3) \ +static PyObject * \ +_w ## func (PyObject *self, PyObject *args) \ +{ \ + PyObject *obj1, *obj3; \ + intype1 arg1; \ + const char *arg2; \ + intype3 arg3; \ + \ + if (!PyArg_ParseTuple(args, "OsO", &obj1, &arg2, &obj3)) \ + return NULL; \ + \ + arg1 = ( intype1 ) PyCapsule_GetPointer(obj1, NULL); \ + arg3 = ( intype3 ) PyCapsule_GetPointer(obj3, NULL); \ + \ + func(arg1, arg2, arg3); \ + \ + Py_RETURN_NONE; \ +} + /** * Wrap LLVM functions of the type @@ -660,7 +684,7 @@ _w ## func (PyObject *self, PyObject *args) \ } /** - * Wrap LLVM functions of the type + * Wrap LLVM functions of the type * outtype func(intype1 arg1, intype2 arg2, intype3, int arg3, const char *arg4) */ #define _wrap_objobjobjintstr2obj(func, intype1, intype2, intype3, outtype) \ diff --git a/test/metadata.py b/test/metadata.py new file mode 100644 index 0000000..63118f5 --- /dev/null +++ b/test/metadata.py @@ -0,0 +1,28 @@ +import unittest + +from llvm.core import * + +class TestMetaData(unittest.TestCase): + def test_metadata_get(self): + module = Module.new('test_metadata') + md = MetaData.get(module, [Constant.int(Type.int(), 1234)]) + + def test_meta_load_nt(self): + module = Module.new('test_meta_load_nt') + func = module.add_function(Type.function(Type.void(), []), + name='test_load_nt') + bldr = Builder.new(func.append_basic_block('entry')) + addr = Constant.int(Type.int(), 0xdeadbeef) + loadinst = bldr.load(bldr.inttoptr(addr, Type.pointer(Type.int(8)))) + + md = MetaData.get(module, [Constant.int(Type.int(), 1)]) + loadinst.set_metadata('nontemporal', md) + + bldr.ret_void() + module.verify() + + self.assertIn('!nontemporal', str(loadinst)) + +if __name__ == '__main__': + unittest.main() +