Skip to content

Commit 944e754

Browse files
committed
WIP: allow @generated begin ... end inside a function to provide an optional optimizer
use meta nodes instead of `stagedfunction` expression head
1 parent 056b374 commit 944e754

15 files changed

+173
-115
lines changed

base/docs/Docs.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ finddoc(λ, def) = false
642642

643643
# Predicates and helpers for `docm` expression selection:
644644

645-
const FUNC_HEADS = [:function, :stagedfunction, :macro, :(=)]
645+
const FUNC_HEADS = [:function, :macro, :(=)]
646646
const BINDING_HEADS = [:typealias, :const, :global, :(=)] # deprecation: remove `typealias` post-0.6
647647
# For the special `:@mac` / `:(Base.@mac)` syntax for documenting a macro after definition.
648648
isquotedmacrocall(x) =

base/expr.jl

+12-3
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,18 @@ function remove_linenums!(ex::Expr)
333333
end
334334

335335
macro generated(f)
336-
if isa(f, Expr) && (f.head === :function || is_short_function_def(f))
337-
f.head = :stagedfunction
338-
return Expr(:escape, f)
336+
if isa(f, Expr) && (f.head === :function || is_short_function_def(f))
337+
body = f.args[2]
338+
lno = body.args[1]
339+
return Expr(:escape,
340+
Expr(f.head, f.args[1],
341+
Expr(:block,
342+
lno,
343+
Expr(:meta, :generator, body),
344+
Expr(:meta, :generated_only),
345+
Expr(:return, nothing))))
346+
elseif isa(f, Expr) && f.head === :block
347+
return Expr(:escape, Expr(:meta, :generator, f))
339348
else
340349
error("invalid syntax; @generated must be used with a function definition")
341350
end

base/methodshow.jl

+11-2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ function argtype_decl(env, n, sig::DataType, i::Int, nargs, isva::Bool) # -> (ar
4242
return s, string_with_env(env, t)
4343
end
4444

45+
function method_argnames(m::Method)
46+
if !isdefined(m, :source)
47+
gm = first(methods(m.generator))
48+
return method_argnames(gm)[length(m.sparam_syms)+2 : end]
49+
end
50+
argnames = Vector{Any}(m.nargs)
51+
ccall(:jl_fill_argnames, Void, (Any, Any), m.source, argnames)
52+
return argnames
53+
end
54+
4555
function arg_decl_parts(m::Method)
4656
tv = Any[]
4757
sig = m.sig
@@ -52,8 +62,7 @@ function arg_decl_parts(m::Method)
5262
file = m.file
5363
line = m.line
5464
if isdefined(m, :source) || isdefined(m, :generator)
55-
argnames = Vector{Any}(m.nargs)
56-
ccall(:jl_fill_argnames, Void, (Any, Any), isdefined(m, :source) ? m.source : m.generator.inferred, argnames)
65+
argnames = method_argnames(m)
5766
show_env = ImmutableDict{Symbol, Any}()
5867
for t in tv
5968
show_env = ImmutableDict(show_env, :unionall_env => t)

base/reflection.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,8 @@ function length(mt::MethodTable)
732732
end
733733
isempty(mt::MethodTable) = (mt.defs === nothing)
734734

735-
uncompressed_ast(m::Method) = uncompressed_ast(m, isdefined(m, :source) ? m.source : m.generator.inferred)
735+
uncompressed_ast(m::Method) = isdefined(m,:source) ? uncompressed_ast(m, m.source) :
736+
uncompressed_ast(first(methods(m.generator)))
736737
uncompressed_ast(m::Method, s::CodeInfo) = s
737738
uncompressed_ast(m::Method, s::Array{UInt8,1}) = ccall(:jl_uncompress_ast, Any, (Any, Any), m, s)::CodeInfo
738739
uncompressed_ast(m::Core.MethodInstance) = uncompressed_ast(m.def)

src/ast.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ jl_sym_t *meta_sym; jl_sym_t *compiler_temp_sym;
5555
jl_sym_t *inert_sym; jl_sym_t *vararg_sym;
5656
jl_sym_t *unused_sym; jl_sym_t *static_parameter_sym;
5757
jl_sym_t *polly_sym; jl_sym_t *inline_sym;
58-
jl_sym_t *propagate_inbounds_sym;
58+
jl_sym_t *propagate_inbounds_sym; jl_sym_t *generator_sym;
59+
jl_sym_t *generated_only_sym;
5960
jl_sym_t *isdefined_sym; jl_sym_t *nospecialize_sym;
6061
jl_sym_t *macrocall_sym;
6162
jl_sym_t *hygienicscope_sym;
@@ -343,6 +344,8 @@ void jl_init_frontend(void)
343344
hygienicscope_sym = jl_symbol("hygienic-scope");
344345
gc_preserve_begin_sym = jl_symbol("gc_preserve_begin");
345346
gc_preserve_end_sym = jl_symbol("gc_preserve_end");
347+
generator_sym = jl_symbol("generator");
348+
generated_only_sym = jl_symbol("generated_only");
346349
}
347350

348351
JL_DLLEXPORT void jl_lisp_prompt(void)

src/ast.scm

+6
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,12 @@
358358
(and (if one (length= e 3) (length> e 2))
359359
(eq? (car e) 'meta) (eq? (cadr e) 'nospecialize)))
360360

361+
(define (generator-meta? e)
362+
(and (length= e 3) (eq? (car e) 'meta) (eq? (cadr e) 'generator)))
363+
364+
(define (generated_only-meta? e)
365+
(and (length= e 2) (eq? (car e) 'meta) (eq? (cadr e) 'generated_only)))
366+
361367
;; flatten nested expressions with the given head
362368
;; (op (op a b) c) => (op a b c)
363369
(define (flatten-ex head e)

src/codegen.cpp

+2-6
Original file line numberDiff line numberDiff line change
@@ -1199,8 +1199,6 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t
11991199
li->inferred &&
12001200
// and there is something to delete (test this before calling jl_ast_flag_inlineable)
12011201
li->inferred != jl_nothing &&
1202-
// don't delete the code for the generator
1203-
li != li->def.method->generator &&
12041202
// don't delete inlineable code, unless it is constant
12051203
(li->jlcall_api == 2 || !jl_ast_flag_inlineable((jl_array_t*)li->inferred)) &&
12061204
// don't delete code when generating a precompile file
@@ -3829,11 +3827,10 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr)
38293827
}
38303828
Value *a1 = boxed(ctx, emit_expr(ctx, args[1]));
38313829
Value *a2 = boxed(ctx, emit_expr(ctx, args[2]));
3832-
Value *mdargs[4] = {
3830+
Value *mdargs[3] = {
38333831
/*argdata*/a1,
38343832
/*code*/a2,
3835-
/*module*/literal_pointer_val(ctx, (jl_value_t*)ctx.module),
3836-
/*isstaged*/literal_pointer_val(ctx, args[3])
3833+
/*module*/literal_pointer_val(ctx, (jl_value_t*)ctx.module)
38373834
};
38383835
ctx.builder.CreateCall(prepare_call(jlmethod_func), makeArrayRef(mdargs));
38393836
return ghostValue(jl_void_type);
@@ -6377,7 +6374,6 @@ static void init_julia_llvm_env(Module *m)
63776374
mdargs.push_back(T_prjlvalue);
63786375
mdargs.push_back(T_prjlvalue);
63796376
mdargs.push_back(T_pjlvalue);
6380-
mdargs.push_back(T_pjlvalue);
63816377
jlmethod_func =
63826378
Function::Create(FunctionType::get(T_void, mdargs, false),
63836379
Function::ExternalLinkage,

src/dump.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1439,7 +1439,7 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_
14391439
m->unspecialized = (jl_method_instance_t*)jl_deserialize_value(s, (jl_value_t**)&m->unspecialized);
14401440
if (m->unspecialized)
14411441
jl_gc_wb(m, m->unspecialized);
1442-
m->generator = (jl_method_instance_t*)jl_deserialize_value(s, (jl_value_t**)&m->generator);
1442+
m->generator = jl_deserialize_value(s, (jl_value_t**)&m->generator);
14431443
if (m->generator)
14441444
jl_gc_wb(m, m->generator);
14451445
m->invokes.unknown = jl_deserialize_value(s, (jl_value_t**)&m->invokes);

src/interpreter.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s)
322322
JL_GC_PUSH2(&atypes, &meth);
323323
atypes = eval(args[1], s);
324324
meth = eval(args[2], s);
325-
jl_method_def((jl_svec_t*)atypes, (jl_code_info_t*)meth, s->module, args[3]);
325+
jl_method_def((jl_svec_t*)atypes, (jl_code_info_t*)meth, s->module);
326326
JL_GC_POP();
327327
return jl_nothing;
328328
}

src/jltypes.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -2061,7 +2061,7 @@ void jl_init_types(void)
20612061
jl_simplevector_type,
20622062
jl_any_type,
20632063
jl_any_type, // jl_method_instance_type
2064-
jl_any_type, // jl_method_instance_type
2064+
jl_any_type,
20652065
jl_array_any_type,
20662066
jl_any_type,
20672067
jl_int32_type,
@@ -2174,7 +2174,6 @@ void jl_init_types(void)
21742174
#endif
21752175
jl_svecset(jl_methtable_type->types, 8, jl_int32_type); // uint32_t
21762176
jl_svecset(jl_method_type->types, 10, jl_method_instance_type);
2177-
jl_svecset(jl_method_type->types, 11, jl_method_instance_type);
21782177
jl_svecset(jl_method_instance_type->types, 12, jl_voidpointer_type);
21792178
jl_svecset(jl_method_instance_type->types, 13, jl_voidpointer_type);
21802179
jl_svecset(jl_method_instance_type->types, 14, jl_voidpointer_type);

0 commit comments

Comments
 (0)