Skip to content

Commit

Permalink
eliminate uniqueness requirement on T_jlvalue (now rendered simply as…
Browse files Browse the repository at this point in the history
… T_pint8)
  • Loading branch information
vtjnash committed Oct 13, 2016
1 parent 203e077 commit cfe8efc
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 59 deletions.
5 changes: 3 additions & 2 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1811,8 +1811,9 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg
return ghostValue(sty);
if (nargs >= 2)
return emit_expr(args[1], ctx); // do side effects
Type *lt = julia_type_to_llvm(ty);
assert(lt != T_pjlvalue);
bool isboxed;
Type *lt = julia_type_to_llvm(ty, &isboxed);
assert(!isboxed);
return mark_julia_type(UndefValue::get(lt), false, ty, ctx);
}
else {
Expand Down
93 changes: 52 additions & 41 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ static DataLayout *jl_data_layout;
#endif

// types
static Type *T_jlvalue;
static Type *T_pjlvalue;
static Type *T_ppjlvalue;
static Type *jl_parray_llvmt;
Expand Down Expand Up @@ -292,8 +291,15 @@ int32_t jl_jlcall_api(const void *function)
// give the function an index in the constant lookup table
if (function == NULL)
return 0;
const Function *F = (const Function*)function;
return (F->getFunctionType() == jl_func_sig ? 1 : 3);
const Function *F = cast<const Function>((const Value*)function);
StringRef Name = F->getName();
if (Name.startswith("japi3_"))
return 3;
assert(Name.startswith("japi1_") ||
Name.startswith("jlcall_") ||
Name.startswith("jlsysw_") ||
Name.startswith("jsys1_"));
return 1;
}


Expand Down Expand Up @@ -620,7 +626,6 @@ static inline jl_cgval_t ghostValue(jl_datatype_t *typ)
static inline jl_cgval_t mark_julia_slot(Value *v, jl_value_t *typ, MDNode *tbaa)
{
// eagerly put this back onto the stack
assert(v->getType() != T_pjlvalue);
assert(tbaa);
jl_cgval_t tagval(v, NULL, false, typ);
tagval.tbaa = tbaa;
Expand All @@ -635,7 +640,6 @@ static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_value_t *typ
return ghostValue(typ);
}
if (v && T->isAggregateType() && !isboxed) {
assert(v->getType() != T_pjlvalue);
// eagerly put this back onto the stack
// llvm mem2reg pass will remove this if unneeded
Value *loc = emit_static_alloca(T);
Expand Down Expand Up @@ -768,8 +772,9 @@ static Value *alloc_local(int s, jl_codectx_t *ctx)
jl_varinfo_t &vi = ctx->slots[s];
jl_value_t *jt = vi.value.typ;
assert(store_unboxed_p(s,ctx));
Type *vtype = julia_type_to_llvm(jt);
assert(vtype != T_pjlvalue);
bool isboxed;
Type *vtype = julia_type_to_llvm(jt, &isboxed);
assert(!isboxed);
if (type_is_ghost(vtype)) {
vi.value = ghostValue(jt);
return NULL;
Expand Down Expand Up @@ -800,7 +805,7 @@ static void maybe_alloc_arrayvar(int s, jl_codectx_t *ctx)
// CreateAlloca is OK here because maybe_alloc_arrayvar is only called in the prologue setup
av.dataptr = builder.CreateAlloca(PointerType::get(elt,0));
av.len = builder.CreateAlloca(T_size);
for(int i=0; i < ndims-1; i++)
for (int i = 0; i < ndims - 1; i++)
av.sizes.push_back(builder.CreateAlloca(T_size));
av.ty = jt;
(*ctx->arrayvars)[s] = av;
Expand Down Expand Up @@ -3131,8 +3136,9 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx)
assert(!ctx->ssavalue_assigned.at(idx));
jl_cgval_t slot = emit_expr(r, ctx); // slot could be a jl_value_t (unboxed) or jl_value_t* (ispointer)
if (!slot.isboxed && !slot.isimmutable) { // emit a copy of values stored in mutable slots
Type *vtype = julia_type_to_llvm(slot.typ);
assert(vtype != T_pjlvalue);
bool isboxed;
Type *vtype = julia_type_to_llvm(slot.typ, &isboxed);
assert(!isboxed);
Value *dest = emit_static_alloca(vtype);
emit_unbox(vtype, slot, slot.typ, dest);
slot = mark_julia_slot(dest, slot.typ, tbaa_stack);
Expand Down Expand Up @@ -3925,18 +3931,10 @@ static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_t
}

// generate a julia-callable function that calls f (AKA lam)
static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, Function *f, bool sret, Module *M)
static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, Function *f, const std::string &funcName, bool sret, Module *M)
{
std::stringstream funcName;
const std::string &fname = f->getName().str();
funcName << "jlcall_";
if (fname.compare(0, 6, "julia_") == 0)
funcName << fname.substr(6);
else
funcName << fname;

Function *w = Function::Create(jl_func_sig, GlobalVariable::ExternalLinkage,
funcName.str(), M);
funcName, M);
jl_init_function(w);
#if JL_LLVM_VERSION >= 30700
w->addFnAttr("no-frame-pointer-elim", "true");
Expand Down Expand Up @@ -4097,7 +4095,6 @@ static std::unique_ptr<Module> emit_function(jl_method_instance_t *lam, jl_code_

// step 4. determine function signature
jl_value_t *jlrettype = lam->rettype;
Function *f = NULL;

bool specsig = false;
bool needsparams = lam->def ? jl_svec_len(lam->def->sparam_syms) != jl_svec_len(lam->sparam_vals) : false;
Expand All @@ -4122,20 +4119,27 @@ static std::unique_ptr<Module> emit_function(jl_method_instance_t *lam, jl_code_
if (!specsig)
ctx.nReqArgs--; // function not part of argArray in jlcall

Module *M = new Module(ctx.name, jl_LLVMContext);
jl_setup_module(M);

std::stringstream funcName;
// try to avoid conflicts in the global symbol table
funcName << "julia_" << ctx.name
if (specsig)
funcName << "jlcall_";
else if (needsparams)
funcName << "japi3_";
else
funcName << "japi1_";
const char* unadorned_name = ctx.name;
#if (defined(_OS_LINUX_) && JL_LLVM_VERSION < 30400)
+ (ctx.name[0] == '@') ? 1 : 0
if (unadorned_name[0] == '@')
unadorned_name++;
#endif
;
funcName << unadorned_name << "_" << globalUnique++;

Function *f = NULL;
Function *fwrap = NULL;
funcName << "_" << globalUnique++;

ctx.sret = false;
Module *M = new Module(ctx.name, jl_LLVMContext);
jl_setup_module(M);
if (specsig) { // assumes !va and !needsparams
std::vector<Type*> fsig(0);
Type *rt;
Expand All @@ -4152,17 +4156,19 @@ static std::unique_ptr<Module> emit_function(jl_method_instance_t *lam, jl_code_
fsig.push_back(rt->getPointerTo());
rt = T_void;
}
for(size_t i=0; i < jl_nparams(lam->specTypes); i++) {
for (size_t i = 0; i < jl_nparams(lam->specTypes); i++) {
Type *ty = julia_type_to_llvm(jl_tparam(lam->specTypes,i));
if (type_is_ghost(ty))
continue;
if (ty->isAggregateType()) // aggregate types are passed by pointer
ty = PointerType::get(ty,0);
fsig.push_back(ty);
}
std::stringstream specName;
specName << "julia_" << unadorned_name << "_" << globalUnique;
f = Function::Create(FunctionType::get(rt, fsig, false),
GlobalVariable::ExternalLinkage,
funcName.str(), M);
specName.str(), M);
jl_init_function(f);
if (ctx.sret) {
f->addAttribute(1, Attribute::StructRet);
Expand All @@ -4171,7 +4177,7 @@ static std::unique_ptr<Module> emit_function(jl_method_instance_t *lam, jl_code_
#if JL_LLVM_VERSION >= 30700
f->addFnAttr("no-frame-pointer-elim", "true");
#endif
fwrap = gen_jlcall_wrapper(lam, f, ctx.sret, M);
fwrap = gen_jlcall_wrapper(lam, f, funcName.str(), ctx.sret, M);
declarations->functionObject = function_proto(fwrap);
declarations->specFunctionObject = function_proto(f);
}
Expand Down Expand Up @@ -5127,7 +5133,18 @@ extern "C" void jl_fptr_to_llvm(jl_fptr_t fptr, jl_method_instance_t *lam, int s
else {
// this assigns a function pointer (from loading the system image), to the function object
std::stringstream funcName;
funcName << "jlsys_" << jl_symbol_name(lam->def->name) << "_" << globalUnique++;
if (specsig)
funcName << "jlsys_"; // the specsig implementation
else if (lam->functionObjectsDecls.specFunctionObject)
funcName << "jlsysw_"; // it's a specsig wrapper
else if (lam->jlcall_api == 1)
funcName << "jsys1_"; // it's a jlcall without a specsig
const char* unadorned_name = jl_symbol_name(lam->def->name);
#if (defined(_OS_LINUX_) && JL_LLVM_VERSION < 30400)
if (unadorned_name[0] == '@')
unadorned_name++;
#endif
funcName << unadorned_name << "_" << globalUnique++;
if (specsig) { // assumes !va
SmallVector<Type*, 8> fsig;
jl_value_t *jlrettype = lam->rettype;
Expand All @@ -5146,7 +5163,7 @@ extern "C" void jl_fptr_to_llvm(jl_fptr_t fptr, jl_method_instance_t *lam, int s
fsig.push_back(rt->getPointerTo());
rt = T_void;
}
for (size_t i=0; i < jl_nparams(lam->specTypes); i++) {
for (size_t i = 0; i < jl_nparams(lam->specTypes); i++) {
Type *ty = julia_type_to_llvm(jl_tparam(lam->specTypes,i));
if (type_is_ghost(ty))
continue;
Expand Down Expand Up @@ -5242,13 +5259,7 @@ static void init_julia_llvm_env(Module *m)
// This type is used to create undef Values for use in struct declarations to skip indices
NoopType = ArrayType::get(T_int1, 0);

// add needed base definitions to our LLVM environment
StructType *valueSt = StructType::create(jl_LLVMContext, "jl_value_t");
Type *valueStructElts[1] = { PointerType::getUnqual(valueSt) };
ArrayRef<Type*> vselts(valueStructElts);
valueSt->setBody(vselts);
T_jlvalue = valueSt;

// add needed base debugging definitions to our LLVM environment
DIBuilder dbuilder(*m);
#if JL_LLVM_VERSION >= 30700
DIFile *julia_h = dbuilder.createFile("julia.h","");
Expand Down Expand Up @@ -5313,7 +5324,7 @@ static void init_julia_llvm_env(Module *m)
dbuilder.getOrCreateArray(ArrayRef<Value*>()));
#endif

T_pjlvalue = PointerType::get(T_jlvalue, 0);
T_pjlvalue = T_ppint8;
T_ppjlvalue = PointerType::get(T_pjlvalue, 0);
two_pvalue_llvmt.push_back(T_pjlvalue);
two_pvalue_llvmt.push_back(T_pjlvalue);
Expand Down
29 changes: 20 additions & 9 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,18 +654,26 @@ char *jl_demangle(const char *name)
const char *start = name + 6;
const char *end = name + strlen(name);
char *ret;
if (strncmp(name, "julia_", 6)) goto done;
if (*start == '\0') goto done;
if (strncmp(name, "japi1_", 6) &&
strncmp(name, "japi3_", 6) &&
strncmp(name, "julia_", 6) &&
strncmp(name, "jsys1_", 6) &&
strncmp(name, "jlsys_", 6))
goto done;
if (*start == '\0')
goto done;
while (*(--end) != '_') {
char c = *end;
if (c < '0' || c > '9') goto done;
if (c < '0' || c > '9')
goto done;
}
if (end <= start) goto done;
ret = (char*)malloc(end-start+1);
memcpy(ret,start,end-start);
ret[end-start] = '\0';
if (end <= start)
goto done;
ret = (char*)malloc(end - start + 1);
memcpy(ret, start, end - start);
ret[end - start] = '\0';
return ret;
done:
done:
return strdup(name);
}

Expand Down Expand Up @@ -770,7 +778,10 @@ static int lookup_pointer(DIContext *context, jl_frame_t **frames,
else
jl_copy_str(&frame->file_name, file_name.c_str());

if (!frame->func_name || !func_name.compare(0, 7, "jlcall_") || !func_name.compare(0, 7, "jlcapi_")) {
if (!frame->func_name ||
func_name.compare(0, 6, "jlsysw_") == 0 ||
func_name.compare(0, 6, "jlcall_") == 0 ||
func_name.compare(0, 7, "jlcapi_") == 0) {
frame->fromC = 1;
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,16 +432,16 @@ static void jl_update_all_fptrs(void)
for (i = 0; i < delayed_fptrs_n; i++) {
jl_method_instance_t *li = delayed_fptrs[i].li;
assert(li->def);
int32_t func = delayed_fptrs[i].func - 1;
if (func >= 0) {
jl_fptr_to_llvm((jl_fptr_t)fvars[func], li, 0);
linfos[func] = li;
}
int32_t cfunc = delayed_fptrs[i].cfunc - 1;
if (cfunc >= 0) {
jl_fptr_to_llvm((jl_fptr_t)fvars[cfunc], li, 1);
linfos[cfunc] = li;
}
int32_t func = delayed_fptrs[i].func - 1;
if (func >= 0) {
jl_fptr_to_llvm((jl_fptr_t)fvars[func], li, 0);
linfos[func] = li;
}
}
jl_register_fptrs(sysimage_base, fvars, linfos, sysimg_fvars_max);
delayed_fptrs_n = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ static jl_cgval_t ghostValue(jl_value_t *ty);
// emit code to unpack a raw value from a box into registers or a stack slot
static Value *emit_unbox(Type *to, const jl_cgval_t &x, jl_value_t *jt, Value *dest, bool volatile_store)
{
assert(to != T_pjlvalue && to != T_void);
assert(to != T_void);
// TODO: fully validate that x.typ == jt?
if (x.isghost) {
// this can happen when a branch yielding a different type ends
Expand Down
3 changes: 2 additions & 1 deletion src/llvm-gcroot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ void JuliaGCAllocator::allocate_frame()
DIBuilder dbuilder(M, false);
#endif
unsigned argSpaceSize = 0;
for(BasicBlock::iterator I = gcframe->getParent()->begin(), E(gcframe); I != E; ) {
for (BasicBlock::iterator I = gcframe->getParent()->begin(), E(gcframe); I != E; ) {
Instruction* inst = &*I;
++I;
if (CallInst* callInst = dyn_cast<CallInst>(inst)) {
Expand Down Expand Up @@ -1051,6 +1051,7 @@ void JuliaGCAllocator::allocate_frame()
}
else if (AllocaInst *allocaInst = dyn_cast<AllocaInst>(inst)) {
if (allocaInst->getAllocatedType() == V_null->getType()) {
// TODO: this is overly aggressive at zeroing allocas that may not actually need to be zeroed
StoreInst *store = new StoreInst(V_null, allocaInst);
store->insertAfter(allocaInst);
}
Expand Down

0 comments on commit cfe8efc

Please sign in to comment.