Beispiel #1
0
int llvm_test_callsite_attributes(void) {
  LLVMEnablePrettyStackTrace();

  LLVMModuleRef M = llvm_load_module(false, true);

  LLVMValueRef F = LLVMGetFirstFunction(M);
  while (F) {
    LLVMBasicBlockRef BB;
    for (BB = LLVMGetFirstBasicBlock(F); BB; BB = LLVMGetNextBasicBlock(BB)) {
      LLVMValueRef I;
      for (I = LLVMGetFirstInstruction(BB); I; I = LLVMGetNextInstruction(I)) {
        if (LLVMIsACallInst(I)) {
          // Read attributes
          int Idx, ParamCount;
          for (Idx = LLVMAttributeFunctionIndex,
              ParamCount = LLVMCountParams(F);
               Idx <= ParamCount; ++Idx) {
            int AttrCount = LLVMGetCallSiteAttributeCount(I, Idx);
            LLVMAttributeRef *Attrs = (LLVMAttributeRef *)malloc(
                AttrCount * sizeof(LLVMAttributeRef));
            assert(Attrs);
            LLVMGetCallSiteAttributes(I, Idx, Attrs);
            free(Attrs);
          }
        }
      }
    }

    F = LLVMGetNextFunction(F);
  }

  LLVMDisposeModule(M);

  return 0;
}
int test_kal_codegen_function() {
    kal_named_value *val;
    unsigned int arg_count = 1;
    char **args = malloc(sizeof(char*) * arg_count);
    args[0] = "foo";
    
    LLVMModuleRef module = LLVMModuleCreateWithName("kal");
    LLVMBuilderRef builder = LLVMCreateBuilder();
    kal_ast_node *prototype = kal_ast_prototype_create("my_func", args, arg_count);
    kal_ast_node *lhs = kal_ast_variable_create("foo");
    kal_ast_node *rhs = kal_ast_number_create(20);
    kal_ast_node *body = kal_ast_binary_expr_create(KAL_BINOP_PLUS, lhs, rhs);
    kal_ast_node *node = kal_ast_function_create(prototype, body);

    kal_codegen_reset();
    LLVMValueRef value = kal_codegen(node, module, builder);

    mu_assert(value != NULL, "");
    mu_assert(LLVMGetNamedFunction(module, "my_func") == value, "");
    mu_assert(LLVMCountParams(value) == 1, "");

    val = kal_codegen_named_value("foo");
    mu_assert(val->value == LLVMGetParam(value, 0), "");
    mu_assert(LLVMGetTypeKind(LLVMTypeOf(LLVMGetParam(value, 0))) == LLVMDoubleTypeKind, "");

    LLVMDisposeBuilder(builder);
    LLVMDisposeModule(module);
    kal_ast_node_free(node);
    return 0;
}
Beispiel #3
0
int llvm_test_function_attributes(void) {
  LLVMEnablePrettyStackTrace();

  LLVMModuleRef M = llvm_load_module(false, true);

  LLVMValueRef F = LLVMGetFirstFunction(M);
  while (F) {
    // Read attributes
    int Idx, ParamCount;
    for (Idx = LLVMAttributeFunctionIndex, ParamCount = LLVMCountParams(F);
         Idx <= ParamCount; ++Idx) {
      int AttrCount = LLVMGetAttributeCountAtIndex(F, Idx);
      LLVMAttributeRef *Attrs =
          (LLVMAttributeRef *)malloc(AttrCount * sizeof(LLVMAttributeRef));
      assert(Attrs);
      LLVMGetAttributesAtIndex(F, Idx, Attrs);
      free(Attrs);
    }
    F = LLVMGetNextFunction(F);
  }

  LLVMDisposeModule(M);

  return 0;
}
Beispiel #4
0
static void add_dispatch_case(compile_t* c, gentype_t* g, ast_t* fun,
  uint32_t index, LLVMValueRef handler, LLVMTypeRef type)
{
  // Add a case to the dispatch function to handle this message.
  codegen_startfun(c, g->dispatch_fn, false);
  LLVMBasicBlockRef block = codegen_block(c, "handler");
  LLVMValueRef id = LLVMConstInt(c->i32, index, false);
  LLVMAddCase(g->dispatch_switch, id, block);

  // Destructure the message.
  LLVMPositionBuilderAtEnd(c->builder, block);
  LLVMValueRef ctx = LLVMGetParam(g->dispatch_fn, 0);
  LLVMValueRef this_ptr = LLVMGetParam(g->dispatch_fn, 1);
  LLVMValueRef msg = LLVMBuildBitCast(c->builder,
    LLVMGetParam(g->dispatch_fn, 2), type, "");

  int count = LLVMCountParams(handler);
  size_t buf_size = count * sizeof(LLVMValueRef);
  LLVMValueRef* args = (LLVMValueRef*)pool_alloc_size(buf_size);
  args[0] = LLVMBuildBitCast(c->builder, this_ptr, g->use_type, "");

  // Trace the message.
  LLVMValueRef start_trace = gencall_runtime(c, "pony_gc_recv", &ctx, 1, "");
  ast_t* params = ast_childidx(fun, 3);
  ast_t* param = ast_child(params);
  bool need_trace = false;

  for(int i = 1; i < count; i++)
  {
    LLVMValueRef field = LLVMBuildStructGEP(c->builder, msg, i + 2, "");
    args[i] = LLVMBuildLoad(c->builder, field, "");

    need_trace |= gentrace(c, ctx, args[i], ast_type(param));
    param = ast_sibling(param);
  }

  if(need_trace)
  {
    gencall_runtime(c, "pony_recv_done", &ctx, 1, "");
  } else {
    LLVMInstructionEraseFromParent(start_trace);
  }

  // Call the handler.
  codegen_call(c, handler, args, count);
  LLVMBuildRetVoid(c->builder);
  codegen_finishfun(c);
  pool_free_size(buf_size, args);
}
int test_kal_codegen_prototype() {
    kal_named_value *val;
    unsigned int arg_count = 3;
    char **args = malloc(sizeof(char*) * arg_count);
    args[0] = "foo";
    args[1] = "bar";
    args[2] = "baz";
    
    LLVMModuleRef module = LLVMModuleCreateWithName("kal");
    LLVMBuilderRef builder = LLVMCreateBuilder();
    kal_ast_node *node = kal_ast_prototype_create("my_func", args, 3);

    kal_codegen_reset();
    LLVMValueRef value = kal_codegen(node, module, builder);

    mu_assert(value != NULL, "");
    mu_assert(LLVMGetNamedFunction(module, "my_func") == value, "");
    mu_assert(LLVMCountParams(value) == 3, "");

    val = kal_codegen_named_value("foo");
    mu_assert(val->value == LLVMGetParam(value, 0), "");
    mu_assert(LLVMGetTypeKind(LLVMTypeOf(LLVMGetParam(value, 0))) == LLVMDoubleTypeKind, "");

    val = kal_codegen_named_value("bar");
    mu_assert(val->value == LLVMGetParam(value, 1), "");
    mu_assert(LLVMGetTypeKind(LLVMTypeOf(LLVMGetParam(value, 1))) == LLVMDoubleTypeKind, "");

    val = kal_codegen_named_value("baz");
    mu_assert(val->value == LLVMGetParam(value, 2), "");
    mu_assert(LLVMGetTypeKind(LLVMTypeOf(LLVMGetParam(value, 2))) == LLVMDoubleTypeKind, "");

    LLVMDisposeBuilder(builder);
    LLVMDisposeModule(module);
    kal_ast_node_free(node);
    return 0;
}
Beispiel #6
0
LLVMValueRef get_struct_fn(
	struct llvm_ctx *ctx,
	IDL_tree ctyp,
	bool for_encode)
{
	const char *s_id = IDL_IDENT(IDL_TYPE_STRUCT(ctyp).ident).repo_id;
	char *lookup_name = talloc_asprintf(ctx, "%c%s",
		for_encode ? 'e' : 'd', s_id);
	LLVMValueRef fn = strmap_get(&ctx->struct_decoder_fns, lookup_name);
	if(fn != NULL) {
		talloc_free(lookup_name);
		return fn;
	}

	const struct packed_format *fmt = packed_format_of(ctyp);
	assert(fmt != NULL);	/* only sane for packable structs */
	int namelen = strlen(s_id);
	char flatname[namelen + 1];
	/* FIXME: make this proper, i.e. use a name mangler that works */
	for(int i=0; i < namelen; i++) {
		flatname[i] = isalnum(s_id[i]) ? s_id[i] : '_';
	}
	flatname[namelen] = '\0';
	T types[3], rettyp = LLVMVoidTypeInContext(ctx->ctx);
	types[0] = LLVMPointerType(llvm_rigid_type(ctx, ctyp), 0);
	int nparms;
	if(!for_encode) {
		/* decoder */
		types[1] = ctx->i32t;
		types[2] = ctx->i32t;
		nparms = fmt->num_bits < BITS_PER_WORD ? 3 : 2;
	} else if(fmt->num_bits < BITS_PER_WORD) {
		/* subword encoder */
		rettyp = ctx->wordt;
		types[1] = ctx->wordt;
		types[2] = ctx->i32t;
		nparms = 3;
	} else {
		/* non-subword encoder */
		types[1] = ctx->i32t;
		nparms = 2;
	}
	T fntype = LLVMFunctionType(rettyp, types, nparms, 0);
	char *fnname = g_strdup_printf("__muidl_idl_%scode__%s",
		for_encode ? "en" : "de", flatname);
	fn = LLVMAddFunction(ctx->module, fnname, fntype);
	LLVMSetLinkage(fn, LLVMExternalLinkage);
	V params[nparms];
	assert(LLVMCountParams(fn) == nparms);
	LLVMGetParams(fn, params);
	LLVMAddAttribute(params[0], LLVMNoAliasAttribute);
	LLVMAddAttribute(params[0], LLVMNoCaptureAttribute);
	for(int i=0; i<nparms; i++) {
		LLVMAddAttribute(params[i], LLVMInRegAttribute);
	}
	g_free(fnname);
	bool ok = strmap_add(&ctx->struct_decoder_fns, lookup_name, fn);
	assert(ok || errno != EEXIST);

	return fn;
}
Beispiel #7
0
void ac_optimize_vs_outputs(struct ac_llvm_context *ctx,
			    LLVMValueRef main_fn,
			    uint8_t *vs_output_param_offset,
			    uint32_t num_outputs,
			    uint8_t *num_param_exports)
{
	LLVMBasicBlockRef bb;
	bool removed_any = false;
	struct ac_vs_exports exports;

	exports.num = 0;

	/* Process all LLVM instructions. */
	bb = LLVMGetFirstBasicBlock(main_fn);
	while (bb) {
		LLVMValueRef inst = LLVMGetFirstInstruction(bb);

		while (inst) {
			LLVMValueRef cur = inst;
			inst = LLVMGetNextInstruction(inst);
			struct ac_vs_exp_inst exp;

			if (LLVMGetInstructionOpcode(cur) != LLVMCall)
				continue;

			LLVMValueRef callee = ac_llvm_get_called_value(cur);

			if (!ac_llvm_is_function(callee))
				continue;

			const char *name = LLVMGetValueName(callee);
			unsigned num_args = LLVMCountParams(callee);

			/* Check if this is an export instruction. */
			if ((num_args != 9 && num_args != 8) ||
			    (strcmp(name, "llvm.SI.export") &&
			     strcmp(name, "llvm.amdgcn.exp.f32")))
				continue;

			LLVMValueRef arg = LLVMGetOperand(cur, AC_EXP_TARGET);
			unsigned target = LLVMConstIntGetZExtValue(arg);

			if (target < V_008DFC_SQ_EXP_PARAM)
				continue;

			target -= V_008DFC_SQ_EXP_PARAM;

			/* Parse the instruction. */
			memset(&exp, 0, sizeof(exp));
			exp.offset = target;
			exp.inst = cur;

			for (unsigned i = 0; i < 4; i++) {
				LLVMValueRef v = LLVMGetOperand(cur, AC_EXP_OUT0 + i);

				exp.chan[i].value = v;

				if (LLVMIsUndef(v)) {
					exp.chan[i].type = AC_IR_UNDEF;
				} else if (LLVMIsAConstantFP(v)) {
					LLVMBool loses_info;
					exp.chan[i].type = AC_IR_CONST;
					exp.chan[i].const_float =
						LLVMConstRealGetDouble(v, &loses_info);
				} else {
					exp.chan[i].type = AC_IR_VALUE;
				}
			}

			/* Eliminate constant and duplicated PARAM exports. */
			if (ac_eliminate_const_output(vs_output_param_offset,
						      num_outputs, &exp) ||
			    ac_eliminate_duplicated_output(vs_output_param_offset,
							   num_outputs, &exports,
							   &exp)) {
				removed_any = true;
			} else {
				exports.exp[exports.num++] = exp;
			}
		}
		bb = LLVMGetNextBasicBlock(bb);
	}

	/* Remove holes in export memory due to removed PARAM exports.
	 * This is done by renumbering all PARAM exports.
	 */
	if (removed_any) {
		uint8_t old_offset[VARYING_SLOT_MAX];
		unsigned out, i;

		/* Make a copy of the offsets. We need the old version while
		 * we are modifying some of them. */
		memcpy(old_offset, vs_output_param_offset,
		       sizeof(old_offset));

		for (i = 0; i < exports.num; i++) {
			unsigned offset = exports.exp[i].offset;

			/* Update vs_output_param_offset. Multiple outputs can
			 * have the same offset.
			 */
			for (out = 0; out < num_outputs; out++) {
				if (old_offset[out] == offset)
					vs_output_param_offset[out] = i;
			}

			/* Change the PARAM offset in the instruction. */
			LLVMSetOperand(exports.exp[i].inst, AC_EXP_TARGET,
				       LLVMConstInt(ctx->i32,
						    V_008DFC_SQ_EXP_PARAM + i, 0));
		}
		*num_param_exports = exports.num;
	}
}
Beispiel #8
0
// Generates the function prototype but overrides the name. This is used by
// the metadata to create external APIs to C.
//
// node          - The node.
// module        - The compilation unit this node is a part of.
// function_name - The name of the function to generate.
// is_external   - A flag stating if this is an external prototype.
// value         - A pointer to where the LLVM value should be returned to.
//
// Returns 0 if successful, otherwise returns -1.
int qip_ast_function_codegen_prototype_with_name(qip_ast_node *node,
                                                 qip_module *module,
                                                 bstring function_name,
                                                 bool is_external,
                                                 LLVMValueRef *value)
{
    int rc;
    unsigned int i;
    LLVMValueRef func = NULL;
    bstring arg_type_name = NULL;
    bstring return_type_name = NULL;

    LLVMContextRef context = LLVMGetModuleContext(module->llvm_module);

    // Determine the number of arguments. External calls always have an
    // additional first argument that is the module reference.
    unsigned int offset = (is_external ? 1 : 0);
    unsigned int total_arg_count = node->function.arg_count + offset;

    // Check for an existing prototype.
    func = LLVMGetNamedFunction(module->llvm_module, bdata(function_name));
    
    // If a prototype exists then simply verify it matches and return it.
    if(func != NULL) {
        check(LLVMCountBasicBlocks(func) == 0, "Illegal function redefinition");
        check(LLVMCountParams(func) == total_arg_count, "Function prototype already exists with different arguments");
    }
    // If there is no prototype then create one.
    else {
        // Dynamically generate the return type of the function if it is missing.
        if(node->function.return_type == NULL) {
            rc = qip_ast_function_generate_return_type(node, module);
            check(rc == 0, "Unable to generate return type for function");
        }

        // Create a list of function argument types.
        qip_ast_node *arg;
        LLVMTypeRef *params = malloc(sizeof(LLVMTypeRef) * total_arg_count);

        // Create module argument for external calls.
        if(is_external) {
            params[0] = LLVMPointerType(LLVMInt8TypeInContext(context), 0);
        }

        // Create arguments.
        for(i=0; i<node->function.arg_count; i++) {
            qip_ast_node *arg = node->function.args[i];
            LLVMTypeRef param = NULL;
            rc = qip_module_get_type_ref(module, arg->farg.var_decl->var_decl.type, NULL, &param);
            check(rc == 0, "Unable to determine function argument type");
        
            // Pass argument as reference if this is a complex type.
            if(qip_module_is_complex_type(module, param)) {
                params[i+offset] = LLVMPointerType(param, 0);
            }
            // Otherwise pass it by value.
            else {
                params[i+offset] = param;
            }
        }

        // Determine return type.
        LLVMTypeRef return_type;
        rc = qip_module_get_type_ref(module, node->function.return_type, NULL, &return_type);
        check(rc == 0, "Unable to determine function return type");

        if(qip_module_is_complex_type(module, return_type)) {
            return_type = LLVMPointerType(return_type, 0);
        }

        // Create function type.
        LLVMTypeRef funcType = LLVMFunctionType(return_type, params, total_arg_count, false);
        check(funcType != NULL, "Unable to create function type");

        // Create function.
        func = LLVMAddFunction(module->llvm_module, bdata(function_name), funcType);
        check(func != NULL, "Unable to create function");
    
        // Assign module argument name.
        if(is_external) {
            LLVMSetValueName(LLVMGetParam(func, 0), "module");
        }
    
        // Assign names to function arguments.
        for(i=0; i<node->function.arg_count; i++) {
            arg = node->function.args[i];
            LLVMValueRef param = LLVMGetParam(func, i+offset);
            LLVMSetValueName(param, bdata(arg->farg.var_decl->var_decl.name));
        }
    }
    
    // Return function prototype;
    *value = func;
    
    bdestroy(arg_type_name);
    bdestroy(return_type_name);
    return 0;

error:
    bdestroy(arg_type_name);
    bdestroy(return_type_name);
    if(func) LLVMDeleteFunction(func);
    *value = NULL;
    return -1;
}
Beispiel #9
0
// Generates a function call to an external function.
//
// node  - The function node.
// block - The LLVM block the call is being added to.
//
// Returns 0 if successful, otherwise returns -1.
int qip_ast_function_generate_external_call(qip_ast_node *node,
                                             qip_module *module,
                                             LLVMBasicBlockRef block)
{
    int rc;
    check(node != NULL, "Node required");
    check(block != NULL, "Block required");
    
    LLVMBuilderRef builder = module->compiler->llvm_builder;

    // Grab the External metadata node if there is one.
    qip_ast_node *external_metadata_node = NULL;
    rc = qip_ast_function_get_external_metadata_node(node, &external_metadata_node);
    check(rc == 0, "Unable to retrieve external metadata node");
    check(external_metadata_node != NULL, "External metadata node does not exist");
    
    // Retrieve function name from metadata.
    bstring function_name = NULL;
    rc = qip_ast_metadata_get_item_value(external_metadata_node, NULL, &function_name);
    check(rc == 0, "Unable to retrieve function name from metadata");
    
    // Make sure we have an external function name.
    check(function_name != NULL, "External function name required");
    
    // Always pass in the global module reference as the first argument to
    // external functions so they have a context.
    unsigned int offset = 1;
    unsigned int total_arg_count = node->function.arg_count + offset;
    LLVMValueRef *args = malloc(sizeof(LLVMValueRef) * total_arg_count); check_mem(args);
    args[0] = LLVMBuildLoad(builder, module->llvm_global_module_value, "");
    
    // Loop over function arguments to make call arguments.
    unsigned int i;
    for(i=0; i<node->function.arg_count; i++) {
        qip_ast_node *farg = node->function.args[i];
        bstring arg_name = farg->farg.var_decl->var_decl.name;
        
        // Retrieve LLVM reference.
        qip_ast_node *farg_var_decl = NULL;
        LLVMValueRef farg_value = NULL;
        rc = qip_module_get_variable(module, arg_name, &farg_var_decl, &farg_value);
        check(rc == 0, "Unable to retrieve function argument declaration: %s", bdata(arg_name));
        check(farg_value != NULL, "No LLVM value for function argument declaration: %s", bdata(arg_name));
        
        // Load the reference and add it to the argument list.
        args[i+offset] = LLVMBuildLoad(builder, farg_value, "");
        check(args[i+offset] != NULL, "Unable to build load for function argument");
    }
    
    // Retrieve function.
    LLVMValueRef func = LLVMGetNamedFunction(module->llvm_module, bdata(function_name));
    check(func != NULL, "Unable to find external function: %s", bdata(function_name));
    check(LLVMCountParams(func) == total_arg_count, "Argument mismatch (got %d, expected %d)", total_arg_count, LLVMCountParams(func));
    
    // Create call instruction.
    LLVMValueRef call_value = LLVMBuildCall(builder, func, args, total_arg_count, "");
    check(call_value != NULL, "Unable to build external function call");
    
    // If function return void then generate a void return.
    if(qip_ast_type_ref_is_void(node->function.return_type)) {
        LLVMValueRef ret_value = LLVMBuildRetVoid(builder);
        check(ret_value != NULL, "Unable to build external void return");
    }
    // Otherwise return the value from the function.
    else {
        LLVMValueRef ret_value = LLVMBuildRet(builder, call_value);
        check(ret_value != NULL, "Unable to build external return value");
    }
    
    return 0;

error:
    return -1;
}