Example #1
0
void o_bootstrap_fn_overload_type_init(oThreadContextRef ctx) {
    LLVMTypeRef llvmTypes[4];
    oFieldRef *fields;
	
    ctx->runtime->builtInTypes.functionOverload->fields = o_bootstrap_type_create_field_array(ctx->runtime, 2);
    ctx->runtime->builtInTypes.functionOverload->kind = o_T_OBJECT;
	ctx->runtime->builtInTypes.functionOverload->name = o_bootstrap_string_create(ctx->runtime, "FunctionOverload");
	ctx->runtime->builtInTypes.functionOverload->size = sizeof(oFunctionOverload);
    
    fields = (oFieldRef*)oArrayDataPointer(ctx->runtime->builtInTypes.functionOverload->fields);
    
    fields[0]->name = o_bootstrap_string_create(ctx->runtime, "signature");
	fields[0]->offset = offsetof(oFunctionOverload, signature);
    fields[0]->type = ctx->runtime->builtInTypes.signature;
    
    fields[1]->name = o_bootstrap_string_create(ctx->runtime, "attributes");
	fields[1]->offset = offsetof(oFunctionOverload, attributes);
    fields[1]->type = ctx->runtime->builtInTypes.array;
    
    // Have to do the llvm type manually because of the "secret" llvm function
    // type and code pointer fields
    
    // signature
    llvmTypes[0] = LLVMPointerType(ctx->runtime->builtInTypes.signature->llvmType, 0);
    // attributes
    llvmTypes[1] = LLVMPointerType(ctx->runtime->builtInTypes.array->llvmType, 0);
    // function type
    llvmTypes[2] = ctx->runtime->builtInTypes.pointer->llvmType;
    // code
    llvmTypes[3] = ctx->runtime->builtInTypes.pointer->llvmType;
    
    ctx->runtime->builtInTypes.functionOverload->llvmType = LLVMStructTypeInContext(ctx->runtime->llvmCtx, llvmTypes, 4, o_false);
}
Example #2
0
void o_bootstrap_thread_context_init_llvm_type(oThreadContextRef ctx) {
	LLVMTypeRef types[6];
	char* un;
	// runtime, opaque pointer. The runtime object is not part of the type system
	types[0] = ctx->runtime->builtInTypes.pointer->llvmType;
	// heap, also opaque
	types[1] = ctx->runtime->builtInTypes.pointer->llvmType;
	// error type, not initialized yet so we create a prototype for it
	un = oGenUniqueName(ctx);
	ctx->runtime->builtInTypes.error->llvmType = LLVMStructCreateNamed(ctx->runtime->llvmCtx, un);
	oFree(un);
	types[2] = ctx->runtime->builtInTypes.error->llvmType;
	// namespace, also needs a prototype
	un = oGenUniqueName(ctx);
	ctx->runtime->builtInTypes.name_space->llvmType = LLVMStructCreateNamed(ctx->runtime->llvmCtx, un);
	oFree(un);
	types[3] = ctx->runtime->builtInTypes.name_space->llvmType;
	// root set, opaque
	types[4] = ctx->runtime->builtInTypes.pointer->llvmType;
	// root set semaphore. This is volatile in the C code but llvm uses volatile
	// on instructions rather than data so this is a regular uword here.
	types[5] = ctx->runtime->builtInTypes.uword->llvmType;

	ctx->runtime->builtInTypes.threadContext->llvmType = LLVMStructTypeInContext(ctx->runtime->llvmCtx, types, 6, o_false);
}
Example #3
0
File: genfun.c Project: fydot/ponyc
static LLVMTypeRef send_message(compile_t* c, ast_t* fun, LLVMValueRef to,
  LLVMValueRef func, uint32_t index)
{
  // Get the parameter types.
  LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(func));
  int count = LLVMCountParamTypes(f_type) + 2;
  VLA(LLVMTypeRef, f_params, count);
  LLVMGetParamTypes(f_type, &f_params[2]);

  // The first one becomes the message size, the second the message ID.
  f_params[0] = c->i32;
  f_params[1] = c->i32;
  f_params[2] = c->void_ptr;
  LLVMTypeRef msg_type = LLVMStructTypeInContext(c->context, f_params, count,
    false);
  LLVMTypeRef msg_type_ptr = LLVMPointerType(msg_type, 0);

  // Allocate the message, setting its size and ID.
  size_t msg_size = LLVMABISizeOfType(c->target_data, msg_type);
  LLVMValueRef args[2];

  args[0] = LLVMConstInt(c->i32, pool_index(msg_size), false);
  args[1] = LLVMConstInt(c->i32, index, false);
  LLVMValueRef msg = gencall_runtime(c, "pony_alloc_msg", args, 2, "");
  LLVMValueRef msg_ptr = LLVMBuildBitCast(c->builder, msg, msg_type_ptr, "");

  // Trace while populating the message contents.
  LLVMValueRef start_trace = gencall_runtime(c, "pony_gc_send", NULL, 0, "");
  ast_t* params = ast_childidx(fun, 3);
  ast_t* param = ast_child(params);
  bool need_trace = false;

  for(int i = 3; i < count; i++)
  {
    LLVMValueRef arg = LLVMGetParam(func, i - 2);
    LLVMValueRef arg_ptr = LLVMBuildStructGEP(c->builder, msg_ptr, i, "");
    LLVMBuildStore(c->builder, arg, arg_ptr);

    need_trace |= gentrace(c, arg, ast_type(param));
    param = ast_sibling(param);
  }

  if(need_trace)
    gencall_runtime(c, "pony_send_done", NULL, 0, "");
  else
    LLVMInstructionEraseFromParent(start_trace);

  // Send the message.
  args[0] = LLVMBuildBitCast(c->builder, to, c->object_ptr, "");
  args[1] = msg;
  gencall_runtime(c, "pony_sendv", args, 2, "");

  // Return the type of the message.
  return msg_type_ptr;
}
Example #4
0
LLVMValueRef build_l4_ipc_call(
	struct llvm_ctx *ctx,
	LLVMValueRef arg_to,
	LLVMValueRef arg_timeouts,
	LLVMValueRef arg_fromspec,
	LLVMValueRef arg_mr0,
	LLVMValueRef *from_p,
	LLVMValueRef *mr1_p,
	LLVMValueRef *mr2_p)
{
	LLVMTypeRef params[5];
	for(int i=0; i<5; i++) params[i] = ctx->wordt;
	LLVMTypeRef ipc_result_type = LLVMStructTypeInContext(ctx->ctx,
		params, 4, 0);
	LLVMTypeRef ipc_type = LLVMFunctionType(ipc_result_type,
		params, 5, 0);
	LLVMValueRef fn = LLVMConstInlineAsm(ipc_type,
		/* NOTE: this compensates against LLVM 3.3's inability to save %ebp
		 * over an asm statement. clearly a bug, but w/e.
		 *
		 * it's been around since at least LLVM 3.2.
		 */
		"  pushl %ebp\n"
		"\tcall __L4_Ipc\n"
		"\tmovl %ebp, %ecx\n"
		"\tpopl %ebp\n",
		"={ax},={si},={bx},={cx},{ax},{cx},{dx},{si},{di},~{dirflag},~{fpsr},~{flags}",
		1, 0);
	LLVMValueRef args[5] = {
		arg_to, arg_timeouts, arg_fromspec, arg_mr0,
		LLVMBuildPtrToInt(ctx->builder, ctx->utcb, ctx->wordt,
			"l4ipc.utcb"),
	};
	LLVMValueRef result = LLVMBuildCall(ctx->builder, fn, args, 5, "l4ipc");
	LLVMSetTailCall(result, 1);

	if(from_p != NULL) {
		*from_p = LLVMBuildExtractValue(ctx->builder, result, 0, "from");
	}
	if(mr1_p != NULL) {
		*mr1_p = LLVMBuildExtractValue(ctx->builder, result, 2, "mr1");
	}
	if(mr2_p != NULL) {
		*mr2_p = LLVMBuildExtractValue(ctx->builder, result, 3, "mr2");
	}
	return LLVMBuildExtractValue(ctx->builder, result, 1, "mr0");
}
Example #5
0
void o_bootstrap_function_type_init(oThreadContextRef ctx) {
    LLVMTypeRef llvmTypes[2];

    ctx->runtime->builtInTypes.function->fields = NULL;
    ctx->runtime->builtInTypes.function->kind = o_T_OBJECT;
	ctx->runtime->builtInTypes.function->name = o_bootstrap_string_create(ctx->runtime, "Function");
	ctx->runtime->builtInTypes.function->size = sizeof(oFunction);
    ctx->runtime->builtInTypes.function->finalizer = functionFinalizer;
    
    // Have to do the llvm type manually because of the "secret" fields
    
    // lock
    llvmTypes[0] = ctx->runtime->builtInTypes.pointer->llvmType;
    // overloads table
    llvmTypes[1] = ctx->runtime->builtInTypes.pointer->llvmType;
    
    ctx->runtime->builtInTypes.function->llvmType = LLVMStructTypeInContext(ctx->runtime->llvmCtx, llvmTypes, 2, o_false);
}
Example #6
0
static LLVMTypeRef ffi_return_type(compile_t* c, reach_type_t* t,
  bool intrinsic)
{
  compile_type_t* c_t = (compile_type_t*)t->c_type;

  if(t->underlying == TK_TUPLETYPE)
  {
    pony_assert(intrinsic);

    // Can't use the named type. Build an unnamed type with the same elements.
    unsigned int count = LLVMCountStructElementTypes(c_t->use_type);
    size_t buf_size = count * sizeof(LLVMTypeRef);
    LLVMTypeRef* e_types = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
    LLVMGetStructElementTypes(c_t->use_type, e_types);

    ast_t* child = ast_child(t->ast);
    size_t i = 0;

    while(child != NULL)
    {
      // A Bool in an intrinsic tuple return type is an i1.
      if(is_bool(child))
        e_types[i] = c->i1;

      child = ast_sibling(child);
      i++;
    }

    LLVMTypeRef r_type = LLVMStructTypeInContext(c->context, e_types, count,
      false);
    ponyint_pool_free_size(buf_size, e_types);
    return r_type;
  } else if(is_none(t->ast_cap)) {
    return c->void_type;
  } else {
    return c_t->use_type;
  }
}
Example #7
0
static void make_cpuid(compile_t* c)
{
  if(target_is_x86(c->opt->triple))
  {
    LLVMTypeRef elems[4] = {c->i32, c->i32, c->i32, c->i32};
    LLVMTypeRef r_type = LLVMStructTypeInContext(c->context, elems, 4, false);
    LLVMTypeRef f_type = LLVMFunctionType(r_type, &c->i32, 1, false);
    LLVMValueRef fun = codegen_addfun(c, "internal.x86.cpuid", f_type);
    LLVMSetFunctionCallConv(fun, LLVMCCallConv);
    codegen_startfun(c, fun, NULL, NULL);

    LLVMValueRef cpuid = LLVMConstInlineAsm(f_type,
      "cpuid", "={ax},={bx},={cx},={dx},{ax}", false, false);
    LLVMValueRef zero = LLVMConstInt(c->i32, 0, false);

    LLVMValueRef result = LLVMBuildCall(c->builder, cpuid, &zero, 1, "");
    LLVMBuildRet(c->builder, result);

    codegen_finishfun(c);
  } else {
    (void)c;
  }
}
Example #8
0
File: lp_jit.c Project: Gnurou/mesa
static void
lp_jit_create_types(struct lp_fragment_shader_variant *lp)
{
   struct gallivm_state *gallivm = lp->gallivm;
   LLVMContextRef lc = gallivm->context;
   LLVMTypeRef viewport_type, texture_type, sampler_type;

   /* struct lp_jit_viewport */
   {
      LLVMTypeRef elem_types[LP_JIT_VIEWPORT_NUM_FIELDS];

      elem_types[LP_JIT_VIEWPORT_MIN_DEPTH] =
      elem_types[LP_JIT_VIEWPORT_MAX_DEPTH] = LLVMFloatTypeInContext(lc);

      viewport_type = LLVMStructTypeInContext(lc, elem_types,
                                              Elements(elem_types), 0);

      LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, min_depth,
                             gallivm->target, viewport_type,
                             LP_JIT_VIEWPORT_MIN_DEPTH);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, max_depth,
                             gallivm->target, viewport_type,
                             LP_JIT_VIEWPORT_MAX_DEPTH);
      LP_CHECK_STRUCT_SIZE(struct lp_jit_viewport,
                           gallivm->target, viewport_type);
   }

   /* struct lp_jit_texture */
   {
      LLVMTypeRef elem_types[LP_JIT_TEXTURE_NUM_FIELDS];

      elem_types[LP_JIT_TEXTURE_WIDTH]  =
      elem_types[LP_JIT_TEXTURE_HEIGHT] =
      elem_types[LP_JIT_TEXTURE_DEPTH] =
      elem_types[LP_JIT_TEXTURE_FIRST_LEVEL] =
      elem_types[LP_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32TypeInContext(lc);
      elem_types[LP_JIT_TEXTURE_BASE] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
      elem_types[LP_JIT_TEXTURE_ROW_STRIDE] =
      elem_types[LP_JIT_TEXTURE_IMG_STRIDE] =
      elem_types[LP_JIT_TEXTURE_MIP_OFFSETS] =
         LLVMArrayType(LLVMInt32TypeInContext(lc), LP_MAX_TEXTURE_LEVELS);

      texture_type = LLVMStructTypeInContext(lc, elem_types,
                                             Elements(elem_types), 0);

      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, width,
                             gallivm->target, texture_type,
                             LP_JIT_TEXTURE_WIDTH);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, height,
                             gallivm->target, texture_type,
                             LP_JIT_TEXTURE_HEIGHT);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, depth,
                             gallivm->target, texture_type,
                             LP_JIT_TEXTURE_DEPTH);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, first_level,
                             gallivm->target, texture_type,
                             LP_JIT_TEXTURE_FIRST_LEVEL);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, last_level,
                             gallivm->target, texture_type,
                             LP_JIT_TEXTURE_LAST_LEVEL);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, base,
                             gallivm->target, texture_type,
                             LP_JIT_TEXTURE_BASE);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, row_stride,
                             gallivm->target, texture_type,
                             LP_JIT_TEXTURE_ROW_STRIDE);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, img_stride,
                             gallivm->target, texture_type,
                             LP_JIT_TEXTURE_IMG_STRIDE);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, mip_offsets,
                             gallivm->target, texture_type,
                             LP_JIT_TEXTURE_MIP_OFFSETS);
      LP_CHECK_STRUCT_SIZE(struct lp_jit_texture,
                           gallivm->target, texture_type);
   }

   /* struct lp_jit_sampler */
   {
      LLVMTypeRef elem_types[LP_JIT_SAMPLER_NUM_FIELDS];
      elem_types[LP_JIT_SAMPLER_MIN_LOD] =
      elem_types[LP_JIT_SAMPLER_MAX_LOD] =
      elem_types[LP_JIT_SAMPLER_LOD_BIAS] = LLVMFloatTypeInContext(lc);
      elem_types[LP_JIT_SAMPLER_BORDER_COLOR] =
         LLVMArrayType(LLVMFloatTypeInContext(lc), 4);

      sampler_type = LLVMStructTypeInContext(lc, elem_types,
                                             Elements(elem_types), 0);

      LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, min_lod,
                             gallivm->target, sampler_type,
                             LP_JIT_SAMPLER_MIN_LOD);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, max_lod,
                             gallivm->target, sampler_type,
                             LP_JIT_SAMPLER_MAX_LOD);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, lod_bias,
                             gallivm->target, sampler_type,
                             LP_JIT_SAMPLER_LOD_BIAS);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, border_color,
                             gallivm->target, sampler_type,
                             LP_JIT_SAMPLER_BORDER_COLOR);
      LP_CHECK_STRUCT_SIZE(struct lp_jit_sampler,
                           gallivm->target, sampler_type);
   }

   /* struct lp_jit_context */
   {
      LLVMTypeRef elem_types[LP_JIT_CTX_COUNT];
      LLVMTypeRef context_type;

      elem_types[LP_JIT_CTX_CONSTANTS] =
         LLVMArrayType(LLVMPointerType(LLVMFloatTypeInContext(lc), 0), LP_MAX_TGSI_CONST_BUFFERS);
      elem_types[LP_JIT_CTX_NUM_CONSTANTS] =
            LLVMArrayType(LLVMInt32TypeInContext(lc), LP_MAX_TGSI_CONST_BUFFERS);
      elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatTypeInContext(lc);
      elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] =
      elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32TypeInContext(lc);
      elem_types[LP_JIT_CTX_U8_BLEND_COLOR] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
      elem_types[LP_JIT_CTX_F_BLEND_COLOR] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0);
      elem_types[LP_JIT_CTX_VIEWPORTS] = LLVMPointerType(viewport_type, 0);
      elem_types[LP_JIT_CTX_TEXTURES] = LLVMArrayType(texture_type,
                                                      PIPE_MAX_SHADER_SAMPLER_VIEWS);
      elem_types[LP_JIT_CTX_SAMPLERS] = LLVMArrayType(sampler_type,
                                                      PIPE_MAX_SAMPLERS);

      context_type = LLVMStructTypeInContext(lc, elem_types,
                                             Elements(elem_types), 0);

      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, constants,
                             gallivm->target, context_type,
                             LP_JIT_CTX_CONSTANTS);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, num_constants,
                             gallivm->target, context_type,
                             LP_JIT_CTX_NUM_CONSTANTS);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value,
                             gallivm->target, context_type,
                             LP_JIT_CTX_ALPHA_REF);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_front,
                             gallivm->target, context_type,
                             LP_JIT_CTX_STENCIL_REF_FRONT);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_back,
                             gallivm->target, context_type,
                             LP_JIT_CTX_STENCIL_REF_BACK);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, u8_blend_color,
                             gallivm->target, context_type,
                             LP_JIT_CTX_U8_BLEND_COLOR);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, f_blend_color,
                             gallivm->target, context_type,
                             LP_JIT_CTX_F_BLEND_COLOR);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, viewports,
                             gallivm->target, context_type,
                             LP_JIT_CTX_VIEWPORTS);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
                             gallivm->target, context_type,
                             LP_JIT_CTX_TEXTURES);
      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, samplers,
                             gallivm->target, context_type,
                             LP_JIT_CTX_SAMPLERS);
      LP_CHECK_STRUCT_SIZE(struct lp_jit_context,
                           gallivm->target, context_type);

      lp->jit_context_ptr_type = LLVMPointerType(context_type, 0);
   }

   /* struct lp_jit_thread_data */
   {
      LLVMTypeRef elem_types[LP_JIT_THREAD_DATA_COUNT];
      LLVMTypeRef thread_data_type;

      elem_types[LP_JIT_THREAD_DATA_COUNTER] = LLVMInt64TypeInContext(lc);
      elem_types[LP_JIT_THREAD_DATA_RASTER_STATE_VIEWPORT_INDEX] =
            LLVMInt32TypeInContext(lc);

      thread_data_type = LLVMStructTypeInContext(lc, elem_types,
                                                 Elements(elem_types), 0);

      lp->jit_thread_data_ptr_type = LLVMPointerType(thread_data_type, 0);
   }

   if (gallivm_debug & GALLIVM_DEBUG_IR) {
      LLVMDumpModule(gallivm->module);
   }
}
Example #9
0
static LLVMValueRef get_stritem_len_fn(struct llvm_ctx *ctx)
{
	if(ctx->stritem_len_fn != NULL) return ctx->stritem_len_fn;

	/* returns (i32 len, i32 new_tpos)
	 * params (word *utcbptr, i32 tpos)
	 *
	 * when return value "new_tpos" > tmax + 1, the result is invalid. the function
	 * should also not be called when tpos > tmax + 1.
	 */
	LLVMTypeRef ret_types[2] = { ctx->i32t, ctx->i32t },
		parm_types[2] = { LLVMPointerType(ctx->wordt, 0), ctx->i32t },
		ret_type = LLVMStructTypeInContext(ctx->ctx, ret_types, 2, 0),
		fn_type = LLVMFunctionType(ret_type, parm_types, 2, 0);
	LLVMValueRef fn = LLVMAddFunction(ctx->module, "__muidl_get_stritem_len",
		fn_type);
	LLVMSetVisibility(fn, LLVMHiddenVisibility);
	LLVMSetLinkage(fn, LLVMInternalLinkage);
	V fn_args[2];
	LLVMGetParams(fn, fn_args);
	LLVMAddAttribute(fn_args[0], LLVMNoCaptureAttribute);
	for(int i=0; i<2; i++) {
		LLVMAddAttribute(fn_args[i], LLVMInRegAttribute);
	}
	ctx->stritem_len_fn = fn;

	LLVMBuilderRef old_builder = ctx->builder;
	ctx->builder = LLVMCreateBuilderInContext(ctx->ctx);
	LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn,
			"EntryBlock"),
		loop_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "loop"),
		valid_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "valid"),
		exit_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "exit");

	LLVMPositionBuilderAtEnd(ctx->builder, entry_bb);
	LLVMValueRef old_utcb = ctx->utcb, old_tpos = ctx->tpos;
	ctx->utcb = fn_args[0];
	ctx->tpos = fn_args[1];
	LLVMBuildBr(ctx->builder, loop_bb);

	LLVMPositionBuilderAtEnd(ctx->builder, exit_bb);
	LLVMValueRef exit_len_phi = LLVMBuildPhi(ctx->builder, ctx->i32t,
			"exit.len.phi"),
		exit_tpos_phi = LLVMBuildPhi(ctx->builder, ctx->i32t,
			"exit.tpos.phi");
	LLVMValueRef rvals[2] = { exit_len_phi, exit_tpos_phi };
	LLVMBuildAggregateRet(ctx->builder, rvals, 2);

	LLVMPositionBuilderAtEnd(ctx->builder, loop_bb);
	LLVMValueRef len_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "len.phi"),
		tpos_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "tpos.phi");
	LLVMAddIncoming(len_phi, &ctx->zero, &entry_bb, 1);
	LLVMAddIncoming(tpos_phi, &ctx->tpos, &entry_bb, 1);
	ctx->tpos = tpos_phi;
	/* test: if *tpos doesn't look like a string item, conk out. */
	LLVMValueRef infoword = build_utcb_load(ctx, ctx->tpos, "si.info");
	LLVMValueRef is_cond = LLVMBuildICmp(ctx->builder, LLVMIntEQ,
		ctx->zero, LLVMBuildAnd(ctx->builder, infoword,
			CONST_WORD(1 << 4), "infoword.si.mask"),
		"infoword.si.cond");
	/* anything + 100 is sure to be > tmax + 1. */
	LLVMValueRef fucked_tpos = LLVMBuildAdd(ctx->builder, tpos_phi,
		CONST_INT(100), "f****d.tpos");
	branch_set_phi(ctx, exit_len_phi, len_phi);
	branch_set_phi(ctx, exit_tpos_phi, fucked_tpos);
	LLVMBuildCondBr(ctx->builder, is_cond, valid_bb, exit_bb);

	LLVMPositionBuilderAtEnd(ctx->builder, valid_bb);
	LLVMValueRef string_length = LLVMBuildTruncOrBitCast(ctx->builder,
			LLVMBuildLShr(ctx->builder, infoword,
				CONST_INT(10), "si.info.len"),
			ctx->i32t, "si.info.len.int"),
		string_j = LLVMBuildTruncOrBitCast(ctx->builder,
			LLVMBuildAnd(ctx->builder, CONST_WORD(0x1f),
				LLVMBuildLShr(ctx->builder, infoword, CONST_WORD(4),
					"si.info.j.shift"),
				"si.info.j.masked"),
			ctx->i32t, "si.info.j"),
		string_c = LLVMBuildTruncOrBitCast(ctx->builder,
			LLVMBuildAnd(ctx->builder, CONST_WORD(1 << 9),
				infoword, "si.info.c.masked"),
			ctx->i32t, "si.info.c.masked.int"),
		c_cond = LLVMBuildICmp(ctx->builder, LLVMIntNE,
			string_c, CONST_WORD(0), "si.info.c.cond"),
		new_len = LLVMBuildAdd(ctx->builder, len_phi,
			LLVMBuildMul(ctx->builder, string_length,
				LLVMBuildAdd(ctx->builder, string_j,
					CONST_INT(1), "j.plus.one"),
				"len.incr"),
			"len.new"),
		new_tpos = LLVMBuildAdd(ctx->builder, ctx->tpos,
			LLVMBuildSelect(ctx->builder, c_cond,
				LLVMBuildAdd(ctx->builder, CONST_INT(2),
					string_j, "cont.tpos.bump"),
				CONST_INT(2), "tpos.bump"),
			"tpos.new");
	LLVMAddIncoming(len_phi, &new_len, &valid_bb, 1);
	LLVMAddIncoming(tpos_phi, &new_tpos, &valid_bb, 1);
	LLVMAddIncoming(exit_len_phi, &new_len, &valid_bb, 1);
	LLVMAddIncoming(exit_tpos_phi, &new_tpos, &valid_bb, 1);
	LLVMBuildCondBr(ctx->builder, c_cond, loop_bb, exit_bb);

	LLVMDisposeBuilder(ctx->builder);
	ctx->builder = old_builder;
	ctx->utcb = old_utcb;
	ctx->tpos = old_tpos;

	return ctx->stritem_len_fn;
}
Example #10
0
static void init_runtime(compile_t* c)
{
  c->str_builtin = stringtab("$0");
  c->str_Bool = stringtab("Bool");
  c->str_I8 = stringtab("I8");
  c->str_I16 = stringtab("I16");
  c->str_I32 = stringtab("I32");
  c->str_I64 = stringtab("I64");
  c->str_I128 = stringtab("I128");
  c->str_ILong = stringtab("ILong");
  c->str_ISize = stringtab("ISize");
  c->str_U8 = stringtab("U8");
  c->str_U16 = stringtab("U16");
  c->str_U32 = stringtab("U32");
  c->str_U64 = stringtab("U64");
  c->str_U128 = stringtab("U128");
  c->str_ULong = stringtab("ULong");
  c->str_USize = stringtab("USize");
  c->str_F32 = stringtab("F32");
  c->str_F64 = stringtab("F64");
  c->str_Pointer = stringtab("Pointer");
  c->str_Maybe = stringtab("MaybePointer");
  c->str_DoNotOptimise = stringtab("DoNotOptimise");
  c->str_Array = stringtab("Array");
  c->str_String = stringtab("String");
  c->str_Platform = stringtab("Platform");
  c->str_Main = stringtab("Main");
  c->str_Env = stringtab("Env");

  c->str_add = stringtab("add");
  c->str_sub = stringtab("sub");
  c->str_mul = stringtab("mul");
  c->str_div = stringtab("div");
  c->str_mod = stringtab("mod");
  c->str_neg = stringtab("neg");
  c->str_add_unsafe = stringtab("add_unsafe");
  c->str_sub_unsafe = stringtab("sub_unsafe");
  c->str_mul_unsafe = stringtab("mul_unsafe");
  c->str_div_unsafe = stringtab("div_unsafe");
  c->str_mod_unsafe = stringtab("mod_unsafe");
  c->str_neg_unsafe = stringtab("neg_unsafe");
  c->str_and = stringtab("op_and");
  c->str_or = stringtab("op_or");
  c->str_xor = stringtab("op_xor");
  c->str_not = stringtab("op_not");
  c->str_shl = stringtab("shl");
  c->str_shr = stringtab("shr");
  c->str_shl_unsafe = stringtab("shl_unsafe");
  c->str_shr_unsafe = stringtab("shr_unsafe");
  c->str_eq = stringtab("eq");
  c->str_ne = stringtab("ne");
  c->str_lt = stringtab("lt");
  c->str_le = stringtab("le");
  c->str_ge = stringtab("ge");
  c->str_gt = stringtab("gt");
  c->str_eq_unsafe = stringtab("eq_unsafe");
  c->str_ne_unsafe = stringtab("ne_unsafe");
  c->str_lt_unsafe = stringtab("lt_unsafe");
  c->str_le_unsafe = stringtab("le_unsafe");
  c->str_ge_unsafe = stringtab("ge_unsafe");
  c->str_gt_unsafe = stringtab("gt_unsafe");

  c->str_this = stringtab("this");
  c->str_create = stringtab("create");
  c->str__create = stringtab("_create");
  c->str__init = stringtab("_init");
  c->str__final = stringtab("_final");
  c->str__event_notify = stringtab("_event_notify");
  c->str__serialise_space = stringtab("_serialise_space");
  c->str__serialise = stringtab("_serialise");
  c->str__deserialise = stringtab("_deserialise");

  LLVMTypeRef type;
  LLVMTypeRef params[5];
  LLVMValueRef value;

  c->void_type = LLVMVoidTypeInContext(c->context);
  c->i1 = LLVMInt1TypeInContext(c->context);
  c->i8 = LLVMInt8TypeInContext(c->context);
  c->i16 = LLVMInt16TypeInContext(c->context);
  c->i32 = LLVMInt32TypeInContext(c->context);
  c->i64 = LLVMInt64TypeInContext(c->context);
  c->i128 = LLVMIntTypeInContext(c->context, 128);
  c->f32 = LLVMFloatTypeInContext(c->context);
  c->f64 = LLVMDoubleTypeInContext(c->context);
  c->intptr = LLVMIntPtrTypeInContext(c->context, c->target_data);

  // i8*
  c->void_ptr = LLVMPointerType(c->i8, 0);

  // forward declare object
  c->object_type = LLVMStructCreateNamed(c->context, "__object");
  c->object_ptr = LLVMPointerType(c->object_type, 0);

  // padding required in an actor between the descriptor and fields
  c->actor_pad = LLVMArrayType(c->i8, PONY_ACTOR_PAD_SIZE);

  // message
  params[0] = c->i32; // size
  params[1] = c->i32; // id
  c->msg_type = LLVMStructCreateNamed(c->context, "__message");
  c->msg_ptr = LLVMPointerType(c->msg_type, 0);
  LLVMStructSetBody(c->msg_type, params, 2, false);

  // trace
  // void (*)(i8*, __object*)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  c->trace_type = LLVMFunctionType(c->void_type, params, 2, false);
  c->trace_fn = LLVMPointerType(c->trace_type, 0);

  // serialise
  // void (*)(i8*, __object*, i8*, intptr, i32)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->void_ptr;
  params[3] = c->intptr;
  params[4] = c->i32;
  c->serialise_type = LLVMFunctionType(c->void_type, params, 5, false);
  c->serialise_fn = LLVMPointerType(c->serialise_type, 0);

  // serialise_space
  // i64 (__object*)
  params[0] = c->object_ptr;
  c->custom_serialise_space_fn = LLVMPointerType(
    LLVMFunctionType(c->i64, params, 1, false), 0);

  // custom_deserialise
  // void (*)(__object*, void*)
  params[0] = c->object_ptr;
  params[1] = c->void_ptr;
  c->custom_deserialise_fn = LLVMPointerType(
  LLVMFunctionType(c->void_type, params, 2, false), 0);

  // dispatch
  // void (*)(i8*, __object*, $message*)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->msg_ptr;
  c->dispatch_type = LLVMFunctionType(c->void_type, params, 3, false);
  c->dispatch_fn = LLVMPointerType(c->dispatch_type, 0);

  // void (*)(__object*)
  params[0] = c->object_ptr;
  c->final_fn = LLVMPointerType(
    LLVMFunctionType(c->void_type, params, 1, false), 0);

  // descriptor, opaque version
  // We need this in order to build our own structure.
  const char* desc_name = genname_descriptor(NULL);
  c->descriptor_type = LLVMStructCreateNamed(c->context, desc_name);
  c->descriptor_ptr = LLVMPointerType(c->descriptor_type, 0);

  // field descriptor
  // Also needed to build a descriptor structure.
  params[0] = c->i32;
  params[1] = c->descriptor_ptr;
  c->field_descriptor = LLVMStructTypeInContext(c->context, params, 2, false);

  // descriptor, filled in
  gendesc_basetype(c, c->descriptor_type);

  // define object
  params[0] = c->descriptor_ptr;
  LLVMStructSetBody(c->object_type, params, 1, false);

#if PONY_LLVM >= 309
  LLVM_DECLARE_ATTRIBUTEREF(nounwind_attr, nounwind, 0);
  LLVM_DECLARE_ATTRIBUTEREF(readnone_attr, readnone, 0);
  LLVM_DECLARE_ATTRIBUTEREF(readonly_attr, readonly, 0);
  LLVM_DECLARE_ATTRIBUTEREF(inacc_or_arg_mem_attr,
    inaccessiblemem_or_argmemonly, 0);
  LLVM_DECLARE_ATTRIBUTEREF(noalias_attr, noalias, 0);
  LLVM_DECLARE_ATTRIBUTEREF(noreturn_attr, noreturn, 0);
  LLVM_DECLARE_ATTRIBUTEREF(deref_actor_attr, dereferenceable,
    PONY_ACTOR_PAD_SIZE + (target_is_ilp32(c->opt->triple) ? 4 : 8));
  LLVM_DECLARE_ATTRIBUTEREF(align_pool_attr, align, ponyint_pool_size(0));
  LLVM_DECLARE_ATTRIBUTEREF(align_heap_attr, align, HEAP_MIN);
  LLVM_DECLARE_ATTRIBUTEREF(deref_or_null_alloc_attr, dereferenceable_or_null,
    HEAP_MIN);
  LLVM_DECLARE_ATTRIBUTEREF(deref_alloc_small_attr, dereferenceable, HEAP_MIN);
  LLVM_DECLARE_ATTRIBUTEREF(deref_alloc_large_attr, dereferenceable,
    HEAP_MAX << 1);
#endif

  // i8* pony_ctx()
  type = LLVMFunctionType(c->void_ptr, NULL, 0, false);
  value = LLVMAddFunction(c->module, "pony_ctx", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, readnone_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMAddFunctionAttr(value, LLVMReadNoneAttribute);
#endif

  // __object* pony_create(i8*, __Desc*)
  params[0] = c->void_ptr;
  params[1] = c->descriptor_ptr;
  type = LLVMFunctionType(c->object_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_create", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_actor_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_pool_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceable(value, 0, PONY_ACTOR_PAD_SIZE +
    (target_is_ilp32(c->opt->triple) ? 4 : 8));
#endif

  // void ponyint_destroy(__object*)
  params[0] = c->object_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "ponyint_destroy", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
#endif

  // void pony_sendv(i8*, __object*, $message*, $message*)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->msg_ptr;
  params[3] = c->msg_ptr;
  type = LLVMFunctionType(c->void_type, params, 4, false);
  value = LLVMAddFunction(c->module, "pony_sendv", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
#endif

  // void pony_sendv_single(i8*, __object*, $message*, $message*)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->msg_ptr;
  params[3] = c->msg_ptr;
  type = LLVMFunctionType(c->void_type, params, 4, false);
  value = LLVMAddFunction(c->module, "pony_sendv_single", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
#endif

  // i8* pony_alloc(i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex,
    deref_or_null_alloc_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN);
#endif

  // i8* pony_alloc_small(i8*, i32)
  params[0] = c->void_ptr;
  params[1] = c->i32;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_small", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex,
    deref_alloc_small_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceable(value, 0, HEAP_MIN);
#endif

  // i8* pony_alloc_large(i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_large", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex,
    deref_alloc_large_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceable(value, 0, HEAP_MAX << 1);
#endif

  // i8* pony_realloc(i8*, i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  params[2] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_realloc", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex,
    deref_or_null_alloc_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN);
#endif

  // i8* pony_alloc_final(i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_final", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex,
    deref_or_null_alloc_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN);
#endif

  // i8* pony_alloc_small_final(i8*, i32)
  params[0] = c->void_ptr;
  params[1] = c->i32;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_small_final", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex,
    deref_alloc_small_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceable(value, 0, HEAP_MIN);
#endif

  // i8* pony_alloc_large_final(i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_large_final", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex,
    deref_alloc_large_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceable(value, 0, HEAP_MAX << 1);
#endif

  // $message* pony_alloc_msg(i32, i32)
  params[0] = c->i32;
  params[1] = c->i32;
  type = LLVMFunctionType(c->msg_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_msg", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_pool_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
#endif

  // void pony_trace(i8*, i8*)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_trace", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, 2, readnone_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  value = LLVMGetParam(value, 1);
  LLVMAddAttribute(value, LLVMReadNoneAttribute);
#endif

  // void pony_traceknown(i8*, __object*, __Desc*, i32)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->descriptor_ptr;
  params[3] = c->i32;
  type = LLVMFunctionType(c->void_type, params, 4, false);
  value = LLVMAddFunction(c->module, "pony_traceknown", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, 2, readonly_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  value = LLVMGetParam(value, 1);
  LLVMAddAttribute(value, LLVMReadOnlyAttribute);
#endif

  // void pony_traceunknown(i8*, __object*, i32)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->i32;
  type = LLVMFunctionType(c->void_type, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_traceunknown", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, 2, readonly_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  value = LLVMGetParam(value, 1);
  LLVMAddAttribute(value, LLVMReadOnlyAttribute);
#endif

  // void pony_gc_send(i8*)
  params[0] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_gc_send", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
#endif

  // void pony_gc_recv(i8*)
  params[0] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_gc_recv", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
#endif

  // void pony_send_done(i8*)
  params[0] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_send_done", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#endif

  // void pony_recv_done(i8*)
  params[0] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_recv_done", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#endif

  // void pony_serialise_reserve(i8*, i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  params[2] = c->intptr;
  type = LLVMFunctionType(c->void_type, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_serialise_reserve", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, 2, readnone_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  value = LLVMGetParam(value, 1);
  LLVMAddAttribute(value, LLVMReadNoneAttribute);
#endif

  // intptr pony_serialise_offset(i8*, i8*)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  type = LLVMFunctionType(c->intptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_serialise_offset", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, 2, readonly_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  value = LLVMGetParam(value, 1);
  LLVMAddAttribute(value, LLVMReadOnlyAttribute);
#endif

  // i8* pony_deserialise_offset(i8*, __desc*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->descriptor_ptr;
  params[2] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_deserialise_offset", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
#elif PONY_LLVM == 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#endif

  // i8* pony_deserialise_block(i8*, intptr, intptr)
  params[0] = c->void_ptr;
  params[1] = c->intptr;
  params[2] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_deserialise_block", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr);
#else
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
  LLVMSetReturnNoAlias(value);
#endif

  // i32 pony_init(i32, i8**)
  params[0] = c->i32;
  params[1] = LLVMPointerType(c->void_ptr, 0);
  type = LLVMFunctionType(c->i32, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_init", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
#endif

  // void pony_become(i8*, __object*)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  type = LLVMFunctionType(c->void_type, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_become", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
#endif

  // i32 pony_start(i32, i32)
  params[0] = c->i32;
  params[1] = c->i32;
  type = LLVMFunctionType(c->i32, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_start", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex,
    inacc_or_arg_mem_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
#  if PONY_LLVM >= 308
  LLVMSetInaccessibleMemOrArgMemOnly(value);
#  endif
#endif

  // i32 pony_get_exitcode()
  type = LLVMFunctionType(c->i32, NULL, 0, false);
  value = LLVMAddFunction(c->module, "pony_get_exitcode", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, readonly_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMAddFunctionAttr(value, LLVMReadOnlyAttribute);
#endif

  // void pony_throw()
  type = LLVMFunctionType(c->void_type, NULL, 0, false);
  value = LLVMAddFunction(c->module, "pony_throw", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, noreturn_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoReturnAttribute);
#endif

  // i32 pony_personality_v0(...)
  type = LLVMFunctionType(c->i32, NULL, 0, true);
  c->personality = LLVMAddFunction(c->module, "pony_personality_v0", type);

  // i32 memcmp(i8*, i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  params[2] = c->intptr;
  type = LLVMFunctionType(c->i32, params, 3, false);
  value = LLVMAddFunction(c->module, "memcmp", type);
#if PONY_LLVM >= 309
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
  LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, readonly_attr);
  LLVMAddAttributeAtIndex(value, 1, readonly_attr);
  LLVMAddAttributeAtIndex(value, 2, readonly_attr);
#else
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMAddFunctionAttr(value, LLVMReadOnlyAttribute);
  LLVMValueRef param = LLVMGetParam(value, 0);
  LLVMAddAttribute(param, LLVMReadOnlyAttribute);
  param = LLVMGetParam(value, 1);
  LLVMAddAttribute(param, LLVMReadOnlyAttribute);
#endif
}
Example #11
0
File: codegen.c Project: dckc/ponyc
static void init_runtime(compile_t* c)
{
  c->str_1 = stringtab("$1");
  c->str_Bool = stringtab("Bool");
  c->str_I8 = stringtab("I8");
  c->str_I16 = stringtab("I16");
  c->str_I32 = stringtab("I32");
  c->str_I64 = stringtab("I64");
  c->str_I128 = stringtab("I128");
  c->str_U8 = stringtab("U8");
  c->str_U16 = stringtab("U16");
  c->str_U32 = stringtab("U32");
  c->str_U64 = stringtab("U64");
  c->str_U128 = stringtab("U128");
  c->str_F32 = stringtab("F32");
  c->str_F64 = stringtab("F64");
  c->str_Pointer = stringtab("Pointer");
  c->str_Array = stringtab("Array");
  c->str_Platform = stringtab("Platform");

  c->str_add = stringtab("add");
  c->str_sub = stringtab("sub");
  c->str_mul = stringtab("mul");
  c->str_div = stringtab("div");
  c->str_mod = stringtab("mod");
  c->str_neg = stringtab("neg");
  c->str_and = stringtab("op_and");
  c->str_or = stringtab("op_or");
  c->str_xor = stringtab("op_xor");
  c->str_not = stringtab("op_not");
  c->str_shl = stringtab("shl");
  c->str_shr = stringtab("shr");
  c->str_eq = stringtab("eq");
  c->str_ne = stringtab("ne");
  c->str_lt = stringtab("lt");
  c->str_le = stringtab("le");
  c->str_ge = stringtab("ge");
  c->str_gt = stringtab("gt");

  LLVMTypeRef type;
  LLVMTypeRef params[4];
  LLVMValueRef value;

  c->void_type = LLVMVoidTypeInContext(c->context);
  c->i1 = LLVMInt1TypeInContext(c->context);
  c->i8 = LLVMInt8TypeInContext(c->context);
  c->i16 = LLVMInt16TypeInContext(c->context);
  c->i32 = LLVMInt32TypeInContext(c->context);
  c->i64 = LLVMInt64TypeInContext(c->context);
  c->i128 = LLVMIntTypeInContext(c->context, 128);
  c->f32 = LLVMFloatTypeInContext(c->context);
  c->f64 = LLVMDoubleTypeInContext(c->context);
  c->intptr = LLVMIntPtrTypeInContext(c->context, c->target_data);

  // i8*
  c->void_ptr = LLVMPointerType(c->i8, 0);

  // forward declare object
  c->object_type = LLVMStructCreateNamed(c->context, "$object");
  c->object_ptr = LLVMPointerType(c->object_type, 0);

  // padding required in an actor between the descriptor and fields
  c->actor_pad = LLVMArrayType(c->i8, PONY_ACTOR_PAD_SIZE);

  // message
  params[0] = c->i32; // size
  params[1] = c->i32; // id
  c->msg_type = LLVMStructCreateNamed(c->context, "$message");
  c->msg_ptr = LLVMPointerType(c->msg_type, 0);
  LLVMStructSetBody(c->msg_type, params, 2, false);

  // trace
  // void (*)($object*)
  params[0] = c->object_ptr;
  c->trace_type = LLVMFunctionType(c->void_type, params, 1, false);
  c->trace_fn = LLVMPointerType(c->trace_type, 0);

  // dispatch
  // void (*)($object*, $message*)
  params[0] = c->object_ptr;
  params[1] = c->msg_ptr;
  c->dispatch_type = LLVMFunctionType(c->void_type, params, 2, false);
  c->dispatch_fn = LLVMPointerType(c->dispatch_type, 0);

  // void (*)($object*)
  params[0] = c->object_ptr;
  c->final_fn = LLVMPointerType(
    LLVMFunctionType(c->void_type, params, 1, false), 0);

  // descriptor, opaque version
  // We need this in order to build our own structure.
  const char* desc_name = genname_descriptor(NULL);
  c->descriptor_type = LLVMStructCreateNamed(c->context, desc_name);
  c->descriptor_ptr = LLVMPointerType(c->descriptor_type, 0);

  // field descriptor
  // Also needed to build a descriptor structure.
  params[0] = c->i32;
  params[1] = c->descriptor_ptr;
  c->field_descriptor = LLVMStructTypeInContext(c->context, params, 2, false);

  // descriptor, filled in
  c->descriptor_type = gendesc_type(c, NULL);

  // define object
  params[0] = c->descriptor_ptr;
  LLVMStructSetBody(c->object_type, params, 1, false);

  // $object* pony_create($desc*)
  params[0] = c->descriptor_ptr;
  type = LLVMFunctionType(c->object_ptr, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_create", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);

  // void pony_destroy($object*)
  params[0] = c->object_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_destroy", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  //LLVMSetReturnNoAlias(value);

  // void pony_sendv($object*, $message*);
  params[0] = c->object_ptr;
  params[1] = c->msg_ptr;
  type = LLVMFunctionType(c->void_type, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_sendv", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // i8* pony_alloc(i64)
  params[0] = c->i64;
  type = LLVMFunctionType(c->void_ptr, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_alloc", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);

  // i8* pony_realloc(i8*, i64)
  params[0] = c->void_ptr;
  params[1] = c->i64;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_realloc", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);

  // i8* pony_alloc_final(i64, c->final_fn)
  params[0] = c->i64;
  params[1] = c->final_fn;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_final", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);

  // $message* pony_alloc_msg(i32, i32)
  params[0] = c->i32;
  params[1] = c->i32;
  type = LLVMFunctionType(c->msg_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_msg", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);

  // void pony_trace(i8*)
  params[0] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_trace", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_traceactor($object*)
  params[0] = c->object_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_traceactor", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_traceobject($object*, trace_fn)
  params[0] = c->object_ptr;
  params[1] = c->trace_fn;
  type = LLVMFunctionType(c->void_type, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_traceobject", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_traceunknown($object*)
  params[0] = c->object_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_traceunknown", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_trace_tag_or_actor($object*)
  params[0] = c->object_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_trace_tag_or_actor", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_gc_send()
  type = LLVMFunctionType(c->void_type, NULL, 0, false);
  value = LLVMAddFunction(c->module, "pony_gc_send", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_gc_recv()
  type = LLVMFunctionType(c->void_type, NULL, 0, false);
  value = LLVMAddFunction(c->module, "pony_gc_recv", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_send_done()
  type = LLVMFunctionType(c->void_type, NULL, 0, false);
  value = LLVMAddFunction(c->module, "pony_send_done", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_recv_done()
  type = LLVMFunctionType(c->void_type, NULL, 0, false);
  value = LLVMAddFunction(c->module, "pony_recv_done", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // i32 pony_init(i32, i8**)
  params[0] = c->i32;
  params[1] = LLVMPointerType(c->void_ptr, 0);
  type = LLVMFunctionType(c->i32, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_init", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_become($object*)
  params[0] = c->object_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_become", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // i32 pony_start(i32)
  params[0] = c->i32;
  type = LLVMFunctionType(c->i32, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_start", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_throw()
  type = LLVMFunctionType(c->void_type, NULL, 0, false);
  LLVMAddFunction(c->module, "pony_throw", type);

  // i32 pony_personality_v0(...)
  type = LLVMFunctionType(c->i32, NULL, 0, true);
  c->personality = LLVMAddFunction(c->module, "pony_personality_v0", type);

  // i8* memcpy(...)
  type = LLVMFunctionType(c->void_ptr, NULL, 0, true);
  value = LLVMAddFunction(c->module, "memcpy", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // i8* memmove(...)
  type = LLVMFunctionType(c->void_ptr, NULL, 0, true);
  value = LLVMAddFunction(c->module, "memmove", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
}
Example #12
0
File: genexe.c Project: volth/ponyc
static void gen_main(compile_t* c, gentype_t* main_g, gentype_t* env_g)
{
  LLVMTypeRef params[3];
  params[0] = c->i32;
  params[1] = LLVMPointerType(LLVMPointerType(c->i8, 0), 0);
  params[2] = LLVMPointerType(LLVMPointerType(c->i8, 0), 0);

  LLVMTypeRef ftype = LLVMFunctionType(c->i32, params, 3, false);
  LLVMValueRef func = LLVMAddFunction(c->module, "main", ftype);

  codegen_startfun(c, func, false);

  LLVMValueRef args[3];
  args[0] = LLVMGetParam(func, 0);
  LLVMSetValueName(args[0], "argc");

  args[1] = LLVMGetParam(func, 1);
  LLVMSetValueName(args[1], "argv");

  args[2] = LLVMGetParam(func, 2);
  LLVMSetValueName(args[1], "envp");

  // Initialise the pony runtime with argc and argv, getting a new argc.
  args[0] = gencall_runtime(c, "pony_init", args, 2, "argc");

  // Create the main actor and become it.
  LLVMValueRef main_actor = create_main(c, main_g);

  // Create an Env on the main actor's heap.
  const char* env_name = "Env";
  const char* env_create = genname_fun(env_name, "_create", NULL);

  LLVMValueRef env_args[4];
  env_args[0] = gencall_alloc(c, env_g);
  env_args[1] = LLVMBuildZExt(c->builder, args[0], c->i64, "");
  env_args[2] = args[1];
  env_args[3] = args[2];

  LLVMValueRef env = gencall_runtime(c, env_create, env_args, 4, "env");
  LLVMSetInstructionCallConv(env, GEN_CALLCONV);

  // Run primitive initialisers using the main actor's heap.
  primitive_call(c, stringtab("_init"), env);

  // Create a type for the message.
  LLVMTypeRef f_params[4];
  f_params[0] = c->i32;
  f_params[1] = c->i32;
  f_params[2] = c->void_ptr;
  f_params[3] = LLVMTypeOf(env);
  LLVMTypeRef msg_type = LLVMStructTypeInContext(c->context, f_params, 4,
    false);
  LLVMTypeRef msg_type_ptr = LLVMPointerType(msg_type, 0);

  // Allocate the message, setting its size and ID.
  uint32_t index = genfun_vtable_index(c, main_g, stringtab("create"), NULL);

  size_t msg_size = LLVMABISizeOfType(c->target_data, msg_type);
  args[0] = LLVMConstInt(c->i32, pool_index(msg_size), false);
  args[1] = LLVMConstInt(c->i32, index, false);
  LLVMValueRef msg = gencall_runtime(c, "pony_alloc_msg", args, 2, "");
  LLVMValueRef msg_ptr = LLVMBuildBitCast(c->builder, msg, msg_type_ptr, "");

  // Set the message contents.
  LLVMValueRef env_ptr = LLVMBuildStructGEP(c->builder, msg_ptr, 3, "");
  LLVMBuildStore(c->builder, env, env_ptr);

  // Trace the message.
  gencall_runtime(c, "pony_gc_send", NULL, 0, "");
  const char* env_trace = genname_trace(env_name);

  args[0] = LLVMBuildBitCast(c->builder, env, c->object_ptr, "");
  args[1] = LLVMGetNamedFunction(c->module, env_trace);
  gencall_runtime(c, "pony_traceobject", args, 2, "");
  gencall_runtime(c, "pony_send_done", NULL, 0, "");

  // Send the message.
  args[0] = main_actor;
  args[1] = msg;
  gencall_runtime(c, "pony_sendv", args, 2, "");

  // Start the runtime.
  LLVMValueRef zero = LLVMConstInt(c->i32, 0, false);
  LLVMValueRef rc = gencall_runtime(c, "pony_start", &zero, 1, "");

  // Run primitive finalisers. We create a new main actor as a context to run
  // the finalisers in, but we do not initialise or schedule it.
  LLVMValueRef final_actor = create_main(c, main_g);
  primitive_call(c, stringtab("_final"), NULL);
  args[0] = final_actor;
  gencall_runtime(c, "pony_destroy", args, 1, "");

  // Return the runtime exit code.
  LLVMBuildRet(c->builder, rc);

  codegen_finishfun(c);

  // External linkage for main().
  LLVMSetLinkage(func, LLVMExternalLinkage);
}
Example #13
0
static LLVMValueRef declare_ffi(compile_t* c, const char* f_name,
  reach_type_t* t, ast_t* args, bool err, bool intrinsic)
{
  ast_t* last_arg = ast_childlast(args);

  if((last_arg != NULL) && (ast_id(last_arg) == TK_ELLIPSIS))
    return declare_ffi_vararg(c, f_name, t, err);

  int count = (int)ast_childcount(args);
  size_t buf_size = count * sizeof(LLVMTypeRef);
  LLVMTypeRef* f_params = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
  count = 0;

  ast_t* arg = ast_child(args);

  while(arg != NULL)
  {
    ast_t* p_type = ast_type(arg);

    if(p_type == NULL)
      p_type = ast_childidx(arg, 1);

    reach_type_t* pt = reach_type(c->reach, p_type);
    pony_assert(pt != NULL);

    // An intrinsic that takes a Bool should be i1, not ibool.
    if(intrinsic && is_bool(pt->ast))
      f_params[count++] = c->i1;
    else
      f_params[count++] = pt->use_type;

    arg = ast_sibling(arg);
  }

  LLVMTypeRef r_type;

  if(t->underlying == TK_TUPLETYPE)
  {
    // Can't use the named type. Build an unnamed type with the same
    // elements.
    unsigned int count = LLVMCountStructElementTypes(t->use_type);
    size_t buf_size = count * sizeof(LLVMTypeRef);
    LLVMTypeRef* e_types = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
    LLVMGetStructElementTypes(t->use_type, e_types);

    if(intrinsic)
    {
      ast_t* child = ast_child(t->ast);
      size_t i = 0;

      while(child != NULL)
      {
        // A Bool in an intrinsic tuple return type is an i1, not an ibool.
        if(is_bool(child))
          e_types[i] = c->i1;

        child = ast_sibling(child);
        i++;
      }
    }

    r_type = LLVMStructTypeInContext(c->context, e_types, count, false);
    ponyint_pool_free_size(buf_size, e_types);
  } else {
    // An intrinsic that returns a Bool returns an i1, not an ibool.
    if(intrinsic && is_bool(t->ast))
      r_type = c->i1;
    else
      r_type = t->use_type;
  }

  LLVMTypeRef f_type = LLVMFunctionType(r_type, f_params, count, false);
  LLVMValueRef func = LLVMAddFunction(c->module, f_name, f_type);

  if(!err)
  {
#if PONY_LLVM >= 309
    LLVM_DECLARE_ATTRIBUTEREF(nounwind_attr, nounwind, 0);

    LLVMAddAttributeAtIndex(func, LLVMAttributeFunctionIndex, nounwind_attr);
#else
    LLVMAddFunctionAttr(func, LLVMNoUnwindAttribute);
#endif
  }

  ponyint_pool_free_size(buf_size, f_params);
  return func;
}
Example #14
0
static LLVMTypeRef send_message(compile_t* c, ast_t* params, LLVMValueRef to,
  LLVMValueRef func, uint32_t index)
{
  // Get the parameter types.
  LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(func));
  int count = LLVMCountParamTypes(f_type) + 2;

  size_t buf_size = count * sizeof(LLVMTypeRef);
  LLVMTypeRef* f_params = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
  LLVMGetParamTypes(f_type, &f_params[2]);

  // The first one becomes the message size, the second the message ID.
  f_params[0] = c->i32;
  f_params[1] = c->i32;
  f_params[2] = c->void_ptr;
  LLVMTypeRef msg_type = LLVMStructTypeInContext(c->context, f_params, count,
    false);
  LLVMTypeRef msg_type_ptr = LLVMPointerType(msg_type, 0);
  ponyint_pool_free_size(buf_size, f_params);

  // Allocate the message, setting its size and ID.
  size_t msg_size = (size_t)LLVMABISizeOfType(c->target_data, msg_type);
  LLVMValueRef args[3];

  args[0] = LLVMConstInt(c->i32, ponyint_pool_index(msg_size), false);
  args[1] = LLVMConstInt(c->i32, index, false);
  LLVMValueRef msg = gencall_runtime(c, "pony_alloc_msg", args, 2, "");
  LLVMValueRef msg_ptr = LLVMBuildBitCast(c->builder, msg, msg_type_ptr, "");

  for(int i = 3; i < count; i++)
  {
    LLVMValueRef arg = LLVMGetParam(func, i - 2);
    LLVMValueRef arg_ptr = LLVMBuildStructGEP(c->builder, msg_ptr, i, "");
    LLVMBuildStore(c->builder, arg, arg_ptr);
  }

  // Trace while populating the message contents.
  LLVMValueRef ctx = codegen_ctx(c);

  ast_t* param = ast_child(params);
  bool need_trace = false;

  while(param != NULL)
  {
    if(gentrace_needed(ast_type(param)))
    {
      need_trace = true;
      break;
    }

    param = ast_sibling(param);
  }

  if(need_trace)
  {
    gencall_runtime(c, "pony_gc_send", &ctx, 1, "");
    param = ast_child(params);

    for(int i = 3; i < count; i++)
    {
      LLVMValueRef arg = LLVMGetParam(func, i - 2);
      gentrace(c, ctx, arg, ast_type(param));
      param = ast_sibling(param);
    }

    gencall_runtime(c, "pony_send_done", &ctx, 1, "");
  }

  // Send the message.
  args[0] = ctx;
  args[1] = LLVMBuildBitCast(c->builder, to, c->object_ptr, "");
  args[2] = msg;
  gencall_runtime(c, "pony_sendv", args, 3, "");

  // Return the type of the message.
  return msg_type_ptr;
}
Example #15
0
LLVMTypeRef ett_llvm_type(EagleComplexType *type)
{
    switch(type->type)
    {
        case ETVoid:
            return LLVMVoidTypeInContext(utl_get_current_context());
        case ETFloat:
            return LLVMFloatTypeInContext(utl_get_current_context());
        case ETDouble:
            return LLVMDoubleTypeInContext(utl_get_current_context());
        case ETInt1:
            return LLVMInt1TypeInContext(utl_get_current_context());
        case ETGeneric: // In practice this doesn't matter
        case ETAny:
        case ETInt8:
        case ETUInt8:
            return LLVMInt8TypeInContext(utl_get_current_context());
        case ETInt16:
        case ETUInt16:
            return LLVMInt16TypeInContext(utl_get_current_context());
        case ETInt32:
        case ETUInt32:
            return LLVMInt32TypeInContext(utl_get_current_context());
        case ETInt64:
        case ETUInt64:
            return LLVMInt64TypeInContext(utl_get_current_context());
        case ETCString:
            return LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0);
        case ETEnum:
            return LLVMInt64TypeInContext(utl_get_current_context());
        case ETGenerator:
        {
            if(generator_type)
                return generator_type;

            LLVMTypeRef ptmp[2];
            ptmp[0] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0);
            ptmp[1] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0);

            generator_type = LLVMStructCreateNamed(utl_get_current_context(), "__egl_gen_strct");
            LLVMStructSetBody(generator_type, ptmp, 2, 0);
            return generator_type;
        }
        case ETClass:
        case ETStruct:
        {
            EagleStructType *st = (EagleStructType *)type;
            LLVMTypeRef loaded = LLVMGetTypeByName(the_module, st->name);
            if(loaded)
                return loaded;

            return NULL;
           // LLVMTypeRef ty = LLVMStructTypeInContext(utl_get_current_context(),
        }
        case ETInterface:
        {
            return LLVMInt8TypeInContext(utl_get_current_context());
        }
        case ETPointer:
        {
            EaglePointerType *pt = (EaglePointerType *)type;
            if(pt->counted || pt->weak)
            {
                LLVMTypeRef ptmp[2];
                ptmp[0] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0);
                ptmp[1] = LLVMInt1TypeInContext(utl_get_current_context());

                LLVMTypeRef tys[6];
                tys[0] = LLVMInt64TypeInContext(utl_get_current_context());
                tys[1] = LLVMInt16TypeInContext(utl_get_current_context());
                tys[2] = LLVMInt16TypeInContext(utl_get_current_context());
                tys[3] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0);
                tys[4] = LLVMPointerType(LLVMFunctionType(LLVMVoidTypeInContext(utl_get_current_context()), ptmp, 2, 0), 0);
                tys[5] = ett_llvm_type(pt->to);

                return LLVMPointerType(ty_get_counted(LLVMStructTypeInContext(utl_get_current_context(), tys, 6, 0)), 0);
            }
            return LLVMPointerType(ett_llvm_type(((EaglePointerType *)type)->to), 0);
        }
        case ETArray:
            {
                EagleArrayType *at = (EagleArrayType *)type;
                if(at->ct < 0)
                    return LLVMPointerType(ett_llvm_type(at->of), 0);
                else
                    return LLVMArrayType(ett_llvm_type(at->of), at->ct);
            }
        case ETFunction:
            {
                EagleFunctionType *ft = (EagleFunctionType *)type;
                if(ET_IS_CLOSURE(type))
                {
                    LLVMTypeRef tys[2];
                    tys[0] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0);
                    tys[1] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0);
                    return LLVMStructTypeInContext(utl_get_current_context(), tys, 2, 0);
                }

                LLVMTypeRef *tys = malloc(sizeof(LLVMTypeRef) * ft->pct);
                int i;
                for(i = 0; i < ft->pct; i++)
                    tys[i] = ett_llvm_type(ft->params[i]);
                LLVMTypeRef out = LLVMFunctionType(ett_llvm_type(ft->retType), tys, ft->pct, 0);
                free(tys);
                return out;
            }
        default:
            return NULL;
    }
}
Example #16
0
static void init_runtime(compile_t* c)
{
  c->str_builtin = stringtab("$0");
  c->str_Bool = stringtab("Bool");
  c->str_I8 = stringtab("I8");
  c->str_I16 = stringtab("I16");
  c->str_I32 = stringtab("I32");
  c->str_I64 = stringtab("I64");
  c->str_I128 = stringtab("I128");
  c->str_ILong = stringtab("ILong");
  c->str_ISize = stringtab("ISize");
  c->str_U8 = stringtab("U8");
  c->str_U16 = stringtab("U16");
  c->str_U32 = stringtab("U32");
  c->str_U64 = stringtab("U64");
  c->str_U128 = stringtab("U128");
  c->str_ULong = stringtab("ULong");
  c->str_USize = stringtab("USize");
  c->str_F32 = stringtab("F32");
  c->str_F64 = stringtab("F64");
  c->str_Pointer = stringtab("Pointer");
  c->str_Maybe = stringtab("MaybePointer");
  c->str_DoNotOptimise = stringtab("DoNotOptimise");
  c->str_Array = stringtab("Array");
  c->str_String = stringtab("String");
  c->str_Platform = stringtab("Platform");
  c->str_Main = stringtab("Main");
  c->str_Env = stringtab("Env");

  c->str_add = stringtab("add");
  c->str_sub = stringtab("sub");
  c->str_mul = stringtab("mul");
  c->str_div = stringtab("div");
  c->str_mod = stringtab("mod");
  c->str_neg = stringtab("neg");
  c->str_and = stringtab("op_and");
  c->str_or = stringtab("op_or");
  c->str_xor = stringtab("op_xor");
  c->str_not = stringtab("op_not");
  c->str_shl = stringtab("shl");
  c->str_shr = stringtab("shr");
  c->str_eq = stringtab("eq");
  c->str_ne = stringtab("ne");
  c->str_lt = stringtab("lt");
  c->str_le = stringtab("le");
  c->str_ge = stringtab("ge");
  c->str_gt = stringtab("gt");

  c->str_this = stringtab("this");
  c->str_create = stringtab("create");
  c->str__create = stringtab("_create");
  c->str__init = stringtab("_init");
  c->str__final = stringtab("_final");
  c->str__event_notify = stringtab("_event_notify");

  LLVMTypeRef type;
  LLVMTypeRef params[5];
  LLVMValueRef value;

  c->void_type = LLVMVoidTypeInContext(c->context);
  c->ibool = LLVMInt8TypeInContext(c->context);
  c->i1 = LLVMInt1TypeInContext(c->context);
  c->i8 = LLVMInt8TypeInContext(c->context);
  c->i16 = LLVMInt16TypeInContext(c->context);
  c->i32 = LLVMInt32TypeInContext(c->context);
  c->i64 = LLVMInt64TypeInContext(c->context);
  c->i128 = LLVMIntTypeInContext(c->context, 128);
  c->f32 = LLVMFloatTypeInContext(c->context);
  c->f64 = LLVMDoubleTypeInContext(c->context);
  c->intptr = LLVMIntPtrTypeInContext(c->context, c->target_data);

  // i8*
  c->void_ptr = LLVMPointerType(c->i8, 0);

  // forward declare object
  c->object_type = LLVMStructCreateNamed(c->context, "__object");
  c->object_ptr = LLVMPointerType(c->object_type, 0);

  // padding required in an actor between the descriptor and fields
  c->actor_pad = LLVMArrayType(c->i8, PONY_ACTOR_PAD_SIZE);

  // message
  params[0] = c->i32; // size
  params[1] = c->i32; // id
  c->msg_type = LLVMStructCreateNamed(c->context, "__message");
  c->msg_ptr = LLVMPointerType(c->msg_type, 0);
  LLVMStructSetBody(c->msg_type, params, 2, false);

  // trace
  // void (*)(i8*, __object*)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  c->trace_type = LLVMFunctionType(c->void_type, params, 2, false);
  c->trace_fn = LLVMPointerType(c->trace_type, 0);

  // serialise
  // void (*)(i8*, __object*, i8*, intptr, i32)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->void_ptr;
  params[3] = c->intptr;
  params[4] = c->i32;
  c->serialise_type = LLVMFunctionType(c->void_type, params, 5, false);
  c->serialise_fn = LLVMPointerType(c->serialise_type, 0);

  // dispatch
  // void (*)(i8*, __object*, $message*)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->msg_ptr;
  c->dispatch_type = LLVMFunctionType(c->void_type, params, 3, false);
  c->dispatch_fn = LLVMPointerType(c->dispatch_type, 0);

  // void (*)(__object*)
  params[0] = c->object_ptr;
  c->final_fn = LLVMPointerType(
    LLVMFunctionType(c->void_type, params, 1, false), 0);

  // descriptor, opaque version
  // We need this in order to build our own structure.
  const char* desc_name = genname_descriptor(NULL);
  c->descriptor_type = LLVMStructCreateNamed(c->context, desc_name);
  c->descriptor_ptr = LLVMPointerType(c->descriptor_type, 0);

  // field descriptor
  // Also needed to build a descriptor structure.
  params[0] = c->i32;
  params[1] = c->descriptor_ptr;
  c->field_descriptor = LLVMStructTypeInContext(c->context, params, 2, false);

  // descriptor, filled in
  gendesc_basetype(c, c->descriptor_type);

  // define object
  params[0] = c->descriptor_ptr;
  LLVMStructSetBody(c->object_type, params, 1, false);

  // $i8* pony_ctx()
  type = LLVMFunctionType(c->void_ptr, NULL, 0, false);
  value = LLVMAddFunction(c->module, "pony_ctx", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMAddFunctionAttr(value, LLVMReadNoneAttribute);

  // __object* pony_create(i8*, __Desc*)
  params[0] = c->void_ptr;
  params[1] = c->descriptor_ptr;
  type = LLVMFunctionType(c->object_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_create", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceable(value, 0, PONY_ACTOR_PAD_SIZE);

  // void ponyint_destroy(__object*)
  params[0] = c->object_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "ponyint_destroy", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_sendv(i8*, __object*, $message*);
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->msg_ptr;
  type = LLVMFunctionType(c->void_type, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_sendv", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // i8* pony_alloc(i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);
#if PONY_LLVM >= 307
  LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN);
#endif

  // i8* pony_alloc_small(i8*, i32)
  params[0] = c->void_ptr;
  params[1] = c->i32;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_small", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceable(value, 0, HEAP_MIN);

  // i8* pony_alloc_large(i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_large", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);
  LLVMSetDereferenceable(value, 0, HEAP_MAX + 1);

  // i8* pony_realloc(i8*, i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  params[2] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_realloc", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);
#if PONY_LLVM >= 307
  LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN);
#endif

  // i8* pony_alloc_final(i8*, intptr, c->final_fn)
  params[0] = c->void_ptr;
  params[1] = c->intptr;
  params[2] = c->final_fn;
  type = LLVMFunctionType(c->void_ptr, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_alloc_final", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);
#if PONY_LLVM >= 307
  LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN);
#endif

  // $message* pony_alloc_msg(i32, i32)
  params[0] = c->i32;
  params[1] = c->i32;
  type = LLVMFunctionType(c->msg_ptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_alloc_msg", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
  LLVMSetReturnNoAlias(value);

  // void pony_trace(i8*, i8*)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_trace", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // i8* pony_traceobject(i8*, __object*, __Desc*, i32)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->descriptor_ptr;
  params[3] = c->i32;
  type = LLVMFunctionType(c->void_ptr, params, 4, false);
  value = LLVMAddFunction(c->module, "pony_traceknown", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // i8* pony_traceunknown(i8*, __object*, i32)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  params[2] = c->i32;
  type = LLVMFunctionType(c->void_ptr, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_traceunknown", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_gc_send(i8*)
  params[0] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_gc_send", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_gc_recv(i8*)
  params[0] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_gc_recv", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_send_done(i8*)
  params[0] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_send_done", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_recv_done(i8*)
  params[0] = c->void_ptr;
  type = LLVMFunctionType(c->void_type, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_recv_done", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_serialise_reserve(i8*, i8*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  params[2] = c->intptr;
  type = LLVMFunctionType(c->void_type, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_serialise_reserve", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // intptr pony_serialise_offset(i8*, i8*)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  type = LLVMFunctionType(c->intptr, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_serialise_offset", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // i8* pony_deserialise_offset(i8*, __desc*, intptr)
  params[0] = c->void_ptr;
  params[1] = c->descriptor_ptr;
  params[2] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_deserialise_offset", type);

  // i8* pony_deserialise_block(i8*, intptr, intptr)
  params[0] = c->void_ptr;
  params[1] = c->intptr;
  params[2] = c->intptr;
  type = LLVMFunctionType(c->void_ptr, params, 3, false);
  value = LLVMAddFunction(c->module, "pony_deserialise_block", type);

  // i32 pony_init(i32, i8**)
  params[0] = c->i32;
  params[1] = LLVMPointerType(c->void_ptr, 0);
  type = LLVMFunctionType(c->i32, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_init", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_become(i8*, __object*)
  params[0] = c->void_ptr;
  params[1] = c->object_ptr;
  type = LLVMFunctionType(c->void_type, params, 2, false);
  value = LLVMAddFunction(c->module, "pony_become", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // i32 pony_start(i32)
  params[0] = c->i32;
  type = LLVMFunctionType(c->i32, params, 1, false);
  value = LLVMAddFunction(c->module, "pony_start", type);
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void pony_throw()
  type = LLVMFunctionType(c->void_type, NULL, 0, false);
  LLVMAddFunction(c->module, "pony_throw", type);

  // i32 pony_personality_v0(...)
  type = LLVMFunctionType(c->i32, NULL, 0, true);
  c->personality = LLVMAddFunction(c->module, "pony_personality_v0", type);

  // void llvm.memcpy.*(i8*, i8*, i32/64, i32, i1)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  params[3] = c->i32;
  params[4] = c->i1;
  if(target_is_ilp32(c->opt->triple))
  {
    params[2] = c->i32;
    type = LLVMFunctionType(c->void_type, params, 5, false);
    value = LLVMAddFunction(c->module, "llvm.memcpy.p0i8.p0i8.i32", type);
  } else {
    params[2] = c->i64;
    type = LLVMFunctionType(c->void_type, params, 5, false);
    value = LLVMAddFunction(c->module, "llvm.memcpy.p0i8.p0i8.i64", type);
  }
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);

  // void llvm.memmove.*(i8*, i8*, i32/64, i32, i1)
  params[0] = c->void_ptr;
  params[1] = c->void_ptr;
  params[3] = c->i32;
  params[4] = c->i1;
  if(target_is_ilp32(c->opt->triple))
  {
    params[2] = c->i32;
    type = LLVMFunctionType(c->void_type, params, 5, false);
    value = LLVMAddFunction(c->module, "llvm.memmove.p0i8.p0i8.i32", type);
  } else {
    params[2] = c->i64;
    type = LLVMFunctionType(c->void_type, params, 5, false);
    value = LLVMAddFunction(c->module, "llvm.memmove.p0i8.p0i8.i64", type);
  }
  LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute);
}
Example #17
0
static LLVMValueRef declare_ffi(compile_t* c, const char* f_name,
  gentype_t* g, ast_t* args, bool err)
{
  ast_t* last_arg = ast_childlast(args);

  if((last_arg != NULL) && (ast_id(last_arg) == TK_ELLIPSIS))
    return declare_ffi_vararg(c, f_name, g, err);

  int count = (int)ast_childcount(args);
  size_t buf_size = count * sizeof(LLVMTypeRef);
  LLVMTypeRef* f_params = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
  count = 0;

  ast_t* arg = ast_child(args);

  while(arg != NULL)
  {
    ast_t* p_type = ast_type(arg);

    if(p_type == NULL)
      p_type = ast_childidx(arg, 1);

    gentype_t param_g;

    if(!gentype(c, p_type, &param_g))
      return NULL;

    f_params[count++] = param_g.use_type;
    arg = ast_sibling(arg);
  }

  // We may have generated the function by generating a parameter type.
  LLVMValueRef func = LLVMGetNamedFunction(c->module, f_name);

  if(func == NULL)
  {
    LLVMTypeRef r_type;

    if(g->underlying == TK_TUPLETYPE)
    {
      // Can't use the named type. Build an unnamed type with the same
      // elements.
      unsigned int count = LLVMCountStructElementTypes(g->use_type);
      size_t buf_size = count * sizeof(LLVMTypeRef);
      LLVMTypeRef* e_types = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
      LLVMGetStructElementTypes(g->use_type, e_types);
      r_type = LLVMStructTypeInContext(c->context, e_types, count, false);
      ponyint_pool_free_size(buf_size, e_types);
    } else {
      r_type = g->use_type;
    }

    LLVMTypeRef f_type = LLVMFunctionType(r_type, f_params, count, false);
    func = LLVMAddFunction(c->module, f_name, f_type);

    if(!err)
      LLVMAddFunctionAttr(func, LLVMNoUnwindAttribute);
  }

  ponyint_pool_free_size(buf_size, f_params);
  return func;
}
Example #18
0
		}
		if(names_p != NULL) {
			g_ptr_array_add(names, g_strdup(members[i].name));
		}
	}
	g_free(members);

	if(names_p != NULL) {
		char **namev = g_new(char *, names->len + 1);
		for(int i=0; i<names->len; i++) namev[i] = names->pdata[i];
		namev[names->len] = NULL;
		g_ptr_array_free(names, TRUE);
		(*names_p) = namev;
	}

	T ret = LLVMStructTypeInContext(ctx->ctx, &g_array_index(types, T, 0),
		types->len, is_packed(type) ? 1 : 0);
	g_array_free(types, TRUE);
	return ret;
}


/* arrays, while rigid according to is_rigid_type(), don't have a distinct LLVM
 * representation.
 */
LLVMTypeRef llvm_rigid_type(struct llvm_ctx *ctx, IDL_tree type)
{
	if(type == NULL) return LLVMVoidTypeInContext(ctx->ctx);
	switch(IDL_NODE_TYPE(type)) {
		case IDLN_TYPE_STRUCT:
			return llvm_struct_type(ctx, NULL, type);
Example #19
0
LLVMValueRef gen_try(compile_t* c, ast_t* ast)
{
  bool needed = is_result_needed(ast);
  AST_GET_CHILDREN(ast, body, else_clause, then_clause);

  ast_t* type = ast_type(ast);
  ast_t* body_type = ast_type(body);
  ast_t* else_type = ast_type(else_clause);

  reach_type_t* phi_type = NULL;

  // We will have no type if both branches have return statements.
  if(!is_control_type(type))
    phi_type = reach_type(c->reach, type);

  LLVMBasicBlockRef block = LLVMGetInsertBlock(c->builder);
  LLVMBasicBlockRef else_block = codegen_block(c, "try_else");
  LLVMBasicBlockRef post_block = NULL;

  if(!is_control_type(type))
    post_block = codegen_block(c, "try_post");

  // Keep a reference to the else block.
  codegen_pushtry(c, else_block);

  // Body block.
  LLVMPositionBuilderAtEnd(c->builder, block);
  LLVMValueRef body_value = gen_expr(c, body);

  if(body_value != GEN_NOVALUE)
  {
    if(needed)
    {
      body_value = gen_assign_cast(c, phi_type->use_type, body_value,
        body_type);
    }

    if(body_value == NULL)
      return NULL;

    gen_expr(c, then_clause);
    block = LLVMGetInsertBlock(c->builder);
    LLVMBuildBr(c->builder, post_block);
  }

  // Pop the try before generating the else block.
  codegen_poptry(c);

  // Else block.
  LLVMPositionBuilderAtEnd(c->builder, else_block);

  // The landing pad is marked as a cleanup, since exceptions are typeless and
  // valueless. The first landing pad is always the destination.
  LLVMTypeRef lp_elements[2];
  lp_elements[0] = c->void_ptr;
  lp_elements[1] = c->i32;
  LLVMTypeRef lp_type = LLVMStructTypeInContext(c->context, lp_elements, 2,
    false);

#if PONY_LLVM == 307 && LLVM_VERSION_PATCH == 0
  // This backwards-incompatible API change to LLVMBuildLandingPad is only in
  // LLVM 3.7.0. In 3.7.1 and all later versions, backward-compatibility was
  // restored.
  assert((c->frame->fun != NULL) && "No function in current frame!");
  LLVMSetPersonalityFn(c->frame->fun, c->personality);
  LLVMValueRef landing = LLVMBuildLandingPad(c->builder, lp_type, 1, "");
#else
  LLVMValueRef landing = LLVMBuildLandingPad(c->builder, lp_type,
    c->personality, 1, "");
#endif

  LLVMAddClause(landing, LLVMConstNull(c->void_ptr));

  LLVMValueRef else_value = gen_expr(c, else_clause);

  if(else_value != GEN_NOVALUE)
  {
    if(needed)
    {
      else_value = gen_assign_cast(c, phi_type->use_type, else_value,
        else_type);
    }

    if(else_value == NULL)
      return NULL;

    gen_expr(c, then_clause);

    else_block = LLVMGetInsertBlock(c->builder);
    LLVMBuildBr(c->builder, post_block);
  }

  // If both sides return, we return a sentinal value.
  if(is_control_type(type))
    return GEN_NOVALUE;

  // Continue in the post block.
  LLVMPositionBuilderAtEnd(c->builder, post_block);

  if(needed)
  {
    LLVMValueRef phi = LLVMBuildPhi(c->builder, phi_type->use_type, "");

    if(body_value != GEN_NOVALUE)
      LLVMAddIncoming(phi, &body_value, &block, 1);

    if(else_value != GEN_NOVALUE)
      LLVMAddIncoming(phi, &else_value, &else_block, 1);

    return phi;
  }

  return GEN_NOTNEEDED;
}
Example #20
0
static void gen_main(compile_t* c, reach_type_t* t_main,
  reach_type_t* t_env)
{
  LLVMTypeRef params[3];
  params[0] = c->i32;
  params[1] = LLVMPointerType(LLVMPointerType(c->i8, 0), 0);
  params[2] = LLVMPointerType(LLVMPointerType(c->i8, 0), 0);

  LLVMTypeRef ftype = LLVMFunctionType(c->i32, params, 3, false);
  LLVMValueRef func = LLVMAddFunction(c->module, "main", ftype);

  codegen_startfun(c, func, NULL, NULL);

  LLVMValueRef args[4];
  args[0] = LLVMGetParam(func, 0);
  LLVMSetValueName(args[0], "argc");

  args[1] = LLVMGetParam(func, 1);
  LLVMSetValueName(args[1], "argv");

  args[2] = LLVMGetParam(func, 2);
  LLVMSetValueName(args[2], "envp");

  // Initialise the pony runtime with argc and argv, getting a new argc.
  args[0] = gencall_runtime(c, "pony_init", args, 2, "argc");

  // Create the main actor and become it.
  LLVMValueRef ctx = gencall_runtime(c, "pony_ctx", NULL, 0, "");
  codegen_setctx(c, ctx);
  LLVMValueRef main_actor = create_main(c, t_main, ctx);

  // Create an Env on the main actor's heap.
  reach_method_t* m = reach_method(t_env, TK_NONE, c->str__create, NULL);

  LLVMValueRef env_args[4];
  env_args[0] = gencall_alloc(c, t_env);
  env_args[1] = args[0];
  env_args[2] = LLVMBuildBitCast(c->builder, args[1], c->void_ptr, "");
  env_args[3] = LLVMBuildBitCast(c->builder, args[2], c->void_ptr, "");
  codegen_call(c, m->func, env_args, 4);
  LLVMValueRef env = env_args[0];

  // Run primitive initialisers using the main actor's heap.
  primitive_call(c, c->str__init);

  // Create a type for the message.
  LLVMTypeRef f_params[4];
  f_params[0] = c->i32;
  f_params[1] = c->i32;
  f_params[2] = c->void_ptr;
  f_params[3] = LLVMTypeOf(env);
  LLVMTypeRef msg_type = LLVMStructTypeInContext(c->context, f_params, 4,
    false);
  LLVMTypeRef msg_type_ptr = LLVMPointerType(msg_type, 0);

  // Allocate the message, setting its size and ID.
  uint32_t index = reach_vtable_index(t_main, c->str_create);
  size_t msg_size = (size_t)LLVMABISizeOfType(c->target_data, msg_type);
  args[0] = LLVMConstInt(c->i32, ponyint_pool_index(msg_size), false);
  args[1] = LLVMConstInt(c->i32, index, false);
  LLVMValueRef msg = gencall_runtime(c, "pony_alloc_msg", args, 2, "");
  LLVMValueRef msg_ptr = LLVMBuildBitCast(c->builder, msg, msg_type_ptr, "");

  // Set the message contents.
  LLVMValueRef env_ptr = LLVMBuildStructGEP(c->builder, msg_ptr, 3, "");
  LLVMBuildStore(c->builder, env, env_ptr);

  // Trace the message.
  args[0] = ctx;
  gencall_runtime(c, "pony_gc_send", args, 1, "");

  args[0] = ctx;
  args[1] = LLVMBuildBitCast(c->builder, env, c->object_ptr, "");
  args[2] = LLVMBuildBitCast(c->builder, t_env->desc, c->descriptor_ptr, "");
  args[3] = LLVMConstInt(c->i32, PONY_TRACE_IMMUTABLE, false);
  gencall_runtime(c, "pony_traceknown", args, 4, "");

  args[0] = ctx;
  gencall_runtime(c, "pony_send_done", args, 1, "");

  // Send the message.
  args[0] = ctx;
  args[1] = main_actor;
  args[2] = msg;
  gencall_runtime(c, "pony_sendv", args, 3, "");

  // Start the runtime.
  LLVMValueRef zero = LLVMConstInt(c->i32, 0, false);
  LLVMValueRef rc = gencall_runtime(c, "pony_start", &zero, 1, "");

  // Run primitive finalisers. We create a new main actor as a context to run
  // the finalisers in, but we do not initialise or schedule it.
  if(need_primitive_call(c, c->str__final))
  {
    LLVMValueRef final_actor = create_main(c, t_main, ctx);
    primitive_call(c, c->str__final);
    args[0] = final_actor;
    gencall_runtime(c, "ponyint_destroy", args, 1, "");
  }

  // Return the runtime exit code.
  LLVMBuildRet(c->builder, rc);

  codegen_finishfun(c);

  // External linkage for main().
  LLVMSetLinkage(func, LLVMExternalLinkage);
}
Example #21
0
LLVMValueRef gen_ffi(compile_t* c, ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, typeargs, args);

  // Get the function name, +1 to skip leading @
  const char* f_name = ast_name(id) + 1;

  // Generate the return type.
  ast_t* type = ast_type(ast);
  gentype_t g;

  // Emit dwarf location of ffi call
  dwarf_location(&c->dwarf, ast);

  if(!gentype(c, type, &g))
    return NULL;

  // Get the function.
  LLVMValueRef func = LLVMGetNamedFunction(c->module, f_name);

  if(func == NULL)
  {
    // If we have no prototype, declare one.
    if(!strncmp(f_name, "llvm.", 5))
    {
      // Intrinsic, so use the exact types we supply.
      int count = (int)ast_childcount(args);
      size_t buf_size = count * sizeof(LLVMTypeRef);
      LLVMTypeRef* f_params = (LLVMTypeRef*)pool_alloc_size(buf_size);
      count = 0;

      ast_t* arg = ast_child(args);

      while(arg != NULL)
      {
        ast_t* p_type = ast_type(arg);
        gentype_t param_g;

        if(!gentype(c, p_type, &param_g))
          return NULL;

        f_params[count++] = param_g.use_type;
        arg = ast_sibling(arg);
      }

      // We may have generated the function by generating a parameter type.
      func = LLVMGetNamedFunction(c->module, f_name);

      if(func == NULL)
      {
        LLVMTypeRef r_type;

        if(g.underlying == TK_TUPLETYPE)
        {
          // Can't use the named type. Build an unnamed type with the same
          // elements.
          unsigned int count = LLVMCountStructElementTypes(g.use_type);
          size_t buf_size = count * sizeof(LLVMTypeRef);
          LLVMTypeRef* e_types = (LLVMTypeRef*)pool_alloc_size(buf_size);
          LLVMGetStructElementTypes(g.use_type, e_types);
          r_type = LLVMStructTypeInContext(c->context, e_types, count, false);
          pool_free_size(buf_size, e_types);
        } else {
          r_type = g.use_type;
        }

        LLVMTypeRef f_type = LLVMFunctionType(r_type, f_params, count,
          false);
        func = LLVMAddFunction(c->module, f_name, f_type);

        if(!ast_canerror(ast))
          LLVMAddFunctionAttr(func, LLVMNoUnwindAttribute);
      }

      pool_free_size(buf_size, f_params);
    } else {
      // Make it varargs.
      LLVMTypeRef f_type = LLVMFunctionType(g.use_type, NULL, 0, true);
      func = LLVMAddFunction(c->module, f_name, f_type);

      if(!ast_canerror(ast))
        LLVMAddFunctionAttr(func, LLVMNoUnwindAttribute);
    }
  }

  // Generate the arguments.
  int count = (int)ast_childcount(args);
  size_t buf_size = count * sizeof(LLVMValueRef);
  LLVMValueRef* f_args = (LLVMValueRef*)pool_alloc_size(buf_size);
  ast_t* arg = ast_child(args);

  for(int i = 0; i < count; i++)
  {
    f_args[i] = gen_expr(c, arg);

    if(f_args[i] == NULL)
    {
      pool_free_size(buf_size, f_args);
      return NULL;
    }

    arg = ast_sibling(arg);
  }

  // If we can error out and we have an invoke target, generate an invoke
  // instead of a call.
  LLVMValueRef result;

  if(ast_canerror(ast) && (c->frame->invoke_target != NULL))
    result = invoke_fun(c, func, f_args, count, "", false);
  else
    result = LLVMBuildCall(c->builder, func, f_args, count, "");

  pool_free_size(buf_size, f_args);

  // Special case a None return value, which is used for void functions.
  if(is_none(type))
    return g.instance;

  return result;
}