Пример #1
0
static LLVMValueRef
CreateFibFunction(LLVMModuleRef M, LLVMContextRef Context)
{
	LLVMBuilderRef B = LLVMCreateBuilderInContext(Context);

	// Create the fib function and insert it into module M. This function is said
	// to return an int and take an int parameter.
	LLVMTypeRef  ParamTypes[] = {LLVMInt32TypeInContext(Context)};
	LLVMTypeRef  ReturnType   = LLVMInt32TypeInContext(Context);
	LLVMTypeRef  FunctionTy   = LLVMFunctionType(ReturnType, ParamTypes, 1, 0);
	LLVMValueRef FibF         = LLVMAddFunction(M, "fib", FunctionTy);

	// Add a basic block to the function.
	LLVMBasicBlockRef BB = LLVMAppendBasicBlockInContext(Context, FibF, "EntryBlock");

	// Get pointers to the constants.
	LLVMValueRef One = LLVMConstInt(LLVMInt32TypeInContext(Context), 1, 0);
	LLVMValueRef Two = LLVMConstInt(LLVMInt32TypeInContext(Context), 2, 0);

	// Get pointer to the integer argument of the add1 function...
	LLVMValueRef ArgX = LLVMGetFirstParam(FibF); // Get the arg.
	LLVMSetValueName(ArgX, "AnArg");             // Give it a nice symbolic name for fun.

	// Create the true_block.
	LLVMBasicBlockRef RetBB = LLVMAppendBasicBlockInContext(Context, FibF, "return");

	// Create an exit block.
	LLVMBasicBlockRef RecurseBB = LLVMAppendBasicBlockInContext(Context, FibF, "recurse");

	// Create the "if (arg <= 2) goto exitbb"
	LLVMPositionBuilderAtEnd(B, BB);
	LLVMValueRef CondInst = LLVMBuildICmp(B, LLVMIntSLE, ArgX, Two, "cond");
	LLVMBuildCondBr(B, CondInst, RetBB, RecurseBB);

	// Create: ret int 1
	LLVMPositionBuilderAtEnd(B, RetBB);
	LLVMBuildRet(B, One);

	// create fib(x-1)
	LLVMPositionBuilderAtEnd(B, RecurseBB);
	LLVMValueRef Sub       = LLVMBuildSub(B, ArgX, One, "arg");
	LLVMValueRef CallFibX1 = LLVMBuildCall(B, FibF, &Sub, 1, "fibx1");
	LLVMSetTailCall(CallFibX1, 1);

	// create fib(x-2)
	LLVMPositionBuilderAtEnd(B, RecurseBB);
	Sub                    = LLVMBuildSub(B, ArgX, Two, "arg");
	LLVMValueRef CallFibX2 = LLVMBuildCall(B, FibF, &Sub, 1, "fibx2");
	LLVMSetTailCall(CallFibX2, 1);

	// fib(x-1)+fib(x-2)
	LLVMPositionBuilderAtEnd(B, RecurseBB);
	LLVMValueRef Sum = LLVMBuildAdd(B, CallFibX1, CallFibX2, "addresult");

	// Create the return instruction and add it to the basic block
	LLVMPositionBuilderAtEnd(B, RecurseBB);
	LLVMBuildRet(B, Sum);

	return FibF;
}
Пример #2
0
Output::Output(LContext context)
    : IntrinsicRepository(context)
    , m_function(0)
    , m_heaps(0)
    , m_builder(LLVMCreateBuilderInContext(m_context))
    , m_block(0)
    , m_nextBlock(0)
{
}
Пример #3
0
static void init_module(compile_t* c, ast_t* program, pass_opt_t* opt)
{
  c->opt = opt;

  // Get the first package and the builtin package.
  ast_t* package = ast_child(program);
  ast_t* builtin = ast_sibling(package);

  // If we have only one package, we are compiling builtin itself.
  if(builtin == NULL)
    builtin = package;

  c->reach = reach_new();

  // The name of the first package is the name of the program.
  c->filename = package_filename(package);

  // LLVM context and machine settings.
  if(c->opt->library || target_is_ilp32(opt->triple))
    c->callconv = LLVMCCallConv;
  else
    c->callconv = LLVMFastCallConv;

  if(!c->opt->release || c->opt->library || c->opt->extfun)
    c->linkage = LLVMExternalLinkage;
  else
    c->linkage = LLVMPrivateLinkage;

  c->context = LLVMContextCreate();
  c->machine = make_machine(opt);
  c->target_data = LLVMGetTargetMachineData(c->machine);

  // Create a module.
  c->module = LLVMModuleCreateWithNameInContext(c->filename, c->context);

  // Set the target triple.
  LLVMSetTarget(c->module, opt->triple);

  // Set the data layout.
  char* layout = LLVMCopyStringRepOfTargetData(c->target_data);
  LLVMSetDataLayout(c->module, layout);
  LLVMDisposeMessage(layout);

  // IR builder.
  c->builder = LLVMCreateBuilderInContext(c->context);
  c->di = LLVMNewDIBuilder(c->module);

  // TODO: what LANG id should be used?
  c->di_unit = LLVMDIBuilderCreateCompileUnit(c->di, 0x0004,
    package_filename(package), package_path(package), "ponyc-" PONY_VERSION,
    c->opt->release);

  // Empty frame stack.
  c->frame = NULL;
}
Пример #4
0
static LLVMBuilderRef
create_builder_at_entry(struct gallivm_state *gallivm)
{
   LLVMBuilderRef builder = gallivm->builder;
   LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
   LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
   LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
   LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
   LLVMBuilderRef first_builder = LLVMCreateBuilderInContext(gallivm->context);

   if (first_instr) {
      LLVMPositionBuilderBefore(first_builder, first_instr);
   } else {
      LLVMPositionBuilderAtEnd(first_builder, first_block);
   }

   return first_builder;
}
Пример #5
0
static void init_module(compile_t* c, ast_t* program, pass_opt_t* opt)
{
  c->opt = opt;

  // Get the first package and the builtin package.
  ast_t* package = ast_child(program);
  ast_t* builtin = ast_sibling(package);

  // If we have only one package, we are compiling builtin itself.
  if(builtin == NULL)
    builtin = package;

  c->reachable = reach_new();
  reach_primitives(c->reachable, opt, builtin);

  // The name of the first package is the name of the program.
  c->filename = package_filename(package);

  // LLVM context and machine settings.
  c->context = LLVMContextCreate();
  c->machine = make_machine(opt);
  c->target_data = LLVMGetTargetMachineData(c->machine);

  // Create a module.
  c->module = LLVMModuleCreateWithNameInContext(c->filename, c->context);

  // Set the target triple.
  LLVMSetTarget(c->module, opt->triple);

  // Set the data layout.
  char* layout = LLVMCopyStringRepOfTargetData(c->target_data);
  LLVMSetDataLayout(c->module, layout);
  LLVMDisposeMessage(layout);

  // IR builder.
  c->builder = LLVMCreateBuilderInContext(c->context);

  // Empty frame stack.
  c->frame = NULL;
}
Пример #6
0
LLVMBuilderRef ac_create_builder(LLVMContextRef ctx,
				 enum ac_float_mode float_mode)
{
	LLVMBuilderRef builder = LLVMCreateBuilderInContext(ctx);

	llvm::FastMathFlags flags;

	switch (float_mode) {
	case AC_FLOAT_MODE_DEFAULT:
		break;
	case AC_FLOAT_MODE_NO_SIGNED_ZEROS_FP_MATH:
		flags.setNoSignedZeros();
		llvm::unwrap(builder)->setFastMathFlags(flags);
		break;
	case AC_FLOAT_MODE_UNSAFE_FP_MATH:
		flags.setFast();
		llvm::unwrap(builder)->setFastMathFlags(flags);
		break;
	}

	return builder;
}
Пример #7
0
/**
 * Allocate gallivm LLVM objects.
 * \return  TRUE for success, FALSE for failure
 */
static boolean
init_gallivm_state(struct gallivm_state *gallivm)
{
   assert(!gallivm->context);
   assert(!gallivm->module);
   assert(!gallivm->provider);

   lp_build_init();

   gallivm->context = LLVMContextCreate();
   if (!gallivm->context)
      goto fail;

   gallivm->module = LLVMModuleCreateWithNameInContext("gallivm",
                                                       gallivm->context);
   if (!gallivm->module)
      goto fail;

   gallivm->provider =
      LLVMCreateModuleProviderForExistingModule(gallivm->module);
   if (!gallivm->provider)
      goto fail;

   if (!GlobalEngine) {
      /* We can only create one LLVMExecutionEngine (w/ LLVM 2.6 anyway) */
      enum LLVM_CodeGenOpt_Level optlevel;
      char *error = NULL;

      if (gallivm_debug & GALLIVM_DEBUG_NO_OPT) {
         optlevel = None;
      }
      else {
         optlevel = Default;
      }

      if (LLVMCreateJITCompiler(&GlobalEngine, gallivm->provider,
                                (unsigned) optlevel, &error)) {
         _debug_printf("%s\n", error);
         LLVMDisposeMessage(error);
         goto fail;
      }

#if defined(DEBUG) || defined(PROFILE)
      lp_register_oprofile_jit_event_listener(GlobalEngine);
#endif
   }

   gallivm->engine = GlobalEngine;

   LLVMAddModuleProvider(gallivm->engine, gallivm->provider);//new

   gallivm->target = LLVMGetExecutionEngineTargetData(gallivm->engine);
   if (!gallivm->target)
      goto fail;

   if (!create_pass_manager(gallivm))
      goto fail;

   gallivm->builder = LLVMCreateBuilderInContext(gallivm->context);
   if (!gallivm->builder)
      goto fail;

   return TRUE;

fail:
   free_gallivm_state(gallivm);
   return FALSE;
}
Пример #8
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;
}
/**
 * Allocate gallivm LLVM objects.
 * \return  TRUE for success, FALSE for failure
 */
static boolean
init_gallivm_state(struct gallivm_state *gallivm)
{
   assert(!gallivm->context);
   assert(!gallivm->module);
   assert(!gallivm->provider);

   lp_build_init();

   if (!gallivm_context) {
      gallivm_context = LLVMContextCreate();
   }
   gallivm->context = gallivm_context;
   if (!gallivm->context)
      goto fail;

   gallivm->module = LLVMModuleCreateWithNameInContext("gallivm",
                                                       gallivm->context);
   if (!gallivm->module)
      goto fail;

   gallivm->provider =
      LLVMCreateModuleProviderForExistingModule(gallivm->module);
   if (!gallivm->provider)
      goto fail;

   gallivm->builder = LLVMCreateBuilderInContext(gallivm->context);
   if (!gallivm->builder)
      goto fail;

   /* FIXME: MC-JIT only allows compiling one module at a time, and it must be
    * complete when MC-JIT is created. So defer the MC-JIT engine creation for
    * now.
    */
#if !USE_MCJIT
   if (!init_gallivm_engine(gallivm)) {
      goto fail;
   }
#else
   /*
    * MC-JIT engine compiles the module immediately on creation, so we can't
    * obtain the target data from it.  Instead we create a target data layout
    * from a string.
    *
    * The produced layout strings are not precisely the same, but should make
    * no difference for the kind of optimization passes we run.
    *
    * For reference this is the layout string on x64:
    *
    *   e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64
    *
    * See also:
    * - http://llvm.org/docs/LangRef.html#datalayout
    */

   {
      const unsigned pointer_size = 8 * sizeof(void *);
      char layout[512];
      util_snprintf(layout, sizeof layout, "%c-p:%u:%u:%u-i64:64:64-a0:0:%u-s0:%u:%u",
#ifdef PIPE_ARCH_LITTLE_ENDIAN
                    'e', // little endian
#else
                    'E', // big endian
#endif
                    pointer_size, pointer_size, pointer_size, // pointer size, abi alignment, preferred alignment
                    pointer_size, // aggregate preferred alignment
                    pointer_size, pointer_size); // stack objects abi alignment, preferred alignment

      gallivm->target = LLVMCreateTargetData(layout);
      if (!gallivm->target) {
         return FALSE;
      }
   }
#endif

   if (!create_pass_manager(gallivm))
      goto fail;

   return TRUE;

fail:
   free_gallivm_state(gallivm);
   return FALSE;
}