Beispiel #1
0
static Value *runtime_sym_lookup(PointerType *funcptype, char *f_lib, char *f_name, jl_codectx_t *ctx)
{
    // in pseudo-code, this function emits the following:
    //   global uv_lib_t **libptrgv
    //   global void **llvmgv
    //   if (*llvmgv == NULL) {
    //       *llvmgv = jl_load_and_lookup(f_lib, f_name, libptrgv);
    //   }
    //   return (*llvmgv)
    Constant *initnul = ConstantPointerNull::get((PointerType*)T_pint8);

    uv_lib_t *libsym = NULL;
    bool runtime_lib = false;
    GlobalVariable *libptrgv;
#ifdef _OS_WINDOWS_
    if ((intptr_t)f_lib == 1) {
        libptrgv = prepare_global(jlexe_var);
        libsym = jl_exe_handle;
    }
    else if ((intptr_t)f_lib == 2) {
        libptrgv = prepare_global(jldll_var);
        libsym = jl_dl_handle;
    }
    else
#endif
    if (f_lib == NULL) {
        libptrgv = prepare_global(jlRTLD_DEFAULT_var);
        libsym = jl_RTLD_DEFAULT_handle;
    }
    else {
        runtime_lib = true;
        libptrgv = libMapGV[f_lib];
        if (libptrgv == NULL) {
            libptrgv = new GlobalVariable(*jl_Module, T_pint8,
               false, GlobalVariable::PrivateLinkage,
               initnul, f_lib);
            libMapGV[f_lib] = libptrgv;
            libsym = get_library(f_lib);
            assert(libsym != NULL);
#ifdef USE_MCJIT
            llvm_to_jl_value[libptrgv] = libsym;
#else
            *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv)) = libsym;
#endif
        }
    }
    if (libsym == NULL) {
#ifdef USE_MCJIT
        libsym = (uv_lib_t*)llvm_to_jl_value[libptrgv];
#else
        libsym = *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv));
#endif
    }

    assert(libsym != NULL);

    GlobalVariable *llvmgv = symMapGV[f_name];
    if (llvmgv == NULL) {
        // MCJIT forces this to have external linkage eventually, so we would clobber
        // the symbol of the actual function.
        std::string name = f_name;
        name = "ccall_" + name;
        llvmgv = new GlobalVariable(*jl_Module, T_pint8,
           false, GlobalVariable::PrivateLinkage,
           initnul, name);
        symMapGV[f_name] = llvmgv;
#ifdef USE_MCJIT
        llvm_to_jl_value[llvmgv] = jl_dlsym_e(libsym, f_name);
#else
        *((void**)jl_ExecutionEngine->getPointerToGlobal(llvmgv)) = jl_dlsym_e(libsym, f_name);
#endif
    }

    BasicBlock *dlsym_lookup = BasicBlock::Create(getGlobalContext(), "dlsym"),
               *ccall_bb = BasicBlock::Create(getGlobalContext(), "ccall");
    builder.CreateCondBr(builder.CreateICmpNE(builder.CreateLoad(llvmgv), initnul), ccall_bb, dlsym_lookup);

    ctx->f->getBasicBlockList().push_back(dlsym_lookup);
    builder.SetInsertPoint(dlsym_lookup);
    Value *libname;
    if (runtime_lib) {
        libname = builder.CreateGlobalStringPtr(f_lib);
    }
    else {
        libname = literal_static_pointer_val(f_lib, T_pint8);
    }
    Value *llvmf = builder.CreateCall3(prepare_call(jldlsym_func), libname, builder.CreateGlobalStringPtr(f_name), libptrgv);
    builder.CreateStore(llvmf, llvmgv);
    builder.CreateBr(ccall_bb);

    ctx->f->getBasicBlockList().push_back(ccall_bb);
    builder.SetInsertPoint(ccall_bb);
    llvmf = builder.CreateLoad(llvmgv);
    return builder.CreatePointerCast(llvmf,funcptype);
}
Beispiel #2
0
static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv,
                              jl_value_t *argex, bool addressOf,
                              int argn, jl_codectx_t *ctx,
                              bool *mightNeedTempSpace, bool *needStackRestore)
{
    Type *vt = jv->getType();
    if (ty == jl_pvalue_llvmt) {
        return boxed(jv,ctx);
    }
    else if (ty == vt && !addressOf) {
        return jv;
    }
    else if (vt != jl_pvalue_llvmt) {
        // argument value is unboxed
        if (addressOf) {
            if (ty->isPointerTy() && ty->getContainedType(0)==vt) {
                // pass the address of an alloca'd thing, not a box
                // since those are immutable.
                *needStackRestore = true;
                Value *slot = builder.CreateAlloca(vt);
                builder.CreateStore(jv, slot);
                return builder.CreateBitCast(slot, ty);
            }
        }
        else if ((vt->isIntegerTy() && ty->isIntegerTy()) ||
                 (vt->isFloatingPointTy() && ty->isFloatingPointTy()) ||
                 (vt->isPointerTy() && ty->isPointerTy())) {
            if (vt->getPrimitiveSizeInBits() ==
                ty->getPrimitiveSizeInBits()) {
                return builder.CreateBitCast(jv, ty);
            }
        }
        // error. box for error handling.
        jv = boxed(jv,ctx);
    }
    else if (jl_is_cpointer_type(jt)) {
        assert(ty->isPointerTy());
        jl_value_t *aty = expr_type(argex, ctx);
        if (jl_is_array_type(aty) &&
            (jl_tparam0(jt) == jl_tparam0(aty) ||
             jl_tparam0(jt) == (jl_value_t*)jl_bottom_type)) {
            // array to pointer
            return builder.CreateBitCast(emit_arrayptr(jv), ty);
        }
        if (aty == (jl_value_t*)jl_ascii_string_type || aty == (jl_value_t*)jl_utf8_string_type) {
            return builder.CreateBitCast(emit_arrayptr(emit_nthptr(jv,1,tbaa_const)), ty);
        }
        if (jl_is_structtype(aty) && jl_is_leaf_type(aty) && !jl_is_array_type(aty)) {
            if (!addressOf) {
                emit_error("ccall: expected & on argument", ctx);
                return literal_pointer_val(jl_nothing);
            }
            return builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), ty); // skip type tag field
        }
        *mightNeedTempSpace = true;
        Value *p = builder.CreateCall4(prepare_call(value_to_pointer_func),
                                       literal_pointer_val(jl_tparam0(jt)), jv,
                                       ConstantInt::get(T_int32, argn),
                                       ConstantInt::get(T_int32, (int)addressOf));
        return builder.CreateBitCast(p, ty);
    }
    else if (jl_is_structtype(jt)) {
        if (addressOf)
            jl_error("ccall: unexpected & on argument"); // the only "safe" thing to emit here is the expected struct
        assert (ty->isStructTy() && (Type*)((jl_datatype_t*)jt)->struct_decl == ty);
        jl_value_t *aty = expr_type(argex, ctx);
        if (aty != jt) {
            std::stringstream msg;
            msg << "ccall argument ";
            msg << argn;
            emit_typecheck(jv, jt, msg.str(), ctx);
        }
        //TODO: check instead that prefix matches
        //if (!jl_is_structtype(aty))
        //    emit_typecheck(emit_typeof(jv), (jl_value_t*)jl_struct_kind, "ccall: Struct argument called with something that isn't a struct", ctx);
        // //safe thing would be to also check that jl_typeof(aty)->size > sizeof(ty) here and/or at runtime
        Value *pjv = builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), PointerType::get(ty,0));
        return builder.CreateLoad(pjv, false);
    }
    else if (jl_is_tuple(jt)) {
        return emit_unbox(ty,jv,jt);
    }
    // TODO: error for & with non-pointer argument type
    assert(jl_is_bitstype(jt));
    std::stringstream msg;
    msg << "ccall argument ";
    msg << argn;
    emit_typecheck(jv, jt, msg.str(), ctx);
    Value *p = data_pointer(jv);
    return builder.CreateLoad(builder.CreateBitCast(p,
                                                    PointerType::get(ty,0)),
                              false);
}
Beispiel #3
0
void
load_file(FILE *fp, char *name, TBOOLEAN can_do_args)
{
    int len;

    int start, left;
    int more;
    int stop = FALSE;

    lf_push(fp, name, NULL); /* save state for errors and recursion */
    do_load_arg_substitution = can_do_args;

    if (fp == (FILE *) NULL) {
	os_error(NO_CARET, "Cannot open %s file '%s'",
		 can_do_args ? "call" : "load", name);
    } else if (fp == stdin) {
	/* DBT 10-6-98  go interactive if "-" named as load file */
	interactive = TRUE;
	while (!com_line());
    } else {
	call_argc = 0;
	if (can_do_args) {
	    prepare_call();
	    lf_head->c_token = c_token; /* update after prepare_call() */
	}
	/* things to do after lf_push */
	inline_num = 0;
	/* go into non-interactive mode during load */
	/* will be undone below, or in load_file_error */
	interactive = FALSE;

	while (!stop) {	/* read all lines in file */
	    left = gp_input_line_len;
	    start = 0;
	    more = TRUE;

	    /* read one logical line */
	    while (more) {
		if (fgets(&(gp_input_line[start]), left, fp) == (char *) NULL) {
		    stop = TRUE;	/* EOF in file */
		    gp_input_line[start] = '\0';
		    more = FALSE;
		} else {
		    inline_num++;
		    len = strlen(gp_input_line) - 1;
		    if (gp_input_line[len] == '\n') {	/* remove any newline */
			gp_input_line[len] = '\0';
			/* Look, len was 1-1 = 0 before, take care here! */
			if (len > 0)
			    --len;
			if (gp_input_line[len] == '\r') {	/* remove any carriage return */
			    gp_input_line[len] = NUL;
			    if (len > 0)
				--len;
			}
		    } else if (len + 2 >= left) {
			extend_input_line();
			left = gp_input_line_len - len - 1;
			start = len + 1;
			continue;	/* don't check for '\' */
		    }
		    if (gp_input_line[len] == '\\') {
			/* line continuation */
			start = len;
			left = gp_input_line_len - start;
		    } else {
			/* EAM May 2011 - handle multi-line bracketed clauses {...}.
			 * Introduces a requirement for scanner.c and scanner.h
			 * This code is redundant with part of do_line(),
			 * but do_line() assumes continuation lines come from stdin.
			 */

			/* macros in a clause are problematic, as they are */
			/* only expanded once even if the clause is replayed */
			string_expand_macros();

			/* Strip off trailing comment and count curly braces */
			num_tokens = scanner(&gp_input_line, &gp_input_line_len);
			if (gp_input_line[token[num_tokens].start_index] == '#') {
			    gp_input_line[token[num_tokens].start_index] = NUL;
			    start = token[num_tokens].start_index;
			    left = gp_input_line_len - start;
			}
			/* Read additional lines if necessary to complete a
			 * bracketed clause {...}
			 */
			if (curly_brace_count < 0)
			    int_error(NO_CARET, "Unexpected }");
			if (curly_brace_count > 0) {
			    if (len + 4 > gp_input_line_len)
				extend_input_line();
			    strcat(gp_input_line,";\n");
			    start = strlen(gp_input_line);
			    left = gp_input_line_len - start;
			    continue;
			}
			
			more = FALSE;
		    }

		}
	    }

	    /* process line */
	    if (strlen(gp_input_line) > 0) {
		if (can_do_args)
		  expand_call_args();

		screen_ok = FALSE;	/* make sure command line is
					   echoed on error */
		if (do_line())
		    stop = TRUE;
	    }
	}
    }

    /* pop state */
    (void) lf_pop();		/* also closes file fp */
}
Beispiel #4
0
/*
 * load_file() is called from
 * (1) the "load" command, no arguments substitution is done
 * (2) the "call" command, arguments are substituted for $0, $1, etc.
 * (3) on program entry to load initialization files (acts like "load")
 * (4) to execute script files given on the command line (acts like "load")
 * (5) to execute a single script file given with -c (acts like "call")
 */
void
load_file(FILE *fp, char *name, int calltype)
{
    int len;

    int start, left;
    int more;
    int stop = FALSE;

    /* Provide a user-visible copy of the current line number in the input file */
    udvt_entry *gpval_lineno = add_udv_by_name("GPVAL_LINENO");
    Ginteger(&gpval_lineno->udv_value, 0);
    gpval_lineno->udv_undef = FALSE;

    lf_push(fp, name, NULL); /* save state for errors and recursion */

    if (fp == (FILE *) NULL) {
	int_error(NO_CARET, "Cannot open script file '%s'", name);
	return; /* won't actually reach here */
    }

    if (fp == stdin) {
	/* DBT 10-6-98  go interactive if "-" named as load file */
	interactive = TRUE;
	while (!com_line());
	(void) lf_pop();
	return;
    }

    /* We actually will read from a file */
    prepare_call(calltype);

    /* things to do after lf_push */
    inline_num = 0;
    /* go into non-interactive mode during load */
    /* will be undone below, or in load_file_error */
    interactive = FALSE;

    while (!stop) {	/* read all lines in file */
	left = gp_input_line_len;
	start = 0;
	more = TRUE;

	/* read one logical line */
	while (more) {
	    if (fgets(&(gp_input_line[start]), left, fp) == (char *) NULL) {
		stop = TRUE;	/* EOF in file */
		gp_input_line[start] = '\0';
		more = FALSE;
	    } else {
		inline_num++;
		gpval_lineno->udv_value.v.int_val = inline_num;	/* User visible copy */
		len = strlen(gp_input_line) - 1;
		if (gp_input_line[len] == '\n') {	/* remove any newline */
		    gp_input_line[len] = '\0';
		    /* Look, len was 1-1 = 0 before, take care here! */
		    if (len > 0)
			--len;
		    if (gp_input_line[len] == '\r') {	/* remove any carriage return */
			gp_input_line[len] = NUL;
			if (len > 0)
			    --len;
		    }
		} else if (len + 2 >= left) {
		    extend_input_line();
		    left = gp_input_line_len - len - 1;
		    start = len + 1;
		    continue;	/* don't check for '\' */
		}
		if (gp_input_line[len] == '\\') {
		    /* line continuation */
		    start = len;
		    left = gp_input_line_len - start;
		} else {
		    /* EAM May 2011 - handle multi-line bracketed clauses {...}.
		     * Introduces a requirement for scanner.c and scanner.h
		     * This code is redundant with part of do_line(),
		     * but do_line() assumes continuation lines come from stdin.
		     */

		    /* macros in a clause are problematic, as they are */
		    /* only expanded once even if the clause is replayed */
		    string_expand_macros();

		    /* Strip off trailing comment and count curly braces */
		    num_tokens = scanner(&gp_input_line, &gp_input_line_len);
		    if (gp_input_line[token[num_tokens].start_index] == '#') {
			gp_input_line[token[num_tokens].start_index] = NUL;
			start = token[num_tokens].start_index;
			left = gp_input_line_len - start;
		    }
		    /* Read additional lines if necessary to complete a
		     * bracketed clause {...}
		     */
		    if (curly_brace_count < 0)
			int_error(NO_CARET, "Unexpected }");
		    if (curly_brace_count > 0) {
			if ((len + 4) > gp_input_line_len)
			    extend_input_line();
			strcat(gp_input_line,";\n");
			start = strlen(gp_input_line);
			left = gp_input_line_len - start;
			continue;
		    }
		    
		    more = FALSE;
		}

	    }
	}

	/* process line */
	if (strlen(gp_input_line) > 0) {
#ifdef OLD_STYLE_CALL_ARGS
	    if (calltype == 2 || calltype == 5)
		expand_call_args();
#endif
	    screen_ok = FALSE;	/* make sure command line is echoed on error */
	    if (do_line())
		stop = TRUE;
	}
    }

    /* pop state */
    (void) lf_pop();		/* also closes file fp */
}
Beispiel #5
0
const Array::Temp Call_stack::unpack(const Raw_string pattern, const Raw_string value) {
    prepare_call();
    int count = unpackstring(const_cast<char*>(pattern.value), const_cast<char*>(pattern.value + pattern.length), const_cast<char*>(value.value), const_cast<char*>(value.value + value.length), value.utf8 && !IN_BYTES ? FLAG_UNPACK_DO_UTF8 : 0);
    finish_call();
    return Array::Temp(interp, av_make(count, SP - count + 1), true);
}
Beispiel #6
0
int Call_stack::method_call(const char* name, intptr_t flags) {
    prepare_call();
    const int ret = call_method(name, flags);
    finish_call();
    return ret;
}
Beispiel #7
0
int Call_stack::sub_call(SV* ref, intptr_t flags) {
    prepare_call();
    const int ret = call_sv(ref, flags|G_EVAL);
    finish_call();
    return ret;
}
Beispiel #8
0
int Call_stack::sub_call(const char* name, intptr_t flags) {
    prepare_call();
    const int ret = call_pv(name, flags|G_EVAL);
    finish_call();
    return ret;
}