From 43816c8b6ba6cf04b43b3bb32498801ef618002a Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 14 Jun 2013 23:16:52 -0400 Subject: [PATCH] (disabled) Revert "Revert "partially fix #2149, partially support more efficient struct return (disabled). unfortunately this would break some struct returns while making other work -- this needs to be selectively enabled for different possible return types" This reverts commit 4fa936436a1ebb44b4e73023e557d3f686f8dacc. Conflicts: src/ccall.cpp --- src/ccall.cpp | 85 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 25 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 67854a5581877..bd03ebcfde9a1 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -315,14 +315,14 @@ typedef struct { static native_sym_arg_t interpret_symbol_arg(jl_value_t *arg, jl_codectx_t *ctx, const char *fname) { jl_value_t *ptr = NULL; - Value *jl_ptr = NULL; + Value *jl_ptr=NULL; ptr = static_eval(arg, ctx, true); if (ptr == NULL) { jl_value_t *ptr_ty = expr_type(arg, ctx); Value *arg1 = emit_unboxed(arg, ctx); if (!jl_is_cpointer_type(ptr_ty)) { - emit_cpointercheck(arg1, + emit_cpointercheck(arg1, !strcmp(fname,"ccall") ? "ccall: first argument not a pointer or valid constant expression" : "cglobal: first argument not a pointer or valid constant expression", @@ -331,8 +331,8 @@ static native_sym_arg_t interpret_symbol_arg(jl_value_t *arg, jl_codectx_t *ctx, jl_ptr = emit_unbox(T_size, T_psize, arg1); } - void *fptr = NULL; - char *f_name = NULL, *f_lib = NULL; + void *fptr=NULL; + char *f_name=NULL, *f_lib=NULL; if (ptr != NULL) { if (jl_is_tuple(ptr) && jl_tuple_len(ptr)==1) { ptr = jl_tupleref(ptr,0); @@ -344,8 +344,8 @@ static native_sym_arg_t interpret_symbol_arg(jl_value_t *arg, jl_codectx_t *ctx, if (f_name != NULL) { // just symbol, default to JuliaDLHandle #ifdef _OS_WINDOWS_ - //TODO: store the f_lib name instead of fptr - fptr = jl_dlsym_win32(f_name); + //TODO: store the f_lib name instead of fptr + fptr = jl_dlsym_win32(f_name); #else // will look in process symbol table #endif @@ -478,19 +478,30 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) JL_TYPECHK(ccall, type, rt); JL_TYPECHK(ccall, tuple, at); JL_TYPECHK(ccall, type, at); - jl_tuple_t *tt = (jl_tuple_t*)at; - std::vector fargt(0); - std::vector fargt_sig(0); Type *lrt = julia_struct_to_llvm(rt); if (lrt == NULL) { JL_GC_POP(); emit_error("ccall: return type doesn't correspond to a C type", ctx); return literal_pointer_val(jl_nothing); } + jl_tuple_t *tt = (jl_tuple_t*)at; + std::vector fargt(0); + std::vector fargt_sig(0); + std::vector attrs; + int sret = 0; + if (0 && lrt->isStructTy()) { +#ifdef LLVM32 + attrs.push_back(AttributeWithIndex::get(getGlobalContext(), 1, Attributes::StructRet)); +#else + attrs.push_back(AttributeWithIndex::get(1, Attribute::StructRet)); +#endif + fargt_sig.push_back(PointerType::get(lrt,0)); + lrt = T_void; + sret = 1; + } size_t i; bool isVa = false; size_t nargt = jl_tuple_len(tt); - std::vector attrs; for(i=0; i < nargt; i++) { jl_value_t *tti = jl_tupleref(tt,i); @@ -514,15 +525,14 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) av = Attributes::SExt; else av = Attributes::ZExt; - attrs.push_back(AttributeWithIndex::get(getGlobalContext(), i+1, - ArrayRef(&av, 1))); + attrs.push_back(AttributeWithIndex::get(getGlobalContext(), i+1+sret, av)); #else Attribute::AttrConst av; if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0)) av = Attribute::SExt; else av = Attribute::ZExt; - attrs.push_back(AttributeWithIndex::get(i+1, av)); + attrs.push_back(AttributeWithIndex::get(i+1+sret, av)); #endif } } @@ -536,6 +546,14 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) emit_error(msg.str(), ctx); return literal_pointer_val(jl_nothing); } + if (0 && t->isStructTy()) { + t = PointerType::get(t,0); +#ifdef LLVM32 + attrs.push_back(AttributeWithIndex::get(getGlobalContext(), i+1+sret, Attributes::ByVal)); +#else + attrs.push_back(AttributeWithIndex::get(i+1, Attribute::ByVal)); +#endif + } fargt.push_back(t); if (!isVa) fargt_sig.push_back(t); @@ -640,7 +658,22 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) } // emit arguments - Value *argvals[(nargs-3)/2]; + Value *argvals[(nargs-3)/2 + sret]; + Value *result; + if (sret) { + assert(jl_is_structtype(rt)); + result = builder.CreateCall( + jlallocobj_func, + ConstantInt::get(T_size, + sizeof(void*)+((jl_datatype_t*)rt)->size)); + //TODO: Fill type pointer fields with C_NULL's + builder.CreateStore( + literal_pointer_val((jl_value_t*)rt), + emit_nthptr_addr(result, (size_t)0)); + argvals[0] = builder.CreateBitCast( + emit_nthptr_addr(result, (size_t)1), + fargt_sig[0]); + } int last_depth = ctx->argDepth; int nargty = jl_tuple_len(tt); bool needTempSpace = false; @@ -664,7 +697,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) } Value *arg; if (largty == jl_pvalue_llvmt || - largty->isStructTy()) { + largty->isStructTy()) { arg = emit_expr(argi, ctx, true); } else { @@ -686,8 +719,8 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) #endif bool mightNeed=false; - argvals[ai] = julia_to_native(largty, jargty, arg, argi, addressOf, - ai+1, ctx, &mightNeed); + argvals[ai+sret] = julia_to_native(largty, jargty, arg, argi, addressOf, + ai+1, ctx, &mightNeed); needTempSpace |= mightNeed; } if (needTempSpace) { @@ -703,16 +736,18 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) instList.insertAfter((Instruction*)saveloc, (Instruction*)stacksave); } // the actual call - Value *result = builder.CreateCall(llvmf, - ArrayRef(&argvals[0],(nargs-3)/2)); - if (cc != CallingConv::C) - ((CallInst*)result)->setCallingConv(cc); - + Value *ret = builder.CreateCall( + llvmf, + ArrayRef(&argvals[0],(nargs-3)/2+sret)); #ifdef LLVM32 - ((CallInst*)result)->setAttributes(AttrListPtr::get(getGlobalContext(), ArrayRef(attrs))); + ((CallInst*)ret)->setAttributes(AttrListPtr::get(getGlobalContext(), ArrayRef(attrs))); #else - ((CallInst*)result)->setAttributes(AttrListPtr::get(attrs.data(),attrs.size())); + ((CallInst*)ret)->setAttributes(AttrListPtr::get(attrs.data(),attrs.size())); #endif + if (cc != CallingConv::C) + ((CallInst*)ret)->setCallingConv(cc); + if (!sret) + result = ret; if (needTempSpace) { // restore temp argument area stack pointer assert(saveloc != NULL); @@ -732,7 +767,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) } JL_GC_POP(); - if (lrt == T_void) + if (!sret && lrt == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); if (lrt->isStructTy()) { //fprintf(stderr, "ccall rt: %s -> %s\n", f_name, ((jl_tag_type_t*)rt)->name->name->name);