aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-04-04 17:22:26 -0400
committerAndrew Kelley <superjoe30@gmail.com>2018-04-04 17:22:26 -0400
commitcca93908e6d57f18054d153ca01d6869739306f2 (patch)
treeb7316e13386963e5b08aebc1f5707498b64a9ebb /src/analyze.cpp
parentc541ac240c3ad17dda964f9de085a5e8f5472c7a (diff)
parent8938429ea12ff2857ace5380932a7cd68d3b4ab1 (diff)
downloadzig-cca93908e6d57f18054d153ca01d6869739306f2.tar.gz
zig-cca93908e6d57f18054d153ca01d6869739306f2.zip
Merge remote-tracking branch 'origin/master' into llvm7
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp142
1 files changed, 125 insertions, 17 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 395df229cd..291e7e7644 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -170,6 +170,12 @@ Scope *create_comptime_scope(AstNode *node, Scope *parent) {
return &scope->base;
}
+Scope *create_coro_prelude_scope(AstNode *node, Scope *parent) {
+ ScopeCoroPrelude *scope = allocate<ScopeCoroPrelude>(1);
+ init_scope(&scope->base, ScopeIdCoroPrelude, node, parent);
+ return &scope->base;
+}
+
ImportTableEntry *get_scope_import(Scope *scope) {
while (scope) {
if (scope->id == ScopeIdDecls) {
@@ -985,7 +991,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
// populate the name of the type
buf_resize(&fn_type->name, 0);
if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
- buf_appendf(&fn_type->name, "async(%s) ", buf_ptr(&fn_type_id->async_allocator_type->name));
+ assert(fn_type_id->async_allocator_type != nullptr);
+ buf_appendf(&fn_type->name, "async<%s> ", buf_ptr(&fn_type_id->async_allocator_type->name));
} else {
const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
buf_appendf(&fn_type->name, "%s", cc_str);
@@ -3253,6 +3260,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeResume:
case NodeTypeAwaitExpr:
case NodeTypeSuspend:
+ case NodeTypePromiseType:
zig_unreachable();
}
}
@@ -3590,6 +3598,7 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope) {
case ScopeIdCImport:
case ScopeIdLoop:
case ScopeIdCompTime:
+ case ScopeIdCoroPrelude:
scope = scope->parent;
continue;
case ScopeIdFnDef:
@@ -3864,7 +3873,7 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ
TypeTableEntry *block_return_type = ir_analyze(g, &fn_table_entry->ir_executable,
&fn_table_entry->analyzed_executable, fn_type_id->return_type, return_type_node);
- fn_table_entry->implicit_return_type = block_return_type;
+ fn_table_entry->src_implicit_return_type = block_return_type;
if (type_is_invalid(block_return_type) || fn_table_entry->analyzed_executable.invalid) {
assert(g->errors.length > 0);
@@ -3876,10 +3885,10 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ
TypeTableEntry *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type;
if (return_err_set_type->data.error_set.infer_fn != nullptr) {
TypeTableEntry *inferred_err_set_type;
- if (fn_table_entry->implicit_return_type->id == TypeTableEntryIdErrorSet) {
- inferred_err_set_type = fn_table_entry->implicit_return_type;
- } else if (fn_table_entry->implicit_return_type->id == TypeTableEntryIdErrorUnion) {
- inferred_err_set_type = fn_table_entry->implicit_return_type->data.error_union.err_set_type;
+ if (fn_table_entry->src_implicit_return_type->id == TypeTableEntryIdErrorSet) {
+ inferred_err_set_type = fn_table_entry->src_implicit_return_type;
+ } else if (fn_table_entry->src_implicit_return_type->id == TypeTableEntryIdErrorUnion) {
+ inferred_err_set_type = fn_table_entry->src_implicit_return_type->data.error_union.err_set_type;
} else {
add_node_error(g, return_type_node,
buf_sprintf("function with inferred error set must return at least one possible error"));
@@ -4276,26 +4285,118 @@ static ZigWindowsSDK *get_windows_sdk(CodeGen *g) {
return g->win_sdk;
}
+
+Buf *get_linux_libc_lib_path(const char *o_file) {
+ const char *cc_exe = getenv("CC");
+ cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
+ ZigList<const char *> args = {};
+ args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file)));
+ Termination term;
+ Buf *out_stderr = buf_alloc();
+ Buf *out_stdout = buf_alloc();
+ int err;
+ if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
+ zig_panic("unable to determine libc lib path: executing C compiler: %s", err_str(err));
+ }
+ if (term.how != TerminationIdClean || term.code != 0) {
+ zig_panic("unable to determine libc lib path: executing C compiler command failed");
+ }
+ if (buf_ends_with_str(out_stdout, "\n")) {
+ buf_resize(out_stdout, buf_len(out_stdout) - 1);
+ }
+ if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) {
+ zig_panic("unable to determine libc lib path: C compiler could not find %s", o_file);
+ }
+ Buf *result = buf_alloc();
+ os_path_dirname(out_stdout, result);
+ return result;
+}
+
+Buf *get_linux_libc_include_path(void) {
+ const char *cc_exe = getenv("CC");
+ cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
+ ZigList<const char *> args = {};
+ args.append("-E");
+ args.append("-Wp,-v");
+ args.append("-xc");
+ args.append("/dev/null");
+ Termination term;
+ Buf *out_stderr = buf_alloc();
+ Buf *out_stdout = buf_alloc();
+ int err;
+ if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
+ zig_panic("unable to determine libc include path: executing C compiler: %s", err_str(err));
+ }
+ if (term.how != TerminationIdClean || term.code != 0) {
+ zig_panic("unable to determine libc include path: executing C compiler command failed");
+ }
+ char *prev_newline = buf_ptr(out_stderr);
+ ZigList<const char *> search_paths = {};
+ bool found_search_paths = false;
+ for (;;) {
+ char *newline = strchr(prev_newline, '\n');
+ if (newline == nullptr) {
+ zig_panic("unable to determine libc include path: bad output from C compiler command");
+ }
+ *newline = 0;
+ if (found_search_paths) {
+ if (strcmp(prev_newline, "End of search list.") == 0) {
+ break;
+ }
+ search_paths.append(prev_newline);
+ } else {
+ if (strcmp(prev_newline, "#include <...> search starts here:") == 0) {
+ found_search_paths = true;
+ }
+ }
+ prev_newline = newline + 1;
+ }
+ if (search_paths.length == 0) {
+ zig_panic("unable to determine libc include path: even C compiler does not know where libc headers are");
+ }
+ for (size_t i = 0; i < search_paths.length; i += 1) {
+ // search in reverse order
+ const char *search_path = search_paths.items[search_paths.length - i - 1];
+ // cut off spaces
+ while (*search_path == ' ') {
+ search_path += 1;
+ }
+ Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path);
+ bool exists;
+ if ((err = os_file_exists(stdlib_path, &exists))) {
+ exists = false;
+ }
+ if (exists) {
+ return buf_create_from_str(search_path);
+ }
+ }
+ zig_panic("unable to determine libc include path: stdlib.h not found in C compiler search paths");
+}
+
void find_libc_include_path(CodeGen *g) {
- if (!g->libc_include_dir || buf_len(g->libc_include_dir) == 0) {
- ZigWindowsSDK *sdk = get_windows_sdk(g);
+ if (g->libc_include_dir == nullptr) {
if (g->zig_target.os == OsWindows) {
+ ZigWindowsSDK *sdk = get_windows_sdk(g);
+ g->libc_include_dir = buf_alloc();
if (os_get_win32_ucrt_include_path(sdk, g->libc_include_dir)) {
zig_panic("Unable to determine libc include path.");
}
+ } else if (g->zig_target.os == OsLinux) {
+ g->libc_include_dir = get_linux_libc_include_path();
+ } else if (g->zig_target.os == OsMacOSX) {
+ g->libc_include_dir = buf_create_from_str("/usr/include");
+ } else {
+ // TODO find libc at runtime for other operating systems
+ zig_panic("Unable to determine libc include path.");
}
}
-
- // TODO find libc at runtime for other operating systems
- if(!g->libc_include_dir || buf_len(g->libc_include_dir) == 0) {
- zig_panic("Unable to determine libc include path.");
- }
+ assert(buf_len(g->libc_include_dir) != 0);
}
void find_libc_lib_path(CodeGen *g) {
// later we can handle this better by reporting an error via the normal mechanism
- if (!g->libc_lib_dir || buf_len(g->libc_lib_dir) == 0 ||
+ if (g->libc_lib_dir == nullptr ||
(g->zig_target.os == OsWindows && (g->msvc_lib_dir == nullptr || g->kernel32_lib_dir == nullptr)))
{
if (g->zig_target.os == OsWindows) {
@@ -4319,18 +4420,25 @@ void find_libc_lib_path(CodeGen *g) {
g->msvc_lib_dir = vc_lib_dir;
g->libc_lib_dir = ucrt_lib_path;
g->kernel32_lib_dir = kern_lib_path;
+ } else if (g->zig_target.os == OsLinux) {
+ g->libc_lib_dir = get_linux_libc_lib_path("crt1.o");
} else {
zig_panic("Unable to determine libc lib path.");
}
+ } else {
+ assert(buf_len(g->libc_lib_dir) != 0);
}
- if (!g->libc_static_lib_dir || buf_len(g->libc_static_lib_dir) == 0) {
+ if (g->libc_static_lib_dir == nullptr) {
if ((g->zig_target.os == OsWindows) && (g->msvc_lib_dir != NULL)) {
return;
- }
- else {
+ } else if (g->zig_target.os == OsLinux) {
+ g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o");
+ } else {
zig_panic("Unable to determine libc static lib path.");
}
+ } else {
+ assert(buf_len(g->libc_static_lib_dir) != 0);
}
}