Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tuples made me sad (so I fixed them) #4042

Merged
merged 28 commits into from
Dec 7, 2013
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9f2002c
Pass tuples unboxed if possible
Keno Aug 11, 2013
793562b
All tests pass
Keno Aug 12, 2013
9bfd041
Specialize more functions
Keno Aug 12, 2013
4917312
bugfixes
Keno Aug 13, 2013
2ffa794
Remove unnessecary pto argument from emit_unbox
Keno Aug 13, 2013
c802070
Adjust llvmcall for new tuple infrastructure
Keno Aug 13, 2013
91f8ae7
Some llvmcall bugfixes
Keno Aug 13, 2013
c343b5a
Address compiler warnings
Keno Aug 13, 2013
49217ff
Also remove PM initialization
Keno Aug 13, 2013
9cc2819
Handle nothingness correctly
Keno Aug 13, 2013
aec2612
Fix a performance regression
Keno Aug 14, 2013
6b567e1
tpl -> &tpl and don't use return value from unreachable
Keno Aug 15, 2013
1933ea7
Allow unboxed storing tupl purebits tuples
Keno Aug 15, 2013
c58e1ff
remove invalid check from store_unboxed_p
Keno Aug 16, 2013
17690a0
is_stable_expr for tuples
Keno Aug 16, 2013
10330fa
Fix tuples branch for some changes since it was introduced
Keno Oct 2, 2013
a93b442
Tuples branch bug-fixes
Keno Oct 5, 2013
0e2c3e6
Fix a missing JL_GC_POP
Keno Oct 25, 2013
f8b79c4
Fix ifelse on the tuple branch
Keno Oct 26, 2013
8217d70
Merge some bugfixes from MCJIT branch
Keno Nov 16, 2013
71a5def
Fix build failure after merge
Keno Nov 17, 2013
665ffe5
Cleanup
Keno Nov 19, 2013
e02db98
Separate out llvmcall
Keno Nov 19, 2013
9deb3a1
Simplify emit_tupleset, but disallowing non-constant ones
Keno Nov 20, 2013
ee26d21
Add a missing GC root
Keno Nov 21, 2013
f9999b1
Fix an improperly adjusted gc frame
Keno Nov 23, 2013
a7d99e6
Fix vararg root counting
Keno Nov 27, 2013
d5ad8e6
Fix a rebase conflict
Keno Nov 27, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Separate out llvmcall
  • Loading branch information
Keno committed Nov 29, 2013
commit e02db98e162df55034d1a8e0db0c07f0aff0cdf3
2 changes: 1 addition & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export
JULIA_HOME, nothing, Main,
# intrinsics module
Intrinsics
#ccall, cglobal, llvmcall, abs_float, add_float, add_int, and_int, ashr_int,
#ccall, cglobal, abs_float, add_float, add_int, and_int, ashr_int,
#box, bswap_int, checked_fptosi, checked_fptoui, checked_sadd,
#checked_smul, checked_ssub, checked_uadd, checked_umul, checked_usub,
#nan_dom_err, copysign_float, ctlz_int, ctpop_int, cttz_int,
Expand Down
4 changes: 0 additions & 4 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,6 @@ t_func[nan_dom_err] = (2, 2, (a, b)->a)
t_func[eval(Core.Intrinsics,:ccall)] =
(3, Inf, (fptr, rt, at, a...)->(is(rt,Type{Void}) ? Nothing :
isType(rt) ? rt.parameters[1] : Any))
t_func[eval(Core.Intrinsics,:llvmcall)] =
(3, Inf, (fptr, rt, at, a...)->(is(rt,Type{Void}) ? Nothing :
isType(rt) ? rt.parameters[1] :
isa(rt,Tuple) ? map(x->x.parameters[1],rt) : Any))
t_func[eval(Core.Intrinsics,:cglobal)] =
(1, 2, (fptr, t...)->(isempty(t) ? Ptr{Void} :
isType(t[1]) ? Ptr{t[1].parameters[1]} : Ptr))
Expand Down
132 changes: 0 additions & 132 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,138 +493,6 @@ static Value *emit_cglobal(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
return mark_julia_type(res, rt);
}

// llvmcall(ir, (rettypes...), (argtypes...), args...)
static Value *emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
{
JL_NARGSV(llvmcall, 3)
jl_value_t *rt = NULL, *at = NULL;
JL_GC_PUSH2(&rt, &at);
{
JL_TRY {
at = jl_interpret_toplevel_expr_in(ctx->module, args[3],
&jl_tupleref(ctx->sp,0),
jl_tuple_len(ctx->sp)/2);
}
JL_CATCH {
jl_rethrow_with_add("error interpreting llvmcall return type");
}
}
{
JL_TRY {
rt = jl_interpret_toplevel_expr_in(ctx->module, args[2],
&jl_tupleref(ctx->sp,0),
jl_tuple_len(ctx->sp)/2);
}
JL_CATCH {
jl_rethrow_with_add("error interpreting ccall argument tuple");
}
}
JL_TYPECHK(llvmcall, type, rt);
JL_TYPECHK(llvmcall, tuple, at);
JL_TYPECHK(llvmcall, type, at);
int i = 1;
// Make sure to find a unique name
std::string ir_name;
while(true) {
std::stringstream name;
name << (ctx->f->getName().str()) << i++;
ir_name = name.str();
if(jl_Module->getFunction(ir_name) == NULL)
break;
}
jl_value_t *ir = static_eval(args[1], ctx, true);
if (!jl_is_byte_string(ir))
{
jl_error("First argument to llvmcall must be a string");
}

std::stringstream ir_stream;

// Generate arguments
std::string arguments;
llvm::raw_string_ostream argstream(arguments);
jl_tuple_t *tt = (jl_tuple_t*)at;
size_t nargt = jl_tuple_len(tt);
Value *argvals[nargt];
/*
* Semantics for arguments are as follows:
* If the argument type is immutable (including bitstype), we pass the loaded llvm value
* type. Otherwise we pass a pointer to a jl_value_t.
*/
for (size_t i = 0; i < nargt; ++i)
{
jl_value_t *tti = jl_tupleref(tt,i);
Type *t = julia_type_to_llvm(tti);
t->print(argstream);
argstream << " ";
jl_value_t *argi = args[4+i];
Value *arg;
bool needroot = false;
if (t == jl_pvalue_llvmt || !jl_isbits(tti)) {
arg = emit_expr(argi, ctx, true);
if (t == jl_pvalue_llvmt && arg->getType() != jl_pvalue_llvmt) {
arg = boxed(arg, ctx);
needroot = true;
}
}
else {
arg = emit_unboxed(argi, ctx);
if (jl_is_bitstype(expr_type(argi, ctx))) {
arg = emit_unbox(t, arg, tti);
}
}

#ifdef JL_GC_MARKSWEEP
// make sure args are rooted
if (t == jl_pvalue_llvmt && (needroot || might_need_root(argi))) {
make_gcroot(arg, ctx);
}
#endif
bool mightNeedTempSpace = false;
argvals[i] = julia_to_native(t,tti,arg,argi,false,i,ctx,&mightNeedTempSpace,&mightNeedTempSpace);
if ((i+1) != nargt)
argstream << ",";
}

Type *rettype;
std::string rstring;
llvm::raw_string_ostream rtypename(rstring);
// Construct return type
rettype = julia_type_to_llvm(rt);
rettype->print(rtypename);

ir_stream << "; Number of arguments: " << nargt << "\n"
<< "define "<<rtypename.str()<<" @" << ir_name << "("<<argstream.str()<<") {\n"
<< jl_string_data(ir) << "\n}";
SMDiagnostic Err = SMDiagnostic();
std::string ir_string = ir_stream.str();
Module *m = ParseAssemblyString(ir_string.data(),jl_Module,Err,jl_LLVMContext);
if (m == NULL) {
std::string message = "Failed to parse LLVM Assembly: \n";
llvm::raw_string_ostream stream(message);
Err.print("julia",stream,true);
jl_error(stream.str().c_str());
}
Function *f = m->getFunction(ir_name);
/*
* It might be tempting to just try to set the Always inline attribute on the function
* and hope for the best. However, this doesn't work since that would require an inlining
* pass (which is a Call Graph pass and cannot be managed by a FunctionPassManager). Instead
* We are sneaky and call the inliner directly. This however doesn't work until we've actually
* generated the entire function, so we need to store it in the context until the end of the
* function. This also has the benefit of looking exactly like we cut/pasted it in in `code_llvm`.
*/
f->setLinkage(GlobalValue::LinkOnceODRLinkage);

// the actual call
CallInst *inst = builder.CreateCall(f,ArrayRef<Value*>(&argvals[0],nargt));
ctx->to_inline.push_back(inst);

JL_GC_POP();

return mark_julia_type(inst,rt);
}

// --- code generator for ccall itself ---

// ccall(pointer, rettype, (argtypes...), args...)
Expand Down
4 changes: 1 addition & 3 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace JL_I {
// pointer access
pointerref, pointerset, pointertoref,
// c interface
ccall, cglobal, jl_alloca, llvmcall
ccall, cglobal, jl_alloca
};
};

Expand Down Expand Up @@ -669,7 +669,6 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
switch (f) {
case ccall: return emit_ccall(args, nargs, ctx);
case cglobal: return emit_cglobal(args, nargs, ctx);
case llvmcall: return emit_llvmcall(args, nargs, ctx);

HANDLE(box,2) return generic_box(args[1], args[2], ctx);
HANDLE(unbox,2) return generic_unbox(args[1], args[2], ctx);
Expand Down Expand Up @@ -1217,5 +1216,4 @@ extern "C" void jl_init_intrinsic_functions(void)
ADD_I(nan_dom_err);
ADD_I(ccall); ADD_I(cglobal);
ADD_I(jl_alloca);
ADD_I(llvmcall);
}