Browse Source

`foreign export` block
```
foreign export {
my_i32: i32;
my_foo :: proc() -> i32 {
return 123;
}
}
```

gingerBill 7 years ago
parent
commit
3d8bf36a30
7 changed files with 72 additions and 59 deletions
  1. 7 3
      src/check_decl.cpp
  2. 26 15
      src/checker.cpp
  3. 1 0
      src/entity.cpp
  4. 17 4
      src/ir.cpp
  5. 7 3
      src/ir_print.cpp
  6. 12 32
      src/parser.cpp
  7. 2 2
      src/ssa.cpp

+ 7 - 3
src/check_decl.cpp

@@ -425,9 +425,9 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 
 
 	TypeProc *pt = &proc_type->Proc;
 	TypeProc *pt = &proc_type->Proc;
 
 
-	bool is_foreign         = (pl->tags & ProcTag_foreign)   != 0;
+	bool is_foreign         = e->Procedure.is_foreign;
+	bool is_export          = (e->flags & EntityFlag_ForeignExport) != 0;
 	bool is_link_name       = (pl->tags & ProcTag_link_name) != 0;
 	bool is_link_name       = (pl->tags & ProcTag_link_name) != 0;
-	bool is_export          = (pl->tags & ProcTag_export)    != 0;
 	bool is_inline          = (pl->tags & ProcTag_inline)    != 0;
 	bool is_inline          = (pl->tags & ProcTag_inline)    != 0;
 	bool is_no_inline       = (pl->tags & ProcTag_no_inline) != 0;
 	bool is_no_inline       = (pl->tags & ProcTag_no_inline) != 0;
 	bool is_require_results = (pl->tags & ProcTag_require_results) != 0;
 	bool is_require_results = (pl->tags & ProcTag_require_results) != 0;
@@ -489,7 +489,11 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 			check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pl->body, pl->tags);
 			check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pl->body, pl->tags);
 		}
 		}
 	} else if (!is_foreign) {
 	} else if (!is_foreign) {
-		error(e->token, "Only a foreign procedure cannot have a body");
+		if (e->flags & EntityFlag_ForeignExport) {
+			error(e->token, "Foreign export procedures must have a body");
+		} else {
+			error(e->token, "Only a foreign procedure cannot have a body");
+		}
 	}
 	}
 
 
 	if (pt->result_count == 0 && is_require_results) {
 	if (pt->result_count == 0 && is_require_results) {

+ 26 - 15
src/checker.cpp

@@ -423,6 +423,7 @@ struct CheckerContext {
 	DeclInfo * curr_proc_decl;
 	DeclInfo * curr_proc_decl;
 	AstNode *  curr_foreign_library;
 	AstNode *  curr_foreign_library;
 
 
+	bool       in_foreign_export;
 	bool       collect_delayed_decls;
 	bool       collect_delayed_decls;
 	bool       allow_polymorphic_types;
 	bool       allow_polymorphic_types;
 	bool       no_polymorphic_errors;
 	bool       no_polymorphic_errors;
@@ -1481,13 +1482,13 @@ PtrSet<Entity *> generate_minimum_dependency_set(CheckerInfo *info, Entity *star
 				add_dependency_to_map(&map, info, e);
 				add_dependency_to_map(&map, info, e);
 			}
 			}
 		} else if (e->kind == Entity_Procedure) {
 		} else if (e->kind == Entity_Procedure) {
-			if ((e->Procedure.tags & ProcTag_export) != 0) {
-				add_dependency_to_map(&map, info, e);
-			}
 			if (e->Procedure.is_foreign) {
 			if (e->Procedure.is_foreign) {
 				add_dependency_to_map(&map, info, e->Procedure.foreign_library);
 				add_dependency_to_map(&map, info, e->Procedure.foreign_library);
 			}
 			}
 		}
 		}
+		if (e->flags & EntityFlag_ForeignExport) {
+			add_dependency_to_map(&map, info, e);
+		}
 	}
 	}
 
 
 	add_dependency_to_map(&map, info, start);
 	add_dependency_to_map(&map, info, start);
@@ -1969,6 +1970,8 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
 				GB_ASSERT(fl->kind == AstNode_Ident);
 				GB_ASSERT(fl->kind == AstNode_Ident);
 				e->Variable.is_foreign = true;
 				e->Variable.is_foreign = true;
 				e->Variable.foreign_library_ident = fl;
 				e->Variable.foreign_library_ident = fl;
+			} else if (c->context.in_foreign_export) {
+				e->flags |= EntityFlag_ForeignExport;
 			}
 			}
 
 
 			entities[entity_count++] = e;
 			entities[entity_count++] = e;
@@ -2027,7 +2030,9 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
 				if (fl != nullptr) {
 				if (fl != nullptr) {
 					GB_ASSERT(fl->kind == AstNode_Ident);
 					GB_ASSERT(fl->kind == AstNode_Ident);
 					e->Procedure.foreign_library_ident = fl;
 					e->Procedure.foreign_library_ident = fl;
-					pl->tags |= ProcTag_foreign;
+					e->Procedure.is_foreign = true;
+				} else if (c->context.in_foreign_export) {
+					e->flags |= EntityFlag_ForeignExport;
 				}
 				}
 				d->proc_lit = init;
 				d->proc_lit = init;
 				d->type_expr = pl->type;
 				d->type_expr = pl->type;
@@ -2038,13 +2043,14 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
 			}
 			}
 			e->identifier = name;
 			e->identifier = name;
 
 
-			if (fl != nullptr && e->kind != Entity_Procedure) {
-				AstNodeKind kind = init->kind;
-				error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_node_strings[kind]));
-				if (kind == AstNode_ProcType) {
-					gb_printf_err("\tDid you forget to append `---` to the procedure?\n");
+			if (e->kind != Entity_Procedure) {
+				if (fl != nullptr || c->context.in_foreign_export) {
+					AstNodeKind kind = init->kind;
+					error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_node_strings[kind]));
+					if (kind == AstNode_ProcType) {
+						gb_printf_err("\tDid you forget to append `---` to the procedure?\n");
+					}
 				}
 				}
-				// continue;
 			}
 			}
 
 
 			add_entity_and_decl_info(c, name, e, d);
 			add_entity_and_decl_info(c, name, e, d);
@@ -2061,13 +2067,18 @@ void check_add_foreign_block_decl(Checker *c, AstNode *decl) {
 	fb->been_handled = true;
 	fb->been_handled = true;
 
 
 	AstNode *foreign_library = fb->foreign_library;
 	AstNode *foreign_library = fb->foreign_library;
-	if (foreign_library->kind != AstNode_Ident) {
-		error(foreign_library, "foreign library name must be an identifier");
-		foreign_library = nullptr;
-	}
+
 
 
 	CheckerContext prev_context = c->context;
 	CheckerContext prev_context = c->context;
-	c->context.curr_foreign_library = foreign_library;
+	if (foreign_library->kind == AstNode_Ident) {
+		c->context.curr_foreign_library = foreign_library;
+	} else if (foreign_library->kind == AstNode_Implicit && foreign_library->Implicit.kind == Token_export) {
+		c->context.in_foreign_export = true;
+	} else {
+		error(foreign_library, "Foreign block name must be an identifier or `export`");
+		c->context.curr_foreign_library = nullptr;
+	}
+
 	c->context.collect_delayed_decls = true;
 	c->context.collect_delayed_decls = true;
 	check_collect_entities(c, fb->decls);
 	check_collect_entities(c, fb->decls);
 	c->context = prev_context;
 	c->context = prev_context;

+ 1 - 0
src/entity.cpp

@@ -46,6 +46,7 @@ enum EntityFlag {
 
 
 	EntityFlag_CVarArg       = 1<<20,
 	EntityFlag_CVarArg       = 1<<20,
 
 
+	EntityFlag_ForeignExport = 1<<23,
 };
 };
 
 
 // Zero value means the overloading process is not yet done
 // Zero value means the overloading process is not yet done

+ 17 - 4
src/ir.cpp

@@ -117,6 +117,8 @@ struct irProcedure {
 	AstNode *             type_expr;
 	AstNode *             type_expr;
 	AstNode *             body;
 	AstNode *             body;
 	u64                   tags;
 	u64                   tags;
+	bool                  is_foreign;
+	bool                  is_export;
 
 
 	irValue *             return_ptr;
 	irValue *             return_ptr;
 	Array<irValue *>      params;
 	Array<irValue *>      params;
@@ -357,6 +359,7 @@ struct irValueGlobal {
 	irValue *     value;
 	irValue *     value;
 	Array<irValue *>  referrers;
 	Array<irValue *>  referrers;
 	bool          is_constant;
 	bool          is_constant;
+	bool          is_export;
 	bool          is_private;
 	bool          is_private;
 	bool          is_thread_local;
 	bool          is_thread_local;
 	bool          is_foreign;
 	bool          is_foreign;
@@ -5976,7 +5979,7 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) {
 				ir_module_add_value(proc->module, e, value);
 				ir_module_add_value(proc->module, e, value);
 				ir_build_proc(value, proc);
 				ir_build_proc(value, proc);
 
 
-				if (value->Proc.tags & ProcTag_foreign) {
+				if (value->Proc.is_foreign || value->Proc.is_export) {
 					HashKey key = hash_string(name);
 					HashKey key = hash_string(name);
 					irValue **prev_value = map_get(&proc->module->members, key);
 					irValue **prev_value = map_get(&proc->module->members, key);
 					if (prev_value == nullptr) {
 					if (prev_value == nullptr) {
@@ -7349,6 +7352,14 @@ void ir_build_proc(irValue *value, irProcedure *parent) {
 		Entity *e = proc->entity;
 		Entity *e = proc->entity;
 		String filename = e->token.pos.file;
 		String filename = e->token.pos.file;
 		AstFile *f = ast_file_of_filename(info, filename);
 		AstFile *f = ast_file_of_filename(info, filename);
+
+		if (e->flags & EntityFlag_ForeignExport) {
+			proc->is_export = true;
+		}
+		if (e->Procedure.is_foreign) {
+			proc->is_foreign = true;
+		}
+
 		irDebugInfo *di_file = nullptr;
 		irDebugInfo *di_file = nullptr;
 
 
 		irDebugInfo **di_file_found = map_get(&m->debug_info, hash_ast_file(f));
 		irDebugInfo **di_file_found = map_get(&m->debug_info, hash_ast_file(f));
@@ -8109,7 +8120,7 @@ void ir_gen_tree(irGen *s) {
 				GB_ASSERT(e == entry_point);
 				GB_ASSERT(e == entry_point);
 				// entry_point = e;
 				// entry_point = e;
 			}
 			}
-			if ((e->Procedure.tags & ProcTag_export) != 0 ||
+			if ((e->flags & EntityFlag_ForeignExport) != 0 ||
 			    (e->Procedure.link_name.len > 0) ||
 			    (e->Procedure.link_name.len > 0) ||
 			    (e->scope->is_file && e->Procedure.link_name.len > 0)) {
 			    (e->scope->is_file && e->Procedure.link_name.len > 0)) {
 				if (!has_dll_main && name == "DllMain") {
 				if (!has_dll_main && name == "DllMain") {
@@ -8162,12 +8173,14 @@ void ir_gen_tree(irGen *s) {
 			irValue *g = ir_value_global(a, e, nullptr);
 			irValue *g = ir_value_global(a, e, nullptr);
 			g->Global.name = name;
 			g->Global.name = name;
 			g->Global.is_thread_local = e->Variable.is_thread_local;
 			g->Global.is_thread_local = e->Variable.is_thread_local;
-
+			g->Global.is_export = (e->flags & EntityFlag_ForeignExport) != 0;
+			g->Global.is_foreign = e->Variable.is_foreign;
 
 
 			irGlobalVariable var = {};
 			irGlobalVariable var = {};
 			var.var = g;
 			var.var = g;
 			var.decl = decl;
 			var.decl = decl;
 
 
+
 			if (e->type->kind == Type_Struct && e->type->Struct.has_proc_default_values) {
 			if (e->type->kind == Type_Struct && e->type->Struct.has_proc_default_values) {
 				for_array(i, e->type->Struct.fields) {
 				for_array(i, e->type->Struct.fields) {
 					Entity *f = e->type->Struct.fields[i];
 					Entity *f = e->type->Struct.fields[i];
@@ -8235,7 +8248,7 @@ void ir_gen_tree(irGen *s) {
 		String original_name = name;
 		String original_name = name;
 
 
 		if (!scope->is_global || polymorphic_struct || is_type_polymorphic(e->type)) {
 		if (!scope->is_global || polymorphic_struct || is_type_polymorphic(e->type)) {
-			if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
+			if (e->kind == Entity_Procedure && (e->flags & EntityFlag_ForeignExport) != 0) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
 				// Handle later
 				// Handle later
 			// } else if (scope->is_init && e->kind == Entity_Procedure && name == "main") {
 			// } else if (scope->is_init && e->kind == Entity_Procedure && name == "main") {

+ 7 - 3
src/ir_print.cpp

@@ -801,7 +801,7 @@ bool ir_print_is_proc_global(irModule *m, irProcedure *proc) {
 		    return true;
 		    return true;
 		}
 		}
 	}
 	}
-	return (proc->tags & (ProcTag_foreign|ProcTag_export)) != 0;
+	return proc->is_foreign || proc->is_export;
 }
 }
 
 
 void ir_print_value(irFileBuffer *f, irModule *m, irValue *value, Type *type_hint) {
 void ir_print_value(irFileBuffer *f, irModule *m, irValue *value, Type *type_hint) {
@@ -1673,8 +1673,7 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 		ir_write_byte(f, '\n');
 		ir_write_byte(f, '\n');
 		ir_write_string(f, "define ");
 		ir_write_string(f, "define ");
 		if (build_context.is_dll) {
 		if (build_context.is_dll) {
-			// if (proc->tags & (ProcTag_export|ProcTag_dll_export)) {
-			if (proc->tags & (ProcTag_export)) {
+			if (proc->is_export) {
 				ir_write_string(f, "dllexport ");
 				ir_write_string(f, "dllexport ");
 			}
 			}
 		}
 		}
@@ -1924,6 +1923,11 @@ void print_llvm_ir(irGen *ir) {
 		if (g->is_foreign) {
 		if (g->is_foreign) {
 			ir_write_string(f, str_lit("external "));
 			ir_write_string(f, str_lit("external "));
 		}
 		}
+		if (build_context.is_dll) {
+			if (g->is_export) {
+				ir_write_string(f, str_lit("dllexport "));
+			}
+		}
 		if (g->is_thread_local) {
 		if (g->is_thread_local) {
 			ir_write_string(f, str_lit("thread_local "));
 			ir_write_string(f, str_lit("thread_local "));
 		}
 		}

+ 12 - 32
src/parser.cpp

@@ -95,11 +95,9 @@ enum ProcTag {
 
 
 	ProcTag_require_results = 1<<4,
 	ProcTag_require_results = 1<<4,
 
 
-	ProcTag_foreign         = 1<<10,
-	ProcTag_export          = 1<<11,
-	ProcTag_link_name       = 1<<12,
-	ProcTag_inline          = 1<<13,
-	ProcTag_no_inline       = 1<<14,
+	ProcTag_link_name       = 1<<11,
+	ProcTag_inline          = 1<<12,
+	ProcTag_no_inline       = 1<<13,
 
 
 	// ProcTag_dll_import      = 1<<15,
 	// ProcTag_dll_import      = 1<<15,
 	// ProcTag_dll_export      = 1<<16,
 	// ProcTag_dll_export      = 1<<16,
@@ -1933,12 +1931,7 @@ AstNode *parse_ident(AstFile *f) {
 
 
 AstNode *parse_tag_expr(AstFile *f, AstNode *expression) {
 AstNode *parse_tag_expr(AstFile *f, AstNode *expression) {
 	Token token = expect_token(f, Token_Hash);
 	Token token = expect_token(f, Token_Hash);
-	Token name = {};
-	if (f->curr_token.kind == Token_export) {
-		name = expect_token(f, Token_export);
-	} else {
-		name = expect_token(f, Token_Ident);
-	}
+	Token name = expect_token(f, Token_Ident);
 	return ast_tag_expr(f, token, name, expression);
 	return ast_tag_expr(f, token, name, expression);
 }
 }
 
 
@@ -2088,7 +2081,6 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven
 			}
 			}
 		}
 		}
 		ELSE_IF_ADD_TAG(require_results)
 		ELSE_IF_ADD_TAG(require_results)
-		ELSE_IF_ADD_TAG(export)
 		ELSE_IF_ADD_TAG(bounds_check)
 		ELSE_IF_ADD_TAG(bounds_check)
 		ELSE_IF_ADD_TAG(no_bounds_check)
 		ELSE_IF_ADD_TAG(no_bounds_check)
 		ELSE_IF_ADD_TAG(inline)
 		ELSE_IF_ADD_TAG(inline)
@@ -2131,7 +2123,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven
 	}
 	}
 
 
 	if (cc == ProcCC_Invalid) {
 	if (cc == ProcCC_Invalid) {
-		if ((*tags) & ProcTag_foreign || f->in_foreign_block) {
+		if (f->in_foreign_block) {
 			cc = ProcCC_C;
 			cc = ProcCC_C;
 		} else {
 		} else {
 			cc = ProcCC_Odin;
 			cc = ProcCC_Odin;
@@ -2142,10 +2134,6 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven
 		*calling_convention = cc;
 		*calling_convention = cc;
 	}
 	}
 
 
-	if ((*tags & ProcTag_foreign) && (*tags & ProcTag_export)) {
-		syntax_error(f->curr_token, "A foreign procedure cannot have #export");
-	}
-
 	if ((*tags & ProcTag_inline) && (*tags & ProcTag_no_inline)) {
 	if ((*tags & ProcTag_inline) && (*tags & ProcTag_no_inline)) {
 		syntax_error(f->curr_token, "You cannot apply both #inline and #no_inline to a procedure");
 		syntax_error(f->curr_token, "You cannot apply both #inline and #no_inline to a procedure");
 	}
 	}
@@ -2153,10 +2141,6 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven
 	if ((*tags & ProcTag_bounds_check) && (*tags & ProcTag_no_bounds_check)) {
 	if ((*tags & ProcTag_bounds_check) && (*tags & ProcTag_no_bounds_check)) {
 		syntax_error(f->curr_token, "You cannot apply both #bounds_check and #no_bounds_check to a procedure");
 		syntax_error(f->curr_token, "You cannot apply both #bounds_check and #no_bounds_check to a procedure");
 	}
 	}
-
-	if (((*tags & ProcTag_bounds_check) || (*tags & ProcTag_no_bounds_check)) && (*tags & ProcTag_foreign)) {
-		syntax_error(f->curr_token, "You cannot apply both #bounds_check or #no_bounds_check to a procedure without a body");
-	}
 }
 }
 
 
 
 
@@ -2309,9 +2293,6 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 		if (allow_token(f, Token_Undef)) {
 		if (allow_token(f, Token_Undef)) {
 			return ast_proc_lit(f, type, nullptr, tags, link_name);
 			return ast_proc_lit(f, type, nullptr, tags, link_name);
 		} else if (f->curr_token.kind == Token_OpenBrace) {
 		} else if (f->curr_token.kind == Token_OpenBrace) {
-			if ((tags & ProcTag_foreign) != 0) {
-				syntax_error(token, "A procedure tagged as `#foreign` cannot have a body");
-			}
 			AstNode *curr_proc = f->curr_proc;
 			AstNode *curr_proc = f->curr_proc;
 			AstNode *body = nullptr;
 			AstNode *body = nullptr;
 			f->curr_proc = type;
 			f->curr_proc = type;
@@ -2320,9 +2301,6 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 
 
 			return ast_proc_lit(f, type, body, tags, link_name);
 			return ast_proc_lit(f, type, body, tags, link_name);
 		} else if (allow_token(f, Token_do)) {
 		} else if (allow_token(f, Token_do)) {
-			if ((tags & ProcTag_foreign) != 0) {
-				syntax_error(token, "A procedure tagged as `#foreign` cannot have a body");
-			}
 			AstNode *curr_proc = f->curr_proc;
 			AstNode *curr_proc = f->curr_proc;
 			AstNode *body = nullptr;
 			AstNode *body = nullptr;
 			f->curr_proc = type;
 			f->curr_proc = type;
@@ -2332,9 +2310,6 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 			return ast_proc_lit(f, type, body, tags, link_name);
 			return ast_proc_lit(f, type, body, tags, link_name);
 		}
 		}
 
 
-		if ((tags & ProcTag_foreign) != 0) {
-			return ast_proc_lit(f, type, nullptr, tags, link_name);
-		}
 		if (tags != 0) {
 		if (tags != 0) {
 			// syntax_error(token, "A procedure type cannot have tags");
 			// syntax_error(token, "A procedure type cannot have tags");
 		}
 		}
@@ -3041,7 +3016,12 @@ void parse_foreign_block_decl(AstFile *f, Array<AstNode *> *decls) {
 
 
 AstNode *parse_foreign_block(AstFile *f, Token token) {
 AstNode *parse_foreign_block(AstFile *f, Token token) {
 	CommentGroup docs = f->lead_comment;
 	CommentGroup docs = f->lead_comment;
-	AstNode *foreign_library = parse_ident(f);
+	AstNode *foreign_library = nullptr;
+	if (f->curr_token.kind == Token_export) {
+		foreign_library = ast_implicit(f, expect_token(f, Token_export));
+	} else {
+		foreign_library = parse_ident(f);
+	}
 	Token open = {};
 	Token open = {};
 	Token close = {};
 	Token close = {};
 	Array<AstNode *> decls = make_ast_node_array(f);
 	Array<AstNode *> decls = make_ast_node_array(f);
@@ -3063,7 +3043,6 @@ AstNode *parse_foreign_block(AstFile *f, Token token) {
 		close = expect_token(f, Token_CloseBrace);
 		close = expect_token(f, Token_CloseBrace);
 	}
 	}
 
 
-
 	AstNode *decl = ast_foreign_block_decl(f, token, foreign_library, open, close, decls, docs);
 	AstNode *decl = ast_foreign_block_decl(f, token, foreign_library, open, close, decls, docs);
 	expect_semicolon(f, decl);
 	expect_semicolon(f, decl);
 	return decl;
 	return decl;
@@ -4409,6 +4388,7 @@ AstNode *parse_foreign_decl(AstFile *f) {
 	Token token = expect_token(f, Token_foreign);
 	Token token = expect_token(f, Token_foreign);
 
 
 	switch (f->curr_token.kind) {
 	switch (f->curr_token.kind) {
+	case Token_export:
 	case Token_Ident:
 	case Token_Ident:
 		return parse_foreign_block(f, token);
 		return parse_foreign_block(f, token);
 
 

+ 2 - 2
src/ssa.cpp

@@ -2431,7 +2431,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 			if (e->scope->is_init && name == "main") {
 			if (e->scope->is_init && name == "main") {
 				entry_point = e;
 				entry_point = e;
 			}
 			}
-			if ((e->Procedure.tags & ProcTag_export) != 0 ||
+			if ((e->flags & EntityFlag_ForeignExport) != 0 ||
 			    (e->Procedure.link_name.len > 0) ||
 			    (e->Procedure.link_name.len > 0) ||
 			    (e->scope->is_file && e->Procedure.link_name.len > 0)) {
 			    (e->scope->is_file && e->Procedure.link_name.len > 0)) {
 				if (!has_dll_main && name == "DllMain") {
 				if (!has_dll_main && name == "DllMain") {
@@ -2464,7 +2464,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 		}
 		}
 
 
 		if (!scope->is_global) {
 		if (!scope->is_global) {
-			if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
+			if (e->kind == Entity_Procedure && (e->flags & EntityFlag_ForeignExport) != 0) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
 				// Handle later
 				// Handle later
 			} else if (scope->is_init && e->kind == Entity_Procedure && name == "main") {
 			} else if (scope->is_init && e->kind == Entity_Procedure && name == "main") {