Browse Source

Replace `foreign export {}` with `@export`

gingerBill 6 years ago
parent
commit
e551d2b25e
7 changed files with 70 additions and 30 deletions
  1. 6 5
      src/check_decl.cpp
  2. 16 0
      src/check_expr.cpp
  3. 5 1
      src/check_type.cpp
  4. 40 14
      src/checker.cpp
  5. 1 1
      src/checker.hpp
  6. 2 8
      src/parser.cpp
  7. 0 1
      src/tokenizer.cpp

+ 6 - 5
src/check_decl.cpp

@@ -551,20 +551,20 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
 	check_procedure_type(&tmp_ctx, proc_type, pl->type);
 
 	TypeProc *pt = &proc_type->Proc;
-
-	bool is_foreign         = e->Procedure.is_foreign;
-	bool is_export          = e->Procedure.is_export;
-	bool is_require_results = (pl->tags & ProcTag_require_results) != 0;
-
 	AttributeContext ac = make_attribute_context(e->Procedure.link_prefix);
 
 	if (d != nullptr) {
 		check_decl_attributes(ctx, d->attributes, proc_decl_attribute, &ac);
 	}
 
+	e->Procedure.is_export = ac.is_export;
 	e->deprecated_message = ac.deprecated_message;
 	ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix);
 
+	bool is_foreign         = e->Procedure.is_foreign;
+	bool is_export          = e->Procedure.is_export;
+	bool is_require_results = (pl->tags & ProcTag_require_results) != 0;
+
 	if (e->pkg != nullptr && e->token.string == "main") {
 		if (pt->param_count != 0 ||
 		    pt->result_count != 0) {
@@ -718,6 +718,7 @@ void check_var_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init_ex
 		check_decl_attributes(ctx, decl->attributes, var_decl_attribute, &ac);
 	}
 
+	e->Variable.is_export = ac.is_export;
 	ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix);
 	e->Variable.thread_local_model = ac.thread_local_model;
 

+ 16 - 0
src/check_expr.cpp

@@ -1241,6 +1241,14 @@ bool check_binary_op(CheckerContext *c, Operand *o, Token op) {
 			error(op, "Operator '%.*s' is only allowed with integers", LIT(op.string));
 			return false;
 		}
+		if (is_type_simd_vector(o->type)) {
+			switch (op.kind) {
+			case Token_ModMod:
+			case Token_ModModEq:
+				error(op, "Operator '%.*s' is only allowed with integers", LIT(op.string));
+				return false;
+			}
+		}
 		break;
 
 	case Token_AndNot:
@@ -1249,6 +1257,14 @@ bool check_binary_op(CheckerContext *c, Operand *o, Token op) {
 			error(op, "Operator '%.*s' is only allowed with integers and bit sets", LIT(op.string));
 			return false;
 		}
+		if (is_type_simd_vector(o->type)) {
+			switch (op.kind) {
+			case Token_AndNot:
+			case Token_AndNotEq:
+				error(op, "Operator '%.*s' is only allowed with integers", LIT(op.string));
+				return false;
+			}
+		}
 		break;
 
 	case Token_CmpAnd:

+ 5 - 1
src/check_type.cpp

@@ -1783,7 +1783,11 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
 	Type *new_type = original_type;
 
 	if (is_type_boolean(original_type)) {
-		return t_llvm_bool;
+		Type *t = core_type(base_type(new_type));
+		if (t == t_bool) {
+			return t_llvm_bool;
+		}
+		return new_type;
 	}
 
 	if (build_context.ODIN_ARCH == "386") {

+ 40 - 14
src/checker.cpp

@@ -1952,7 +1952,18 @@ DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) {
 }
 
 DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
-	if (name == "deferred") {
+	if (name == "export") {
+		ExactValue ev = check_decl_attribute_value(c, value);
+		if (ev.kind == ExactValue_Invalid) {
+			ac->is_export = true;
+		} else if (ev.kind == ExactValue_Bool) {
+			ac->is_export = ev.value_bool;
+		} else {
+			error(value, "Expected either a boolean or no parameter for 'export'");
+			return false;
+		}
+		return true;
+	} else if (name == "deferred") {
 		if (value != nullptr) {
 			Operand o = {};
 			check_expr(c, &o, value);
@@ -2064,7 +2075,20 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) {
 		return true;
 	}
 
-	if (name == "link_name") {
+	if (name == "export") {
+		ExactValue ev = check_decl_attribute_value(c, value);
+		if (ev.kind == ExactValue_Invalid) {
+			ac->is_export = true;
+		} else if (ev.kind == ExactValue_Bool) {
+			ac->is_export = ev.value_bool;
+		} else {
+			error(value, "Expected either a boolean or no parameter for 'export'");
+			return false;
+		}
+		if (ac->thread_local_model != "") {
+			error(elem, "An exported variable cannot be thread local");
+		}
+	} else if (name == "link_name") {
 		if (ev.kind == ExactValue_String) {
 			ac->link_name = ev.value_string;
 			if (!is_foreign_name_valid(ac->link_name)) {
@@ -2087,8 +2111,10 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) {
 	} else if (name == "thread_local") {
 		if (ac->init_expr_list_count > 0) {
 			error(elem, "A thread local variable declaration cannot have initialization values");
-		} else if (c->foreign_context.curr_library || c->foreign_context.in_export) {
+		} else if (c->foreign_context.curr_library) {
 			error(elem, "A foreign block variable cannot be thread local");
+		} else if (ac->is_export) {
+			error(elem, "An exported variable cannot be thread local");
 		} else if (ev.kind == ExactValue_Invalid) {
 			ac->thread_local_model = str_lit("default");
 		} else if (ev.kind == ExactValue_String) {
@@ -2151,9 +2177,17 @@ void check_decl_attributes(CheckerContext *c, Array<Ast *> const &attributes, De
 			case_ast_node(i, Ident, elem);
 				name = i->token.string;
 			case_end;
+			case_ast_node(i, Implicit, elem);
+				name = i->string;
+			case_end;
 			case_ast_node(fv, FieldValue, elem);
-				GB_ASSERT(fv->field->kind == Ast_Ident);
-				name = fv->field->Ident.token.string;
+				if (fv->field->kind == Ast_Ident) {
+					name = fv->field->Ident.token.string;
+				} else if (fv->field->kind == Ast_Implicit) {
+					name = fv->field->Implicit.string;
+				} else {
+					GB_PANIC("Unknown Field Value name");
+				}
 				value = fv->value;
 			case_end;
 			default:
@@ -2407,9 +2441,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
 				e->Variable.foreign_library_ident = fl;
 
 				e->Variable.link_prefix = c->foreign_context.link_prefix;
-
-			} else if (c->foreign_context.in_export) {
-				e->Variable.is_export = true;
 			}
 
 			Ast *init_expr = value;
@@ -2475,9 +2506,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
 
 					GB_ASSERT(cc != ProcCC_Invalid);
 					pl->type->ProcType.calling_convention = cc;
-
-				} else if (c->foreign_context.in_export) {
-					e->Procedure.is_export = true;
 				}
 				d->proc_lit = init;
 				d->type_expr = pl->type;
@@ -2516,7 +2544,7 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
 			}
 
 			if (e->kind != Entity_Procedure) {
-				if (fl != nullptr || c->foreign_context.in_export) {
+				if (fl != nullptr) {
 					AstKind kind = init->kind;
 					error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_strings[kind]));
 					if (kind == Ast_ProcType) {
@@ -2544,8 +2572,6 @@ void check_add_foreign_block_decl(CheckerContext *ctx, Ast *decl) {
 	CheckerContext c = *ctx;
 	if (foreign_library->kind == Ast_Ident) {
 		c.foreign_context.curr_library = foreign_library;
-	} else if (foreign_library->kind == Ast_Implicit && foreign_library->Implicit.kind == Token_export) {
-		c.foreign_context.in_export = true;
 	} else {
 		error(foreign_library, "Foreign block name must be an identifier or 'export'");
 		c.foreign_context.curr_library = nullptr;

+ 1 - 1
src/checker.hpp

@@ -305,6 +305,7 @@ struct DeferredProcedure {
 
 
 struct AttributeContext {
+	bool    is_export;
 	String  link_name;
 	String  link_prefix;
 	isize   init_expr_list_count;
@@ -423,7 +424,6 @@ struct ForeignContext {
 	Ast *                 curr_library;
 	ProcCallingConvention default_cc;
 	String                link_prefix;
-	bool                  in_export;
 };
 
 typedef Array<Entity *> CheckerTypePath;

+ 2 - 8
src/parser.cpp

@@ -1199,7 +1199,6 @@ void fix_advance_to_next_stmt(AstFile *f) {
 		case Token_package:
 		case Token_foreign:
 		case Token_import:
-		case Token_export:
 
 		case Token_if:
 		case Token_for:
@@ -2452,9 +2451,7 @@ void parse_foreign_block_decl(AstFile *f, Array<Ast *> *decls) {
 Ast *parse_foreign_block(AstFile *f, Token token) {
 	CommentGroup *docs = f->lead_comment;
 	Ast *foreign_library = nullptr;
-	if (f->curr_token.kind == Token_export) {
-		foreign_library = ast_implicit(f, expect_token(f, Token_export));
-	} else if (f->curr_token.kind == Token_OpenBrace) {
+	if (f->curr_token.kind == Token_OpenBrace) {
 		foreign_library = ast_ident(f, blank_token);
 	} else {
 		foreign_library = parse_ident(f);
@@ -3590,7 +3587,6 @@ Ast *parse_foreign_decl(AstFile *f) {
 	Token token = expect_token(f, Token_foreign);
 
 	switch (f->curr_token.kind) {
-	case Token_export:
 	case Token_Ident:
 	case Token_OpenBrace:
 		return parse_foreign_block(f, token);
@@ -3667,6 +3663,7 @@ Ast *parse_attribute(AstFile *f, Token token, TokenKind open_kind, TokenKind clo
 			       f->curr_token.kind != Token_EOF) {
 				Ast *elem = nullptr;
 				elem = parse_ident(f);
+
 				if (f->curr_token.kind == Token_Eq) {
 					Token eq = expect_token(f, Token_Eq);
 					Ast *value = parse_value(f);
@@ -3732,9 +3729,6 @@ Ast *parse_stmt(AstFile *f) {
 	case Token_import:
 		return parse_import_decl(f, ImportDecl_Standard);
 
-	// case Token_export:
-	// 	return parse_export_decl(f);
-
 
 	case Token_if:     return parse_if_stmt(f);
 	case Token_when:   return parse_when_stmt(f);

+ 0 - 1
src/tokenizer.cpp

@@ -82,7 +82,6 @@ TOKEN_KIND(Token__OperatorEnd, ""), \
 \
 TOKEN_KIND(Token__KeywordBegin, ""), \
 	TOKEN_KIND(Token_import,      "import"),      \
-	TOKEN_KIND(Token_export,      "export"),      \
 	TOKEN_KIND(Token_foreign,     "foreign"),     \
 	TOKEN_KIND(Token_package,     "package"),     \
 	TOKEN_KIND(Token_typeid,      "typeid"),      \