From d15557baee85db0c8d981a777dffff1368595af7 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 3 Feb 2017 23:57:32 -0500 Subject: [PATCH] 0.6 Compatibility --- deps/build.jl | 2 +- src/Cxx.jl | 3 + src/CxxREPL/replpane.jl | 2 +- src/bootstrap.cpp | 17 +++-- src/clangwrapper.jl | 11 +-- src/codegen.jl | 144 ++++++++++++++++++++-------------------- src/cxxmacro.jl | 5 +- src/cxxstr.jl | 99 ++++++++++++++++++--------- src/initialization.jl | 6 +- src/show.jl | 4 +- src/std.jl | 8 ++- src/typetranslation.jl | 25 ++++--- test/cxxstr.jl | 2 +- test/misc.jl | 5 +- 14 files changed, 193 insertions(+), 140 deletions(-) diff --git a/deps/build.jl b/deps/build.jl index ea3179c9..8ec38d5a 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -26,7 +26,7 @@ println("Tuning for julia installation at $BASE_JULIA_BIN with sources possibly llvm_path = is_apple() ? "libLLVM" : "libLLVM-$(Base.libllvm_version)" llvm_lib_path = Libdl.dlpath(llvm_path) -old_cxx_abi = searchindex(open(read, llvm_lib_path),"_ZN4llvm3sys16getProcessTripleEv".data,0) != 0 +old_cxx_abi = searchindex(open(read, llvm_lib_path),Vector{UInt8}("_ZN4llvm3sys16getProcessTripleEv"),0) != 0 old_cxx_abi && (ENV["OLD_CXX_ABI"] = "1") llvm_config_path = joinpath(BASE_JULIA_BIN,"..","tools","llvm-config") diff --git a/src/Cxx.jl b/src/Cxx.jl index b28f600d..3ec0f5fc 100644 --- a/src/Cxx.jl +++ b/src/Cxx.jl @@ -147,6 +147,9 @@ include(pathfile) using Base.Meta using Core: svec +import Compat +using Compat.TypeUtils + export cast, @cxx_str, @cxx_mstr, @icxx_str, @icxx_mstr, @cxxt_str, @cxx, @cxxnew, @jpcpp_str, @exception, @cxxm, diff --git a/src/CxxREPL/replpane.jl b/src/CxxREPL/replpane.jl index fc966fa9..3d3bad94 100644 --- a/src/CxxREPL/replpane.jl +++ b/src/CxxREPL/replpane.jl @@ -93,7 +93,7 @@ module CxxREPL end function isTopLevelExpression(C,data) - @assert data[end] == '\0' + @assert Int(data[end]) == 0 if contains(data,":=") return false end diff --git a/src/bootstrap.cpp b/src/bootstrap.cpp index 365ff2e3..4daa3707 100644 --- a/src/bootstrap.cpp +++ b/src/bootstrap.cpp @@ -554,7 +554,8 @@ static Function *CloneFunctionAndAdjust(C, Function *F, FunctionType *FTy, const clang::CodeGen::CGFunctionInfo &FI, clang::FunctionDecl *FD, bool specsig, bool firstIsEnv, - bool *needsbox, void **juliatypes) { + bool *needsbox, void *jl_retty, + void **juliatypes) { std::vector ArgTypes; llvm::ValueToValueMapTy VMap; @@ -686,8 +687,10 @@ static Function *CloneFunctionAndAdjust(C, Function *F, FunctionType *FTy, Cxx->CGF->Builder.SetInsertPoint(builder.GetInsertBlock(), builder.GetInsertPoint()); - if (Call->getType()->isPointerTy() && - cast(Call->getType())->getElementType()->isAggregateType()) { + bool isboxed = false; + Type *retty = f_julia_type_to_llvm(jl_retty, &isboxed); + if (isboxed || (Call->getType()->isPointerTy() && + cast(Call->getType())->getElementType()->isAggregateType())) { Cxx->CGF->EmitAggregateCopy(Cxx->CGF->ReturnValue, #ifdef LLVM38 clang::CodeGen::Address(Call,clang::CharUnits::fromQuantity(sizeof(void*))), @@ -803,7 +806,7 @@ JL_DLLEXPORT void *DeleteUnusedArguments(llvm::Function *F, uint64_t *dtodelete, } -JL_DLLEXPORT void ReplaceFunctionForDecl(C,clang::FunctionDecl *D, llvm::Function *F, bool DoInline, bool specsig, bool firstIsEnv, bool *needsbox, void **juliatypes) +JL_DLLEXPORT void ReplaceFunctionForDecl(C,clang::FunctionDecl *D, llvm::Function *F, bool DoInline, bool specsig, bool firstIsEnv, bool *needsbox, void *retty, void **juliatypes) { const clang::CodeGen::CGFunctionInfo &FI = Cxx->CGM->getTypes().arrangeGlobalDeclaration(D); llvm::FunctionType *Ty = Cxx->CGM->getTypes().GetFunctionType(FI); @@ -815,7 +818,7 @@ JL_DLLEXPORT void ReplaceFunctionForDecl(C,clang::FunctionDecl *D, llvm::Functio llvm::ValueToValueMapTy VMap; llvm::ClonedCodeInfo CCI; - llvm::Function *NF = CloneFunctionAndAdjust(Cxx,F,Ty,true,&CCI,FI,D,specsig,firstIsEnv,needsbox,juliatypes); + llvm::Function *NF = CloneFunctionAndAdjust(Cxx,F,Ty,true,&CCI,FI,D,specsig,firstIsEnv,needsbox,retty,juliatypes); // TODO: Ideally we would delete the cloned function // once we're done with the inlineing, but clang delays // emitting some functions (e.g. constructors) until @@ -1316,8 +1319,8 @@ static void set_default_clang_options(C, bool CCompiler, const char *Triple, con Cxx->CI->getLangOpts().CPlusPlus = 1; Cxx->CI->getLangOpts().CPlusPlus11 = 1; Cxx->CI->getLangOpts().CPlusPlus14 = 1; - Cxx->CI->getLangOpts().RTTI = 0; - Cxx->CI->getLangOpts().RTTIData = 0; + Cxx->CI->getLangOpts().RTTI = 1; + Cxx->CI->getLangOpts().RTTIData = 1; Cxx->CI->getLangOpts().Exceptions = 1; // exception handling Cxx->CI->getLangOpts().ObjCExceptions = 1; // Objective-C exceptions Cxx->CI->getLangOpts().CXXExceptions = 1; // C++ exceptions diff --git a/src/clangwrapper.jl b/src/clangwrapper.jl index 9f62fd0b..30730f3c 100644 --- a/src/clangwrapper.jl +++ b/src/clangwrapper.jl @@ -375,11 +375,12 @@ AddDeclToDeclCtx(DC::pcpp"clang::DeclContext",D::pcpp"clang::Decl") = ccall((:AddDeclToDeclCtx,libcxxffi),Void,(Ptr{Void},Ptr{Void}),DC,D) function ReplaceFunctionForDecl(C,sv::pcpp"clang::FunctionDecl",f::pcpp"llvm::Function"; - DoInline = true, specsig = false, FirstIsEnv = false, NeedsBoxed = C_NULL, jts = C_NULL) + DoInline = true, specsig = false, FirstIsEnv = false, NeedsBoxed = C_NULL, + retty = Any, jts = C_NULL) @assert sv != C_NULL ccall((:ReplaceFunctionForDecl,libcxxffi),Void, - (Ptr{ClangCompiler},Ptr{Void},Ptr{Void},Bool,Bool,Bool,Ptr{Bool},Ptr{Void}), - &C,sv,f,DoInline,specsig,FirstIsEnv,NeedsBoxed,jts) + (Ptr{ClangCompiler},Ptr{Void},Ptr{Void},Bool,Bool,Bool,Ptr{Bool},Any,Ptr{Void}), + &C,sv,f,DoInline,specsig,FirstIsEnv,NeedsBoxed,retty,jts) end function ReplaceFunctionForDecl(C,sv::pcpp"clang::CXXMethodDecl",f::pcpp"llvm::Function"; kwargs...) @@ -535,7 +536,7 @@ CreateFunctionTemplateDecl(C, DC::pcpp"clang::DeclContext", Params, FD) = function getSpecializations(FTD::pcpp"clang::FunctionTemplateDecl") v = ccall((:newFDVector,libcxxffi),Ptr{Void},()) ccall((:getSpecializations,libcxxffi),Void,(Ptr{Void},Ptr{Void}),FTD,v) - ret = Array(pcpp"clang::FunctionDecl",ccall((:getFDVectorSize,libcxxffi),Csize_t,(Ptr{Void},),v)) + ret = Array{pcpp"clang::FunctionDecl"}(ccall((:getFDVectorSize,libcxxffi),Csize_t,(Ptr{Void},),v)) ccall((:copyFDVector,libcxxffi),Void,(Ptr{Void},Ptr{Void}),ret,v); ccall((:deleteFDVector,libcxxffi),Void,(Ptr{Void},),v) ret @@ -678,7 +679,7 @@ getParent(CxxMD::pcpp"clang::CXXMethodDecl") = pcpp"clang::CXXRecordDecl"(ccall( decouple_pch(C) = ccall((:decouple_pch,libcxxffi),Void,(Ptr{ClangCompiler},),&C) function ParseParameterList(C,nparams) - params = Array(Ptr{Void},nparams) + params = Array{Ptr{Void}}(nparams) ccall((:ParseParameterList,Cxx.libcxxffi),Void, (Ptr{Cxx.ClangCompiler},Ptr{Void},Csize_t),&C,params,length(params)) [pcpp"clang::ParmVarDecl"(p) for p in params] diff --git a/src/codegen.jl b/src/codegen.jl index 1d81d345..a994bd6a 100644 --- a/src/codegen.jl +++ b/src/codegen.jl @@ -359,7 +359,7 @@ end # # Returns the list of processed arguments function llvmargs(C, builder, f, argt) - args = Array(pcpp"llvm::Value", length(argt)) + args = Array{pcpp"llvm::Value"}(length(argt)) for i in 1:length(argt) t = argt[i] args[i] = pcpp"llvm::Value"(ccall( @@ -373,7 +373,8 @@ function llvmargs(C, builder, f, argt) args end -cxxtransform(T,ex) = (T,ex) +cxxtransform(T,ex) = (T, ex) +cxxtransform(::Type{String},ex) = (Ptr{UInt8},:(pointer($ex))) function buildargexprs(C, argt; derefval = true) callargs = pcpp"clang::Expr"[] @@ -439,74 +440,6 @@ function check_args(argt,f) end end - -# -# Code generation for value references (basically everything that's not a call). -# Syntactically, these are of the form -# -# - @cxx foo -# - @cxx foo::bar -# - @cxx foo->bar -# - -# Handle member references, i.e. syntax of the form `@cxx foo->bar` -@generated function cxxmemref(CT::CxxInstance, expr, args...) - C = instance(CT) - this = args[1] - check_args([this], expr) - isaddrof = false - if expr <: CppAddr - expr = expr.parameters[1] - isaddrof = true - end - exprs, pvds = buildargexprs(C,[this]) - me = BuildMemberReference(C, exprs[1], cpptype(C, this), this <: CppPtr, - expr.parameters[1]) - isaddrof && (me = CreateAddrOfExpr(C,me)) - emitRefExpr(C, me, pvds[1], this) -end - -# Handle all other references. This is more complicated than the above for two -# reasons. -# a) We can reference types (e.g. `@cxx int`) -# b) Clang cares about how the reference was qualified, so we need to deal with -# cxxscopes. -@generated function cxxref(CT,expr) - C = instance(CT) - isaddrof = false - if expr <: CppAddr - expr = expr.parameters[1] - isaddrof = true - end - - cxxscope = newCXXScopeSpec(C) - d = declfornns(C,expr,cxxscope) - @assert d != C_NULL - - # If this is a typedef or something we'll try to get the primary one - primary_decl = to_decl(primary_ctx(toctx(d))) - if primary_decl != C_NULL - d = primary_decl - end - - if isaValueDecl(d) - expr = dre = CreateDeclRefExpr(C, d; - islvalue = isaVarDecl(d) || - (isaFunctionDecl(d) && !isaCXXMethodDecl(d)), - cxxscope=cxxscope) - - deleteCXXScopeSpec(cxxscope) - - if isaddrof - expr = CreateAddrOfExpr(C,dre) - end - - return emitRefExpr(C, expr) - else - return :( $(juliatype(QualType(typeForDecl(d)))) ) - end -end - function emitRefExpr(C, expr, pvd = nothing, ct = nothing) # Ask clang what the type is we're expecting rt = BuildDecltypeType(C,expr) @@ -688,10 +621,10 @@ end function EmitExpr(C,ce,nE,ctce, argt, pvds, rett = Void; kwargs...) builder = irbuilder(C) argt = Type[argt...] - map!(argt) do x + map!(argt, argt) do x (isCxxEquivalentType(x) || x <: CxxBuiltinTs) ? x : Ref{x} end - llvmargt = [argt...] + llvmargt = Type[argt...] issret = false rslot = C_NULL rt = C_NULL @@ -825,6 +758,73 @@ function createReturn(C,builder,f,argt,llvmargt,llvmrt,rett,rt,ret,state; argidx end end +# +# Code generation for value references (basically everything that's not a call). +# Syntactically, these are of the form +# +# - @cxx foo +# - @cxx foo::bar +# - @cxx foo->bar +# + +# Handle member references, i.e. syntax of the form `@cxx foo->bar` +@generated function cxxmemref(CT::CxxInstance, expr, args...) + C = instance(CT) + this = args[1] + check_args([this], expr) + isaddrof = false + if expr <: CppAddr + expr = expr.parameters[1] + isaddrof = true + end + exprs, pvds = buildargexprs(C,[this]) + me = BuildMemberReference(C, exprs[1], cpptype(C, this), this <: CppPtr, + expr.parameters[1]) + isaddrof && (me = CreateAddrOfExpr(C,me)) + emitRefExpr(C, me, pvds[1], this) +end + +# Handle all other references. This is more complicated than the above for two +# reasons. +# a) We can reference types (e.g. `@cxx int`) +# b) Clang cares about how the reference was qualified, so we need to deal with +# cxxscopes. +@generated function cxxref(CT,expr) + C = instance(CT) + isaddrof = false + if expr <: CppAddr + expr = expr.parameters[1] + isaddrof = true + end + + cxxscope = newCXXScopeSpec(C) + d = declfornns(C,expr,cxxscope) + @assert d != C_NULL + + # If this is a typedef or something we'll try to get the primary one + primary_decl = to_decl(primary_ctx(toctx(d))) + if primary_decl != C_NULL + d = primary_decl + end + + if isaValueDecl(d) + expr = dre = CreateDeclRefExpr(C, d; + islvalue = isaVarDecl(d) || + (isaFunctionDecl(d) && !isaCXXMethodDecl(d)), + cxxscope=cxxscope) + + deleteCXXScopeSpec(cxxscope) + + if isaddrof + expr = CreateAddrOfExpr(C,dre) + end + + return emitRefExpr(C, expr) + else + return :( $(juliatype(QualType(typeForDecl(d)))) ) + end +end + # And finally the staged functions to drive the call logic above @generated function cppcall(CT::CxxInstance, expr, args...) _cppcall(CT, expr, false, false, args) diff --git a/src/cxxmacro.jl b/src/cxxmacro.jl index 15f140fd..ece6ae05 100644 --- a/src/cxxmacro.jl +++ b/src/cxxmacro.jl @@ -212,7 +212,7 @@ function get_llvmf_for_FD(C,jf,FD) TT = Tuple{typeof(jf), map(x->x[2],extract_params(C,FD))...} needsboxed = Bool[!isbits(x) for x in TT.parameters] specsig = length(needsboxed) == 0 || !reduce(&,needsboxed) - f = pcpp"llvm::Function"(ccall(:jl_get_llvmf, Ptr{Void}, (Any,Bool,Bool), TT, false,true)) + f = get_llvmf_decl(TT) @assert f != C_NULL needsboxed, specsig, Tuple{TT.parameters[2:end]...}, f end @@ -234,6 +234,7 @@ macro cxxm(str,expr) NeedsBoxed, specsig, TT, llvmf = Cxx.get_llvmf_for_FD(Cxx.instance(__current_compiler__),$f,$FD) Cxx.ReplaceFunctionForDecl(Cxx.instance(__current_compiler__), $FD,llvmf, - DoInline = false, specsig = specsig, NeedsBoxed = NeedsBoxed, jts = Any[TT.parameters...]) + DoInline = false, specsig = specsig, NeedsBoxed = NeedsBoxed, + retty = $RT, jts = Any[TT.parameters...]) end) end diff --git a/src/cxxstr.jl b/src/cxxstr.jl index 7354d7f4..fa94e78f 100644 --- a/src/cxxstr.jl +++ b/src/cxxstr.jl @@ -43,7 +43,7 @@ function ssv(C,e::ANY,ctx,varnum,sourcebuf,typeargs=Dict{Void,Void}()) name = string(iscc ? "__juliaglobalvar" : "var",varnum) sv = CreateTypeDefDecl(C,ctx,name,QT) elseif isa(e,TypeVar) - str = takebuf_string(sourcebuf) + str = String(take!(sourcebuf)) name = string(iscc ? "__juliaglobalvar" : "var",varnum) write(sourcebuf, replace(str, string(iscc ? "__juliavar" : "__julia::var",varnum), name)) sv = ActOnTypeParameterParserScope(C,name,varnum) @@ -84,6 +84,41 @@ end const lambda_roots = Function[] +function latest_world_return_type(tt) + if VERSION >= v"0.6-" + params = Core.Inference.InferenceParams(typemax(UInt)) + rt = Union{} + for m in Base._methods_by_ftype(tt, -1, params.world) + ty = Core.Inference.typeinf_type(m[3], m[1], m[2], true, params) + ty === nothing && return Any + rt = Core.Inference.tmerge(rt, ty) + rt === Any && break + end + return rt + else + linfo = tt.parameters[1].name.mt.defs.func + (tree, retty) = Core.Inference.typeinf(linfo,tt,svec()) + return retty + end +end + +function get_llvmf_decl(tt) + # We can emit a direct llvm-level reference to this + if VERSION > v"0.6-" + params = Base.CodegenParams() + world = typemax(UInt) + (ti, env, meth) = Base._methods_by_ftype(tt, 1, world)[1] + #(ti, env) = ccall(:jl_match_method, Any, (Any, Any), tt, meth.sig)::SimpleVector + meth = Base.func_for_method_checked(meth, tt) + linfo = ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any, UInt), meth, tt, env, world) + f = pcpp"llvm::Function"(ccall(:jl_get_llvmf_decl, Ptr{Void}, (Any, UInt, Bool, Base.CodegenParams), linfo, world, false, params)) + else + f = pcpp"llvm::Function"(ccall(:jl_get_llvmf, Ptr{Void}, (Any,Bool,Bool), + tt, false, true)) + end + f +end + # TODO: It would be good if this could be invoked as a callback when Clang instantiates # a template. function InstantiateSpecializationsForType(C, DC, LambdaT) @@ -125,8 +160,8 @@ function InstantiateSpecializationsForType(C, DC, LambdaT) end linfo = F.func - ST = Tuple{LambdaT, specTypes...} - (tree, ty) = Core.Inference.typeinf(linfo,ST,svec()) + tt = Tuple{LambdaT, specTypes...} + ty = latest_world_return_type(tt) T = ty if T === Union{} @@ -135,9 +170,8 @@ function InstantiateSpecializationsForType(C, DC, LambdaT) if isa(T,Union) || T.abstract error("Inferred Union or abstract type $T for expression $F") end + f = get_llvmf_decl(tt) - # We can emit a direct llvm-level reference to this - f = pcpp"llvm::Function"(ccall(:jl_get_llvmf, Ptr{Void}, (Any,Bool,Bool), ST, false, true)) @assert f != C_NULL # Create a Clang function Decl to represent this julia function @@ -181,7 +215,7 @@ end function ArgCleanup(C,e,sv) if isa(sv,pcpp"clang::FunctionDecl") tt = Tuple{typeof(e)} - f = pcpp"llvm::Function"(ccall(:jl_get_llvmf, Ptr{Void}, (Any,Bool,Bool), tt, false, true)) + f = get_llvmf_decl(tt) @assert f != C_NULL ReplaceFunctionForDecl(C,sv,f) elseif !isa(e,Type) && !isa(e,TypeVar) @@ -198,7 +232,7 @@ function ArgCleanup(C,e,sv) end end -const sourcebuffers = Array(Tuple{AbstractString,Symbol,Int,Int},0) +const sourcebuffers = Array{Tuple{AbstractString,Symbol,Int,Int}}(0) immutable SourceBuf{id}; end sourceid{id}(::Type{SourceBuf{id}}) = id @@ -339,26 +373,6 @@ function CallDNE(C, dne, argt; kwargs...) EmitExpr(C,ce,C_NULL,C_NULL,argt,pvds; kwargs...) end -@generated function cxxstr_impl(CT, sourcebuf, args...) - C = instance(CT) - id = sourceid(sourcebuf) - buf, filename, line, col = sourcebuffers[id] - - FD, llvmargs, argidxs, symargs = CreateFunctionWithBody(C,buf, args...; filename = filename, line = line, col = col) - EmitTopLevelDecl(C,FD) - - for T in args - if haskey(MappedTypes, T) - InstantiateSpecializationsForType(C, toctx(translation_unit(C)), T) - end - end - - dne = CreateDeclRefExpr(C,FD) - argt = tuple(llvmargs...) - expr = CallDNE(C,dne,argt; argidxs = argidxs, symargs = symargs) - expr -end - # # Generate a virtual name for a file in the same directory as `filename`. # This will be the virtual filename for clang to refer to the source snippet by. @@ -404,7 +418,7 @@ function collect_exprs(str) push!(exprs, (expr, isexpr)) i += 1 end - exprs, takebuf_string(sourcebuf) + exprs, String(take!(sourcebuf)) end collect_icxx(compiler, s, icxxs) = s @@ -626,8 +640,8 @@ function process_cxx_string(str,global_scope = true,type_name = false,filename=S push!(postparse.args,:(Cxx.RealizeTemplates($instance,$ctx,$s))) startvarnum += 1 end - parsecode = filename == "" ? :( cxxparse($instance,Cxx.adjust_source($instance,takebuf_string($sourcebuf)),$type_name) ) : - :( Cxx.ParseVirtual($instance, Cxx.adjust_source($instance,takebuf_string($sourcebuf)), + parsecode = filename == "" ? :( cxxparse($instance,Cxx.adjust_source($instance,String(take!($sourcebuf))),$type_name) ) : + :( Cxx.ParseVirtual($instance, Cxx.adjust_source($instance,String(take!($sourcebuf))), $( VirtualFileName(filename) ), $( quot(filename) ), $( line ), @@ -668,15 +682,36 @@ function process_cxx_string(str,global_scope = true,type_name = false,filename=S else if type_name Expr(:call,Cxx.CxxType,:__current_compiler__, - CxxTypeName{Symbol(takebuf_string(sourcebuf))}(),CodeLoc{filename,line,col}(),exprs...) + CxxTypeName{Symbol(String(take!(sourcebuf)))}(),CodeLoc{filename,line,col}(),exprs...) else - push!(sourcebuffers,(takebuf_string(sourcebuf),filename,line,col)) + push!(sourcebuffers,(String(take!(sourcebuf)),filename,line,col)) id = length(sourcebuffers) build_icxx_expr(id, exprs, isexprs, icxxs, compiler, cxxstr_impl) end end end +@generated function cxxstr_impl(CT, sourcebuf, args...) + C = instance(CT) + id = sourceid(sourcebuf) + buf, filename, line, col = sourcebuffers[id] + + FD, llvmargs, argidxs, symargs = CreateFunctionWithBody(C,buf, args...; filename = filename, line = line, col = col) + EmitTopLevelDecl(C,FD) + + for T in args + if haskey(MappedTypes, T) + InstantiateSpecializationsForType(C, toctx(translation_unit(C)), T) + end + end + + dne = CreateDeclRefExpr(C,FD) + argt = tuple(llvmargs...) + expr = CallDNE(C,dne,argt; argidxs = argidxs, symargs = symargs) + expr +end + + macro cxx_str(str,args...) esc(process_cxx_string(str,true,false,args...)) end diff --git a/src/initialization.jl b/src/initialization.jl index cd6c3349..5ce3c402 100644 --- a/src/initialization.jl +++ b/src/initialization.jl @@ -24,7 +24,7 @@ init_libcxxffi() function setup_instance(UsePCH = C_NULL; makeCCompiler=false, target = C_NULL, CPU = C_NULL, useDefaultCxxABI=true) - x = Array(ClangCompiler,1) + x = Array{ClangCompiler}(1) sysroot = @static is_apple() ? strip(readstring(`xcodebuild -version -sdk macosx Path`)) : C_NULL EmitPCH = true ccall((:init_clang_instance,libcxxffi),Void, @@ -36,7 +36,7 @@ function setup_instance(UsePCH = C_NULL; makeCCompiler=false, target = C_NULL, C end function setup_instance_from_inovcation(invocation) - x = Array(ClangCompiler,1) + x = Array{ClangCompiler}(1) ccall((:init_clang_instance_from_invocation,libcxxffi),Void, (Ptr{Void},Ptr{Void}), x, invocation) x[1] @@ -60,7 +60,7 @@ function RunGlobalConstructors(C) p = convert(Ptr{Void}, CollectGlobalConstructors(C)) # If p is NULL it means we have no constructors to run if p != C_NULL - eval(:(llvmcall($p,Void,Tuple{}))) + eval(:(let f()=llvmcall($p,Void,Tuple{}); f(); end)) end end diff --git a/src/show.jl b/src/show.jl index 02b57288..7faff428 100644 --- a/src/show.jl +++ b/src/show.jl @@ -1,4 +1,4 @@ -Base.bytestring(str::vcpp"llvm::StringRef") = Cxx.unsafe_string(icxx"$str.data();",icxx"$str.size();") +Base.unsafe_string(str::vcpp"llvm::StringRef") = Cxx.unsafe_string(icxx"$str.data();",icxx"$str.size();") typename(QT) = Cxx.getTypeNameAsString(QT) function typename{T<:Cxx.CxxQualType}(::Type{T}) C = Cxx.instance(Cxx.__default_compiler__) @@ -27,7 +27,7 @@ end if (field->getAccess() != clang::AS_public) continue; $:(begin - fieldname = bytestring(icxx"return field->getName();") + fieldname = unsafe_string(icxx"return field->getName();") showexpr = Expr(:macrocall,Symbol("@icxx_str")," auto &r = \$x.$fieldname; return r; diff --git a/src/std.jl b/src/std.jl index cfe9fdb5..6f6f1adc 100644 --- a/src/std.jl +++ b/src/std.jl @@ -18,7 +18,12 @@ String(str::Union{StdString,StdStringR}) = unsafe_string(str) import Base: showerror import Cxx: CppValue -for T in Cxx.CxxBuiltinTypes.types +if !isdefined(Core, :UnionAll) + uniontypes(U) = U.types +else + const uniontypes = Base.uniontypes +end +for T in uniontypes(Cxx.CxxBuiltinTypes) @eval @exception function showerror(io::IO, e::$(T.parameters[1])) print(io, e) end @@ -71,4 +76,3 @@ function Base.show{T}(io::IO, end #Cxx.cpptype{T<:Union{ASCIIString,UTF8String}}(C,::Type{T}) = Cxx.cpptype(C,Ptr{UInt8}) -Cxx.cxxtransform(::Type{String},ex) = (Ptr{UInt8},:(pointer($ex))) diff --git a/src/typetranslation.jl b/src/typetranslation.jl index 8c9c5992..99648001 100644 --- a/src/typetranslation.jl +++ b/src/typetranslation.jl @@ -139,7 +139,7 @@ function specialize_template(C,cxxt::pcpp"clang::ClassTemplateDecl",targs) integralValues = zeros(UInt64,nparams) integralValuesPresent = zeros(UInt8,nparams) bitwidths = zeros(UInt32,nparams) - ts = Array(QualType,nparams) + ts = Array{QualType}(nparams) for (i,t) in enumerate(targs.parameters) if isa(t,Type) ts[i] = cpptype(C,t) @@ -164,7 +164,7 @@ function specialize_template_clang(C,cxxt::pcpp"clang::ClassTemplateDecl",targs) integralValues = zeros(UInt64,length(targs)) integralValuesPresent = zeros(UInt8,length(targs)) bitwidths = zeros(UInt32,length(targs)) - ts = Array(QualType,length(targs)) + ts = Array{QualType}(length(targs)) for (i,t) in enumerate(targs) if isa(t,pcpp"clang::Type") || isa(t,QualType) ts[i] = QualType(t) @@ -281,7 +281,7 @@ cpptype{f}(C,p::Type{CppFptr{f}}) = pointerTo(C,cpptype(C,f)) const MappedTypes = Dict{Type, QualType}() const InverseMappedTypes = Dict{QualType, Type}() function cpptype{T}(C,::Type{T}) - (!is(T,Union) && !T.abstract) || error("Cannot create C++ equivalent for abstract types") + (!(T === Union) && !T.abstract) || error("Cannot create C++ equivalent for abstract types") try if !haskey(MappedTypes, T) AnonClass = CreateAnonymousClass(C, translation_unit(C)) @@ -293,9 +293,9 @@ function cpptype{T}(C,::Type{T}) linfo = T.name.mt.defs.func sig = T.name.mt.defs.sig nargt = length(sig.parameters)-1 - tt = Tuple{T,(Any for _ in 1:nargt)...} - (tree, retty) = Core.Inference.typeinf(linfo,tt,svec()) - if isa(retty,Union) || retty.abstract + tt = Tuple{T, (Any for _ in 1:nargt)...} + retty = latest_world_return_type(tt) + if isa(retty,Union) || isabstract(retty) || retty === Union{} error("Inferred Union or abstract type $retty for return value of lambda") end # Ok, now we need to figure out what arguments we need to declare to C++. For that purpose, @@ -317,11 +317,11 @@ function cpptype{T}(C,::Type{T}) if isempty(TPs) Method = CreateCxxCallMethodDecl(C, AnonClass, makeFunctionType(C, cpptype(C, retty), argtQTs)) AddCallOpToClass(AnonClass, Method) - f = pcpp"llvm::Function"(ccall(:jl_get_llvmf, Ptr{Void}, (Any,Bool,Bool), tt, false, true)) + f = get_llvmf_decl(tt) @assert f != C_NULL FinalizeAnonClass(C, AnonClass) ReplaceFunctionForDecl(C, Method,f, DoInline = false, specsig = isbits(T) || isbits(retty), - NeedsBoxed = [false], FirstIsEnv = true, jts = Any[T]) + NeedsBoxed = [false], FirstIsEnv = true, retty = retty, jts = Any[T]) else Params = CreateTemplateParameterList(C,TPs) Method = CreateCxxCallMethodDecl(C, AnonClass, makeFunctionType(C, cpptype(C, retty), argtQTs)) @@ -461,6 +461,13 @@ function isCxxEquivalentType(t) (t <: Ref) || (t <: JLCppCast) end +if isdefined(Core, :UnionAll) +include_string(""" +extract_T(::Type{S}) where (T,S<:Cxx.CppValue{T,N} where N) = T +""") +else +extract_T(S) = S.parameters[1] +end function juliatype(t::QualType, quoted = false, typeargs = Dict{Int,Void}(); wrapvalue = true, valuecvr = true) @@ -481,7 +488,7 @@ function juliatype(t::QualType, quoted = false, typeargs = Dict{Int,Void}(); (tt.args[1] == :CppValue || tt.args[1] == :CppPtr || tt.args[1] == :CppRef) : (tt <: CppValue || tt <: CppPtr || tt <: CppRef) if isa(tt,Expr) ? tt.args[1] == :CppValue : tt <: CppValue - tt = isa(tt,Expr) ? tt.args[2] : tt.parameters[1] + tt = isa(tt,Expr) ? tt.args[2] : extract_T(tt) end xT = quoted ? :(CppPtr{$tt,$CVR}) : CppPtr{tt, CVR} # As a special case, if we're returning a jl_value_t *, interpret it diff --git a/test/cxxstr.jl b/test/cxxstr.jl index 17c2c302..1d032377 100644 --- a/test/cxxstr.jl +++ b/test/cxxstr.jl @@ -135,7 +135,7 @@ $:(push!(test103::Vector{Int32},icxx"return x;"); nothing); @test test103 == [5,5] # The same thing with two arguments -test2_103 = Array(Tuple{Int32,Int32},0) +test2_103 = Array{Tuple{Int32,Int32}}(0) cxx""" void foo2_103() { int x = 5; diff --git a/test/misc.jl b/test/misc.jl index 47958a69..c6358e09 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -186,7 +186,7 @@ try catch e buf = IOBuffer(); showerror(buf,e) - @assert takebuf_string(buf) == "20" + @assert String(take!(buf)) == "20" end cxx""" @@ -209,7 +209,7 @@ try catch e buf = IOBuffer(); showerror(buf,e) - @assert takebuf_string(buf) == "5" + @assert String(take!(buf)) == "5" end @@ -283,7 +283,6 @@ end @test icxx"foostruct{1,0}.Add1();" == 2 - @cxxm "struct foostruct foostruct::Add(struct foostruct other)" begin icxx"return foostruct{$this->x+$other.x,$this->y+$other.y};" end