diff --git a/base/boot.jl b/base/boot.jl index 0e8cc513b89d00..8c0069574d6d67 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -124,6 +124,7 @@ export Any, DataType, Vararg, ANY, NTuple, Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, Void, SimpleVector, AbstractArray, DenseArray, + Banana, # special objects Box, Function, Builtin, IntrinsicFunction, LambdaInfo, Method, MethodTable, Module, Symbol, Task, Array, WeakRef, @@ -301,6 +302,10 @@ TypeConstructor(p::ANY, t::ANY) = ccall(:jl_new_type_constructor, Any, (Any, Any Void() = nothing +immutable Banana{T} + value::T +end + Expr(args::ANY...) = _expr(args...) _new(typ::Symbol, argty::Symbol) = eval(:((::Type{$typ})(n::$argty) = $(Expr(:new, typ, :n)))) diff --git a/src/builtins.c b/src/builtins.c index d75442e9ee099a..22a75a804d1df2 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1146,6 +1146,7 @@ void jl_init_primitives(void) add_builtin("TypeConstructor", (jl_value_t*)jl_typector_type); add_builtin("Tuple", (jl_value_t*)jl_anytuple_type); add_builtin("NTuple", (jl_value_t*)jl_ntuple_type); + add_builtin("Banana", (jl_value_t*)jl_banana_type); add_builtin("Vararg", (jl_value_t*)jl_vararg_type); add_builtin("Type", (jl_value_t*)jl_type_type); add_builtin("DataType", (jl_value_t*)jl_datatype_type); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index d4e1cdfcda5350..76c729f145c2f5 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -898,6 +898,12 @@ static Value *julia_binding_gv(jl_binding_t *b) return julia_binding_gv(bv); } +static int is_banana_type(jl_value_t* t) +{ + assert(jl_is_datatype(t)); + return ((jl_datatype_t*)(t))->name == ((jl_datatype_t*)(jl_banana_type))->name; +} + // --- mapping between julia and llvm types --- static Type *julia_struct_to_llvm(jl_value_t *jt, bool *isboxed); @@ -988,13 +994,17 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, bool *isboxed) latypes.push_back(lty); } if (!isTuple) { - structdecl->setBody(latypes); + if (is_banana_type(jt)) + // Banana types are pre-peeled in LLVM + jst->struct_decl = latypes[0]; + else + structdecl->setBody(latypes); } else { if (isvector && lasttype != T_int1 && !type_is_ghost(lasttype)) { // TODO: currently we get LLVM assertion failures for other vector sizes - bool validVectorSize = (ntypes == 2 || ntypes == 4 || ntypes == 6); - if (0 && lasttype->isSingleValueType() && !lasttype->isVectorTy() && validVectorSize) // currently disabled due to load/store alignment issues + bool validVectorSize = (ntypes == 2 || ntypes == 4 || ntypes == 8); + if (lasttype->isSingleValueType() && !lasttype->isVectorTy() && validVectorSize && is_banana_type(jl_svecref(jst->types,0))) jst->struct_decl = VectorType::get(lasttype, ntypes); else jst->struct_decl = ArrayType::get(lasttype, ntypes); @@ -1656,8 +1666,13 @@ static jl_cgval_t emit_getfield_knownidx(const jl_cgval_t &strct, unsigned idx, return typed_load(addr, NULL, jfty, ctx, tbaa_immut); } else { - assert(strct.V->getType()->isVectorTy()); - fldv = builder.CreateExtractElement(strct.V, ConstantInt::get(T_int32, idx)); + if ( strct.V->getType()->isVectorTy() ) { + fldv = builder.CreateExtractElement(strct.V, ConstantInt::get(T_int32, idx)); + } else { + // Banana types are pre-peeled in LLVM. + assert( strct.V->getType()->isSingleValueType() ); + fldv = strct.V; + } if (jfty == (jl_value_t*)jl_bool_type) { fldv = builder.CreateTrunc(fldv, T_int1); } @@ -2202,8 +2217,13 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg fval = builder.CreateZExt(fval, T_int8); if (lt->isVectorTy()) strct = builder.CreateInsertElement(strct, fval, ConstantInt::get(T_int32,idx)); - else + else if (lt->isAggregateType()) strct = builder.CreateInsertValue(strct, fval, ArrayRef(&idx,1)); + else { + // Must be a banana type, which is pre-peeled in LLVM. + assert(is_banana_type(ty)); + strct = fval; + } } idx++; } diff --git a/src/init.c b/src/init.c index ffff1b1962cbca..176319bc192f57 100644 --- a/src/init.c +++ b/src/init.c @@ -838,6 +838,7 @@ void jl_get_builtin_hooks(void) jl_utf8_string_type = (jl_datatype_t*)core("UTF8String"); jl_symbolnode_type = (jl_datatype_t*)core("SymbolNode"); jl_weakref_type = (jl_datatype_t*)core("WeakRef"); + jl_banana_type = (jl_datatype_t*)core("Banana"); jl_array_uint8_type = jl_apply_type((jl_value_t*)jl_array_type, jl_svec2(jl_uint8_type, jl_box_long(1))); diff --git a/src/jltypes.c b/src/jltypes.c index d591bb899e29bf..3ef74c0c0e3bef 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -31,6 +31,7 @@ jl_typename_t *jl_tuple_typename; jl_tupletype_t *jl_anytuple_type; jl_datatype_t *jl_ntuple_type; jl_typename_t *jl_ntuple_typename; +jl_datatype_t *jl_banana_type; jl_datatype_t *jl_vararg_type; jl_datatype_t *jl_tvar_type; jl_datatype_t *jl_uniontype_type; diff --git a/src/julia.h b/src/julia.h index 2d94fb2aeba57d..f8069525f67b2e 100644 --- a/src/julia.h +++ b/src/julia.h @@ -529,6 +529,7 @@ extern JL_DLLEXPORT jl_datatype_t *jl_symbol_type; extern JL_DLLEXPORT jl_datatype_t *jl_gensym_type; extern JL_DLLEXPORT jl_datatype_t *jl_simplevector_type; extern JL_DLLEXPORT jl_typename_t *jl_tuple_typename; +extern JL_DLLEXPORT jl_datatype_t *jl_banana_type; extern JL_DLLEXPORT jl_datatype_t *jl_anytuple_type; #define jl_tuple_type jl_anytuple_type extern JL_DLLEXPORT jl_datatype_t *jl_ntuple_type;