Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

codegen emit constant data as llvm constants #21277

Merged
merged 2 commits into from
Apr 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1927,19 +1927,18 @@ jl_cgval_t function_sig_t::emit_a_ccall(
// argument, allocate the box and store that as the first argument type
bool sretboxed = false;
if (sret) {
jl_cgval_t sret_val = emit_new_struct(rt, 1, NULL, ctx); // TODO: is it valid to be creating an incomplete type this way?
assert(sret_val.typ != NULL && "Type was not concrete");
if (!sret_val.ispointer()) {
Value *mem = emit_static_alloca(lrt, ctx);
builder.CreateStore(sret_val.V, mem);
result = mem;
assert(!retboxed && jl_is_datatype(rt) && "sret return type invalid");
if (jl_isbits(rt)) {
result = emit_static_alloca(lrt, ctx);
}
else {
// XXX: result needs a GC root here if result->getType() == T_pjlvalue
result = sret_val.V;
// XXX: result needs to be zero'd and given a GC root here
assert(jl_datatype_size(rt) > 0 && "sret shouldn't be a singleton instance");
result = emit_allocobj(ctx, jl_datatype_size(rt),
literal_pointer_val((jl_value_t*)rt));
sretboxed = true;
}
argvals[0] = emit_bitcast(result, fargt_sig.at(0));
sretboxed = sret_val.isboxed;
}

Instruction *stacksave = NULL;
Expand Down Expand Up @@ -2062,8 +2061,12 @@ jl_cgval_t function_sig_t::emit_a_ccall(
}
else if (sret) {
jlretboxed = sretboxed;
if (!jlretboxed)
result = builder.CreateLoad(result); // something alloca'd above
if (!jlretboxed) {
// something alloca'd above is SSA
if (static_rt)
return mark_julia_slot(result, rt, NULL, tbaa_stack);
result = builder.CreateLoad(result);
}
}
else {
Type *jlrt = julia_type_to_llvm(rt, &jlretboxed); // compute the real "julian" return type and compute whether it is boxed
Expand Down
25 changes: 14 additions & 11 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,13 @@ static Value *stringConstPtr(IRBuilder<> &builder, const std::string &txt)
static int strno = 0;
std::stringstream ssno;
ssno << "_j_str" << strno++;
GlobalVariable *gv = new GlobalVariable(*shadow_output,
ArrayType::get(T_int8, pooledtxt.size()),
true,
GlobalVariable::PrivateLinkage,
GlobalVariable *gv = get_pointer_to_constant(
ConstantDataArray::get(jl_LLVMContext,
ArrayRef<unsigned char>(
(const unsigned char*)pooledtxt.data(),
pooledtxt.size())),
ssno.str());
#if JL_LLVM_VERSION >= 30900
gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
#else
gv->setUnnamedAddr(true);
#endif
ssno.str(),
*shadow_output);
pooledval->second = gv;
jl_ExecutionEngine->addGlobalMapping(gv, (void*)(uintptr_t)pooledtxt.data());
}
Expand Down Expand Up @@ -1272,9 +1265,19 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx)

// --- accessing the representations of built-in data types ---

static Constant *julia_const_to_llvm(jl_value_t *e);
static Value *data_pointer(const jl_cgval_t &x, jl_codectx_t *ctx, Type *astype = T_ppjlvalue)
{
Value *data = x.constant ? boxed(x, ctx) : x.V;
Value *data = x.V;
if (x.constant) {
Constant *val = julia_const_to_llvm(x.constant);
if (val) {
data = get_pointer_to_constant(val, "", *jl_Module);
}
else {
data = boxed(x, ctx);
}
}
if (data->getType() != astype)
data = emit_bitcast(data, astype);
return data;
Expand Down
56 changes: 44 additions & 12 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,23 @@ template<typename T> static void mark_gc_uses(T &&vec)

// --- convenience functions for tagging llvm values with julia types ---

static GlobalVariable *get_pointer_to_constant(Constant *val, StringRef name, Module &M)
{
GlobalVariable *gv = new GlobalVariable(
M,
val->getType(),
true,
GlobalVariable::PrivateLinkage,
val,
name);
#if JL_LLVM_VERSION >= 30900
gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
#else
gv->setUnnamedAddr(true);
#endif
return gv;
}

static AllocaInst *emit_static_alloca(Type *lty, int arraysize, jl_codectx_t *ctx)
{
return new AllocaInst(lty, ConstantInt::get(T_int32, arraysize), "", /*InsertBefore=*/ctx->ptlsStates);
Expand Down Expand Up @@ -740,8 +757,14 @@ static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_value_t *typ
if (v && T->isAggregateType() && !isboxed) {
// eagerly put this back onto the stack
// llvm mem2reg pass will remove this if unneeded
Value *loc = emit_static_alloca(T);
builder.CreateStore(v, loc);
Value *loc;
if (Constant *cv = dyn_cast<Constant>(v)) {
loc = get_pointer_to_constant(cv, "", *jl_Module);
}
else {
loc = emit_static_alloca(T);
builder.CreateStore(v, loc);
}
return mark_julia_slot(loc, typ, NULL, tbaa_stack);
}
Value *froot = NULL;
Expand Down Expand Up @@ -4982,26 +5005,35 @@ static jl_returninfo_t get_specsig_function(Module *M, const std::string &name,
}
}
}
#if JL_LLVM_VERSION >= 50000
AttributeList attributes; // function declaration attributes
#else
AttributeSet attributes; // function declaration attributes
#endif
if (props.cc == jl_returninfo_t::SRet) {
attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::StructRet);
attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::NoAlias);
attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::NoCapture);
}
if (props.cc == jl_returninfo_t::Union) {
attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::NoAlias);
attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::NoCapture);
}
for (size_t i = 0; i < jl_nparams(sig); i++) {
jl_value_t *jt = jl_tparam(sig, i);
Type *ty = julia_type_to_llvm(jt);
if (type_is_ghost(ty))
continue;
if (ty->isAggregateType()) // aggregate types are passed by pointer
if (ty->isAggregateType()) { // aggregate types are passed by pointer
attributes = attributes.addAttribute(jl_LLVMContext, fsig.size() + 1, Attribute::NoCapture);
attributes = attributes.addAttribute(jl_LLVMContext, fsig.size() + 1, Attribute::ReadOnly);
ty = PointerType::get(ty, 0);
}
fsig.push_back(ty);
}
FunctionType *ftype = FunctionType::get(rt, fsig, false);
Function *f = Function::Create(ftype, GlobalVariable::ExternalLinkage, name, M);
if (props.cc == jl_returninfo_t::SRet) {
f->addAttribute(1, Attribute::StructRet);
f->addAttribute(1, Attribute::NoAlias);
f->addAttribute(1, Attribute::NoCapture);
}
if (props.cc == jl_returninfo_t::Union) {
f->addAttribute(1, Attribute::NoAlias);
f->addAttribute(1, Attribute::NoCapture);
}
f->setAttributes(attributes);
props.decl = f;
return props;
}
Expand Down