From c8041e7d3700fe30ec9d0a1541a7d5850b456611 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 6 Jan 2013 16:07:45 -0500 Subject: [PATCH] add signext/zeroext attributes to small integer ccall arguments. fixes #978 --- src/ccall.cpp | 24 +++++++++++++++++++++++- src/codegen.cpp | 1 + test/ccall.jl | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 02363d82e232d..ddbb29fe0ec80 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -260,6 +260,8 @@ static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, false); } +static jl_value_t *jl_signed_type=NULL; + // --- code generator for ccall itself --- // ccall(pointer, rettype, (argtypes...), args...) @@ -368,12 +370,31 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) size_t i; bool haspointers = false; bool isVa = false; - for(i=0; i < jl_tuple_len(tt); i++) { + size_t nargt = jl_tuple_len(tt); + std::vector attrs; + for(i=0; i < nargt; i++) { jl_value_t *tti = jl_tupleref(tt,i); if (jl_is_seq_type(tti)) { isVa = true; tti = jl_tparam0(tti); } + if (jl_is_bits_type(tti)) { + // see pull req #978. need to annotate signext/zeroext for + // small integer arguments. + jl_bits_type_t *bt = (jl_bits_type_t*)tti; + if (bt->nbits < 32) { + if (jl_signed_type == NULL) { + jl_signed_type = jl_get_global(jl_core_module,jl_symbol("Signed")); + } + Attributes::AttrVal av; + if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0)) + av = Attributes::SExt; + else + av = Attributes::ZExt; + attrs.push_back(AttributeWithIndex::get(getGlobalContext(), i+1, + ArrayRef(&av, 1))); + } + } Type *t = julia_type_to_llvm(tti); if (t == NULL) { JL_GC_POP(); @@ -524,6 +545,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) ArrayRef(&argvals[0],(nargs-3)/2)); if (cc != CallingConv::C) ((CallInst*)result)->setCallingConv(cc); + ((CallInst*)result)->setAttributes(AttrListPtr::get(getGlobalContext(), ArrayRef(attrs))); // restore temp argument area stack pointer if (haspointers) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 9346563258fa5..380272055d721 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -11,6 +11,7 @@ #include "llvm/Intrinsics.h" #include "llvm/PassManager.h" #include "llvm/Analysis/Verifier.h" +#include "llvm/Attributes.h" #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 2 #include "llvm/DebugInfo.h" #include "llvm/DIBuilder.h" diff --git a/test/ccall.jl b/test/ccall.jl index a61ab82fda162..49351a5a6b4aa 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1,3 +1,3 @@ -ccall_test_func(x) = ccall((:testUcharX, "./libccalltest"), Int32, (Int8,), x) +ccall_test_func(x) = ccall((:testUcharX, "./libccalltest"), Int32, (Uint8,), x) @assert ccall_test_func(3) == 1 @assert ccall_test_func(259) == 1