mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 00:35:10 +00:00
parent
5c094d7390
commit
866c841dd8
@ -1128,6 +1128,7 @@ enum FnInline {
|
||||
|
||||
struct FnTableEntry {
|
||||
LLVMValueRef llvm_value;
|
||||
const char *llvm_name;
|
||||
AstNode *proto_node;
|
||||
AstNode *body_node;
|
||||
ScopeFnDef *fndef_scope; // parent should be the top level decls or container decls
|
||||
@ -1501,6 +1502,8 @@ struct CodeGen {
|
||||
|
||||
Buf *cache_dir;
|
||||
Buf *out_h_path;
|
||||
|
||||
ZigList<FnTableEntry *> inline_fns;
|
||||
};
|
||||
|
||||
enum VarLinkage {
|
||||
|
||||
@ -353,10 +353,12 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
|
||||
} else {
|
||||
fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);
|
||||
}
|
||||
fn_table_entry->llvm_name = LLVMGetValueName(fn_table_entry->llvm_value);
|
||||
|
||||
switch (fn_table_entry->fn_inline) {
|
||||
case FnInlineAlways:
|
||||
addLLVMFnAttr(fn_table_entry->llvm_value, "alwaysinline");
|
||||
g->inline_fns.append(fn_table_entry);
|
||||
break;
|
||||
case FnInlineNever:
|
||||
addLLVMFnAttr(fn_table_entry->llvm_value, "noinline");
|
||||
@ -3628,6 +3630,27 @@ static void ensure_cache_dir(CodeGen *g) {
|
||||
}
|
||||
}
|
||||
|
||||
static void report_errors_and_maybe_exit(CodeGen *g) {
|
||||
if (g->errors.length != 0) {
|
||||
for (size_t i = 0; i < g->errors.length; i += 1) {
|
||||
ErrorMsg *err = g->errors.at(i);
|
||||
print_err_msg(err, g->err_color);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void validate_inline_fns(CodeGen *g) {
|
||||
for (size_t i = 0; i < g->inline_fns.length; i += 1) {
|
||||
FnTableEntry *fn_entry = g->inline_fns.at(i);
|
||||
LLVMValueRef fn_val = LLVMGetNamedFunction(g->module, fn_entry->llvm_name);
|
||||
if (fn_val != nullptr) {
|
||||
add_node_error(g, fn_entry->proto_node, buf_sprintf("unable to inline function"));
|
||||
}
|
||||
}
|
||||
report_errors_and_maybe_exit(g);
|
||||
}
|
||||
|
||||
static void do_code_gen(CodeGen *g) {
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "\nCode Generation:\n");
|
||||
@ -3927,6 +3950,8 @@ static void do_code_gen(CodeGen *g) {
|
||||
zig_panic("unable to write object file: %s", err_msg);
|
||||
}
|
||||
|
||||
validate_inline_fns(g);
|
||||
|
||||
g->link_objects.append(output_path);
|
||||
}
|
||||
|
||||
@ -4719,16 +4744,9 @@ static void gen_root_source(CodeGen *g) {
|
||||
}
|
||||
}
|
||||
|
||||
if (g->errors.length == 0) {
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < g->errors.length; i += 1) {
|
||||
ErrorMsg *err = g->errors.at(i);
|
||||
print_err_msg(err, g->err_color);
|
||||
}
|
||||
exit(1);
|
||||
report_errors_and_maybe_exit(g);
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1684,4 +1684,29 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
\\fn bar() -> ?i32 { 1 }
|
||||
,
|
||||
".tmp_source.zig:2:15: error: expected error union type, found '?i32'");
|
||||
|
||||
cases.add("inline fn calls itself indirectly",
|
||||
\\export fn foo() {
|
||||
\\ bar();
|
||||
\\}
|
||||
\\inline fn bar() {
|
||||
\\ baz();
|
||||
\\ quux();
|
||||
\\}
|
||||
\\inline fn baz() {
|
||||
\\ bar();
|
||||
\\ quux();
|
||||
\\}
|
||||
\\extern fn quux();
|
||||
,
|
||||
".tmp_source.zig:4:8: error: unable to inline function");
|
||||
|
||||
cases.add("save reference to inline function",
|
||||
\\export fn foo() {
|
||||
\\ quux(usize(bar));
|
||||
\\}
|
||||
\\inline fn bar() { }
|
||||
\\extern fn quux(usize);
|
||||
,
|
||||
".tmp_source.zig:4:8: error: unable to inline function");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user