Browse Source

Move atomic intrinsics to the new built-in package intrinsics

gingerBill 6 years ago
parent
commit
3742d9e7e9
8 changed files with 215 additions and 180 deletions
  1. 63 61
      core/sync/atomic.odin
  2. 3 2
      src/check_expr.cpp
  3. 2 2
      src/check_stmt.cpp
  4. 2 2
      src/check_type.cpp
  5. 26 11
      src/checker.cpp
  6. 100 94
      src/checker.hpp
  7. 4 3
      src/entity.cpp
  8. 15 5
      src/parser.cpp

+ 63 - 61
core/sync/atomic.odin

@@ -1,5 +1,7 @@
 package sync
 
+import "intrinsics"
+
 Ordering :: enum {
 	Relaxed, // Monotonic
 	Release,
@@ -11,10 +13,10 @@ Ordering :: enum {
 strongest_failure_ordering :: inline proc "contextless" (order: Ordering) -> Ordering {
 	using Ordering;
 	#complete switch order {
-	case Relaxed: return Relaxed;
-	case Release: return Relaxed;
-	case Acquire: return Acquire;
-	case Acquire_Release: return Acquire;
+	case Relaxed:                 return Relaxed;
+	case Release:                 return Relaxed;
+	case Acquire:                 return Acquire;
+	case Acquire_Release:         return Acquire;
 	case Sequentially_Consistent: return Sequentially_Consistent;
 	}
 	return Relaxed;
@@ -23,11 +25,11 @@ strongest_failure_ordering :: inline proc "contextless" (order: Ordering) -> Ord
 fence :: proc "contextless" (order: Ordering) {
 	using Ordering;
 	#complete switch order {
-	case Relaxed: panic("there is no such thing as a relaxed fence");
-	case Release: __atomic_fence_rel();
-	case Acquire: __atomic_fence_acq();
-	case Acquire_Release:  __atomic_fence_acqrel();
-	case Sequentially_Consistent: __atomic_fence();
+	case Relaxed:                 panic("there is no such thing as a relaxed fence");
+	case Release:                 intrinsics.atomic_fence_rel();
+	case Acquire:                 intrinsics.atomic_fence_acq();
+	case Acquire_Release:         intrinsics.atomic_fence_acqrel();
+	case Sequentially_Consistent: intrinsics.atomic_fence();
 	case: panic("unknown order");
 	}
 }
@@ -36,10 +38,10 @@ fence :: proc "contextless" (order: Ordering) {
 atomic_store :: proc "contextless" (dst: ^$T, val: T, order: Ordering) {
 	using Ordering;
 	#complete switch order {
-	case Relaxed: __atomic_store_relaxed(dst, val);
-	case Release: __atomic_store_rel(dst, val);
-	case Sequentially_Consistent: __atomic_store(dst, val);
-	case Acquire: panic("there is not such thing as an acquire store");
+	case Relaxed:                 intrinsics.atomic_store_relaxed(dst, val);
+	case Release:                 intrinsics.atomic_store_rel(dst, val);
+	case Sequentially_Consistent: intrinsics.atomic_store(dst, val);
+	case Acquire:         panic("there is not such thing as an acquire store");
 	case Acquire_Release: panic("there is not such thing as an acquire/release store");
 	case: panic("unknown order");
 	}
@@ -48,10 +50,10 @@ atomic_store :: proc "contextless" (dst: ^$T, val: T, order: Ordering) {
 atomic_load :: proc "contextless" (dst: ^$T, order: Ordering) -> T {
 	using Ordering;
 	#complete switch order {
-	case Relaxed: return __atomic_load_relaxed(dst);
-	case Acquire: return __atomic_load_acq(dst);
-	case Sequentially_Consistent: return __atomic_load(dst);
-	case Release: panic("there is no such thing as a release load");
+	case Relaxed:                 return intrinsics.atomic_load_relaxed(dst);
+	case Acquire:                 return intrinsics.atomic_load_acq(dst);
+	case Sequentially_Consistent: return intrinsics.atomic_load(dst);
+	case Release:         panic("there is no such thing as a release load");
 	case Acquire_Release: panic("there is no such thing as an acquire/release load");
 	}
 	panic("unknown order");
@@ -61,11 +63,11 @@ atomic_load :: proc "contextless" (dst: ^$T, order: Ordering) -> T {
 atomic_swap :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 	using Ordering;
 	#complete switch order {
-	case Relaxed:                 return __atomic_xchg_relaxed(dst, val);
-	case Release:                 return __atomic_xchg_rel(dst, val);
-	case Acquire:                 return __atomic_xchg_acq(dst, val);
-	case Acquire_Release:         return __atomic_xchg_acqrel(dst, val);
-	case Sequentially_Consistent: return __atomic_xchg(dst, val);
+	case Relaxed:                 return intrinsics.atomic_xchg_relaxed(dst, val);
+	case Release:                 return intrinsics.atomic_xchg_rel(dst, val);
+	case Acquire:                 return intrinsics.atomic_xchg_acq(dst, val);
+	case Acquire_Release:         return intrinsics.atomic_xchg_acqrel(dst, val);
+	case Sequentially_Consistent: return intrinsics.atomic_xchg(dst, val);
 	}
 	panic("unknown order");
 	return T{};
@@ -76,23 +78,23 @@ atomic_compare_exchange :: proc "contextless" (dst: ^$T, old, new: T, success, f
 	switch failure {
 	case Relaxed:
 		switch success {
-		case Release:                 return __atomic_cxchg_rel_failrelaxed(dst, old, new);
-		case Relaxed:                 return __atomic_cxchg_relaxed(dst, old, new);
-		case Acquire:                 return __atomic_cxchg_acq_failrelaxed(dst, old, new);
-		case Acquire_Release:         return __atomic_cxchg_acqrel_failrelaxed(dst, old, new);
-		case Sequentially_Consistent: return __atomic_cxchg_failrelaxed(dst, old, new);
+		case Release:                 return intrinsics.atomic_cxchg_rel_failrelaxed(dst, old, new);
+		case Relaxed:                 return intrinsics.atomic_cxchg_relaxed(dst, old, new);
+		case Acquire:                 return intrinsics.atomic_cxchg_acq_failrelaxed(dst, old, new);
+		case Acquire_Release:         return intrinsics.atomic_cxchg_acqrel_failrelaxed(dst, old, new);
+		case Sequentially_Consistent: return intrinsics.atomic_cxchg_failrelaxed(dst, old, new);
 		case: panic("an unknown ordering combination");
 		}
 	case Acquire:
 		switch success {
-		case Acquire:                 return __atomic_cxchg_acq(dst, old, new);
-		case Acquire_Release:         return __atomic_cxchg_acqrel_failacq(dst, old, new);
-		case Sequentially_Consistent: return __atomic_acqrel_failacq(dst, old, new);
+		case Acquire:                 return intrinsics.atomic_cxchg_acq(dst, old, new);
+		case Acquire_Release:         return intrinsics.atomic_cxchg_acqrel_failacq(dst, old, new);
+		case Sequentially_Consistent: return intrinsics.atomic_acqrel_failacq(dst, old, new);
 		case: panic("an unknown ordering combination");
 		}
 	case Sequentially_Consistent:
 		switch success {
-		case Sequentially_Consistent: return __atomic_cxchg(dst, old, new);
+		case Sequentially_Consistent: return intrinsics.atomic_cxchg(dst, old, new);
 		case: panic("an unknown ordering combination");
 		}
 	case Acquire_Release:
@@ -108,11 +110,11 @@ atomic_compare_exchange :: proc "contextless" (dst: ^$T, old, new: T, success, f
 atomic_add :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 	using Ordering;
 	#complete switch order {
-	case Relaxed:                 return __atomic_add_relaxed(dst, val);
-	case Release:                 return __atomic_add_rel(dst, val);
-	case Acquire:                 return __atomic_add_acq(dst, val);
-	case Acquire_Release:         return __atomic_add_acqrel(dst, val);
-	case Sequentially_Consistent: return __atomic_add(dst, val);
+	case Relaxed:                 return intrinsics.atomic_add_relaxed(dst, val);
+	case Release:                 return intrinsics.atomic_add_rel(dst, val);
+	case Acquire:                 return intrinsics.atomic_add_acq(dst, val);
+	case Acquire_Release:         return intrinsics.atomic_add_acqrel(dst, val);
+	case Sequentially_Consistent: return intrinsics.atomic_add(dst, val);
 	}
 	panic("unknown order");
 	return T{};
@@ -121,11 +123,11 @@ atomic_add :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 atomic_sub :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 	using Ordering;
 	#complete switch order {
-	case Relaxed:                 return __atomic_sub_relaxed(dst, val);
-	case Release:                 return __atomic_sub_rel(dst, val);
-	case Acquire:                 return __atomic_sub_acq(dst, val);
-	case Acquire_Release:         return __atomic_sub_acqrel(dst, val);
-	case Sequentially_Consistent: return __atomic_sub(dst, val);
+	case Relaxed:                 return intrinsics.atomic_sub_relaxed(dst, val);
+	case Release:                 return intrinsics.atomic_sub_rel(dst, val);
+	case Acquire:                 return intrinsics.atomic_sub_acq(dst, val);
+	case Acquire_Release:         return intrinsics.atomic_sub_acqrel(dst, val);
+	case Sequentially_Consistent: return intrinsics.atomic_sub(dst, val);
 	}
 	panic("unknown order");
 	return T{};
@@ -134,11 +136,11 @@ atomic_sub :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 atomic_and :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 	using Ordering;
 	#complete switch order {
-	case Relaxed:                 return __atomic_and_relaxed(dst, val);
-	case Release:                 return __atomic_and_rel(dst, val);
-	case Acquire:                 return __atomic_and_acq(dst, val);
-	case Acquire_Release:         return __atomic_and_acqrel(dst, val);
-	case Sequentially_Consistent: return __atomic_and(dst, val);
+	case Relaxed:                 return intrinsics.atomic_and_relaxed(dst, val);
+	case Release:                 return intrinsics.atomic_and_rel(dst, val);
+	case Acquire:                 return intrinsics.atomic_and_acq(dst, val);
+	case Acquire_Release:         return intrinsics.atomic_and_acqrel(dst, val);
+	case Sequentially_Consistent: return intrinsics.atomic_and(dst, val);
 	}
 	panic("unknown order");
 	return T{};
@@ -147,11 +149,11 @@ atomic_and :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 atomic_nand :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 	using Ordering;
 	#complete switch order {
-	case Relaxed:                 return __atomic_nand_relaxed(dst, val);
-	case Release:                 return __atomic_nand_rel(dst, val);
-	case Acquire:                 return __atomic_nand_acq(dst, val);
-	case Acquire_Release:         return __atomic_nand_acqrel(dst, val);
-	case Sequentially_Consistent: return __atomic_nand(dst, val);
+	case Relaxed:                 return intrinsics.atomic_nand_relaxed(dst, val);
+	case Release:                 return intrinsics.atomic_nand_rel(dst, val);
+	case Acquire:                 return intrinsics.atomic_nand_acq(dst, val);
+	case Acquire_Release:         return intrinsics.atomic_nand_acqrel(dst, val);
+	case Sequentially_Consistent: return intrinsics.atomic_nand(dst, val);
 	}
 	panic("unknown order");
 	return T{};
@@ -160,11 +162,11 @@ atomic_nand :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 atomic_or :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 	using Ordering;
 	#complete switch order {
-	case Relaxed:                 return __atomic_or_relaxed(dst, val);
-	case Release:                 return __atomic_or_rel(dst, val);
-	case Acquire:                 return __atomic_or_acq(dst, val);
-	case Acquire_Release:         return __atomic_or_acqrel(dst, val);
-	case Sequentially_Consistent: return __atomic_or(dst, val);
+	case Relaxed:                 return intrinsics.atomic_or_relaxed(dst, val);
+	case Release:                 return intrinsics.atomic_or_rel(dst, val);
+	case Acquire:                 return intrinsics.atomic_or_acq(dst, val);
+	case Acquire_Release:         return intrinsics.atomic_or_acqrel(dst, val);
+	case Sequentially_Consistent: return intrinsics.atomic_or(dst, val);
 	}
 	panic("unknown order");
 	return T{};
@@ -173,11 +175,11 @@ atomic_or :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 atomic_xor :: proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T {
 	using Ordering;
 	#complete switch order {
-	case Relaxed:                 return __atomic_xor_relaxed(dst, val);
-	case Release:                 return __atomic_xor_rel(dst, val);
-	case Acquire:                 return __atomic_xor_acq(dst, val);
-	case Acquire_Release:         return __atomic_xor_acqrel(dst, val);
-	case Sequentially_Consistent: return __atomic_xor(dst, val);
+	case Relaxed:                 return intrinsics.atomic_xor_relaxed(dst, val);
+	case Release:                 return intrinsics.atomic_xor_rel(dst, val);
+	case Acquire:                 return intrinsics.atomic_xor_acq(dst, val);
+	case Acquire_Release:         return intrinsics.atomic_xor_acqrel(dst, val);
+	case Sequentially_Consistent: return intrinsics.atomic_xor(dst, val);
 	}
 	panic("unknown order");
 	return T{};

+ 3 - 2
src/check_expr.cpp

@@ -2704,11 +2704,12 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
 			check_op_expr = false;
 			entity = scope_lookup_current(import_scope, entity_name);
 			bool is_declared = entity != nullptr;
+			bool allow_builtin = false;
 			if (is_declared) {
 				if (entity->kind == Entity_Builtin) {
 					// NOTE(bill): Builtin's are in the universal scope which is part of every scopes hierarchy
 					// This means that we should just ignore the found result through it
-					is_declared = false;
+					allow_builtin = entity->scope == import_scope;
 				} else if ((entity->scope->flags&ScopeFlag_Global) == ScopeFlag_Global && (import_scope->flags&ScopeFlag_Global) == 0) {
 					is_declared = false;
 				}
@@ -2723,7 +2724,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
 			check_entity_decl(c, entity, nullptr, nullptr);
 			GB_ASSERT(entity->type != nullptr);
 
-			if (!is_entity_exported(entity)) {
+			if (!is_entity_exported(entity, allow_builtin)) {
 				gbString sel_str = expr_to_string(selector);
 				error(op_expr, "'%s' is not exported by '%.*s'", sel_str, LIT(import_name));
 				gb_string_free(sel_str);

+ 2 - 2
src/check_stmt.cpp

@@ -1484,7 +1484,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 			}
 
 			if (entity == nullptr) {
-				entity = alloc_entity_dummy_variable(builtin_scope, ast_token(name));
+				entity = alloc_entity_dummy_variable(builtin_pkg->scope, ast_token(name));
 			}
 
 			entities[entity_count++] = entity;
@@ -1663,7 +1663,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 					}
 				}
 				if (entity == nullptr) {
-					entity = alloc_entity_dummy_variable(builtin_scope, ast_token(name));
+					entity = alloc_entity_dummy_variable(builtin_pkg->scope, ast_token(name));
 				}
 				entity->parent_proc_decl = ctx->curr_proc_decl;
 				entities[entity_count++] = entity;

+ 2 - 2
src/check_type.cpp

@@ -2096,7 +2096,7 @@ void init_map_entry_type(Type *type) {
 	}
 	*/
 	Ast *dummy_node = alloc_ast_node(nullptr, Ast_Invalid);
-	Scope *s = create_scope(builtin_scope, a);
+	Scope *s = create_scope(builtin_pkg->scope, a);
 
 	auto fields = array_make<Entity *>(a, 0, 3);
 	array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("key")),   t_map_key,       false, 0, EntityState_Resolved));
@@ -2131,7 +2131,7 @@ void init_map_internal_types(Type *type) {
 	*/
 	gbAllocator a = heap_allocator();
 	Ast *dummy_node = alloc_ast_node(nullptr, Ast_Invalid);
-	Scope *s = create_scope(builtin_scope, a);
+	Scope *s = create_scope(builtin_pkg->scope, a);
 
 	Type *hashes_type  = alloc_type_slice(t_int);
 	Type *entries_type = alloc_type_dynamic_array(type->Map.entry_type);

+ 26 - 11
src/checker.cpp

@@ -252,7 +252,7 @@ Scope *create_scope_from_package(CheckerContext *c, AstPackage *pkg) {
 		decl_count += pkg->files[i]->decls.count;
 	}
 	isize init_elements_capacity = 2*decl_count;
-	Scope *s = create_scope(builtin_scope, c->allocator, init_elements_capacity);
+	Scope *s = create_scope(builtin_pkg->scope, c->allocator, init_elements_capacity);
 
 	s->flags |= ScopeFlag_Pkg;
 	s->pkg = pkg;
@@ -492,14 +492,14 @@ void add_declaration_dependency(CheckerContext *c, Entity *e) {
 }
 
 
-Entity *add_global_entity(Entity *entity) {
+Entity *add_global_entity(Entity *entity, Scope *scope=builtin_pkg->scope) {
 	String name = entity->token.string;
 	defer (entity->state = EntityState_Resolved);
 
 	if (gb_memchr(name.text, ' ', name.len)) {
 		return entity; // NOTE(bill): Usually an 'untyped thing'
 	}
-	if (scope_insert(builtin_scope, entity)) {
+	if (scope_insert(scope, entity)) {
 		compiler_error("double declaration");
 	}
 	return entity;
@@ -532,12 +532,17 @@ void init_universal(void) {
 	builtin_pkg->name = str_lit("builtin");
 	builtin_pkg->kind = Package_Normal;
 
-	builtin_scope = create_scope(nullptr, a);
-	builtin_scope->flags |= ScopeFlag_Pkg | ScopeFlag_Global;
-	builtin_scope->pkg = builtin_pkg;
-	builtin_pkg->scope = builtin_scope;
+	builtin_pkg->scope = create_scope(nullptr, a);
+	builtin_pkg->scope->flags |= ScopeFlag_Pkg | ScopeFlag_Global;
+	builtin_pkg->scope->pkg = builtin_pkg;
 
+	intrinsics_pkg = gb_alloc_item(a, AstPackage);
+	intrinsics_pkg->name = str_lit("intrinsics");
+	intrinsics_pkg->kind = Package_Normal;
 
+	intrinsics_pkg->scope = create_scope(nullptr, a);
+	intrinsics_pkg->scope->flags |= ScopeFlag_Pkg | ScopeFlag_Global;
+	intrinsics_pkg->scope->pkg = intrinsics_pkg;
 
 
 // Types
@@ -566,7 +571,15 @@ void init_universal(void) {
 		if (name != "") {
 			Entity *entity = alloc_entity(Entity_Builtin, nullptr, make_token_ident(name), t_invalid);
 			entity->Builtin.id = id;
-			add_global_entity(entity);
+			switch (builtin_procs[i].pkg) {
+			case BuiltinProcPkg_builtin:
+				add_global_entity(entity, builtin_pkg->scope);
+				break;
+			case BuiltinProcPkg_intrinsics:
+				add_global_entity(entity, intrinsics_pkg->scope);
+				GB_ASSERT(scope_lookup_current(intrinsics_pkg->scope, name) != nullptr);
+				break;
+			}
 		}
 	}
 
@@ -2006,8 +2019,8 @@ void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<Ast *> *attr
 			}
 
 			if (name == "builtin") {
-				add_entity(ctx->checker, builtin_scope, nullptr, e);
-				GB_ASSERT(scope_lookup(builtin_scope, e->token.string) != nullptr);
+				add_entity(ctx->checker, builtin_pkg->scope, nullptr, e);
+				GB_ASSERT(scope_lookup(builtin_pkg->scope, e->token.string) != nullptr);
 				if (value != nullptr) {
 					error(value, "'builtin' cannot have a field value");
 				}
@@ -2448,7 +2461,7 @@ void add_import_dependency_node(Checker *c, Ast *decl, Map<ImportGraphNode *> *M
 	switch (decl->kind) {
 	case_ast_node(id, ImportDecl, decl);
 		String path = id->fullpath;
-		if (path == "builtin") {
+		if (is_package_name_reserved(path)) {
 			return;
 		}
 		HashKey key = hash_string(path);
@@ -2620,6 +2633,8 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) {
 
 	if (id->fullpath == "builtin") {
 		scope = builtin_pkg->scope;
+	} else if (id->fullpath == "intrinsics") {
+		scope = intrinsics_pkg->scope;
 	} else {
 		HashKey key = hash_string(id->fullpath);
 		AstPackage **found = map_get(pkgs, key);

+ 100 - 94
src/checker.hpp

@@ -46,12 +46,19 @@ enum StmtFlag {
 	Stmt_CheckScopeDecls    = 1<<5,
 };
 
+enum BuiltinProcPkg {
+	BuiltinProcPkg_builtin,
+	BuiltinProcPkg_intrinsics,
+};
+
 struct BuiltinProc {
 	String   name;
 	isize    arg_count;
 	bool     variadic;
 	ExprKind kind;
+	BuiltinProcPkg pkg;
 };
+
 enum BuiltinProcId {
 	BuiltinProc_Invalid,
 
@@ -157,107 +164,107 @@ enum BuiltinProcId {
 	BuiltinProc_COUNT,
 };
 gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
-	{STR_LIT(""),                 0, false, Expr_Stmt},
+	{STR_LIT(""),                 0, false, Expr_Stmt, BuiltinProcPkg_builtin},
 
-	{STR_LIT("len"),              1, false, Expr_Expr},
-	{STR_LIT("cap"),              1, false, Expr_Expr},
+	{STR_LIT("len"),              1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("cap"),              1, false, Expr_Expr, BuiltinProcPkg_builtin},
 
-	{STR_LIT("size_of"),          1, false, Expr_Expr},
-	{STR_LIT("align_of"),         1, false, Expr_Expr},
-	{STR_LIT("offset_of"),        2, false, Expr_Expr},
-	{STR_LIT("type_of"),          1, false, Expr_Expr},
-	{STR_LIT("type_info_of"),     1, false, Expr_Expr},
-	{STR_LIT("typeid_of"),        1, false, Expr_Expr},
+	{STR_LIT("size_of"),          1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("align_of"),         1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("offset_of"),        2, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("type_of"),          1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("type_info_of"),     1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("typeid_of"),        1, false, Expr_Expr, BuiltinProcPkg_builtin},
 
-	{STR_LIT("swizzle"),          1, true,  Expr_Expr},
+	{STR_LIT("swizzle"),          1, true,  Expr_Expr, BuiltinProcPkg_builtin},
 
-	{STR_LIT("complex"),          2, false, Expr_Expr},
-	{STR_LIT("real"),             1, false, Expr_Expr},
-	{STR_LIT("imag"),             1, false, Expr_Expr},
-	{STR_LIT("conj"),             1, false, Expr_Expr},
+	{STR_LIT("complex"),          2, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("real"),             1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("imag"),             1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("conj"),             1, false, Expr_Expr, BuiltinProcPkg_builtin},
 
-	{STR_LIT("expand_to_tuple"),  1, false, Expr_Expr},
+	{STR_LIT("expand_to_tuple"),  1, false, Expr_Expr, BuiltinProcPkg_builtin},
 
-	{STR_LIT("min"),              2, true,  Expr_Expr},
-	{STR_LIT("max"),              2, true,  Expr_Expr},
-	{STR_LIT("abs"),              1, false, Expr_Expr},
-	{STR_LIT("clamp"),            3, false, Expr_Expr},
+	{STR_LIT("min"),              2, true,  Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("max"),              2, true,  Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("abs"),              1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("clamp"),            3, false, Expr_Expr, BuiltinProcPkg_builtin},
 
-	{STR_LIT(""),                 0, true,  Expr_Expr}, // DIRECTIVE
+	{STR_LIT(""),                 0, true,  Expr_Expr, BuiltinProcPkg_builtin}, // DIRECTIVE
 
 
 	// "Intrinsics"
-	{STR_LIT("__atomic_fence"),        0, false, Expr_Stmt},
-	{STR_LIT("__atomic_fence_acq"),    0, false, Expr_Stmt},
-	{STR_LIT("__atomic_fence_rel"),    0, false, Expr_Stmt},
-	{STR_LIT("__atomic_fence_acqrel"), 0, false, Expr_Stmt},
-
-	{STR_LIT("__atomic_store"),           2, false, Expr_Stmt},
-	{STR_LIT("__atomic_store_rel"),       2, false, Expr_Stmt},
-	{STR_LIT("__atomic_store_relaxed"),   2, false, Expr_Stmt},
-	{STR_LIT("__atomic_store_unordered"), 2, false, Expr_Stmt},
-
-	{STR_LIT("__atomic_load"),            1, false, Expr_Expr},
-	{STR_LIT("__atomic_load_acq"),        1, false, Expr_Expr},
-	{STR_LIT("__atomic_load_relaxed"),    1, false, Expr_Expr},
-	{STR_LIT("__atomic_load_unordered"),  1, false, Expr_Expr},
-
-	{STR_LIT("__atomic_add"),             2, false, Expr_Expr},
-	{STR_LIT("__atomic_add_acq"),         2, false, Expr_Expr},
-	{STR_LIT("__atomic_add_rel"),         2, false, Expr_Expr},
-	{STR_LIT("__atomic_add_acqrel"),      2, false, Expr_Expr},
-	{STR_LIT("__atomic_add_relaxed"),     2, false, Expr_Expr},
-	{STR_LIT("__atomic_sub"),             2, false, Expr_Expr},
-	{STR_LIT("__atomic_sub_acq"),         2, false, Expr_Expr},
-	{STR_LIT("__atomic_sub_rel"),         2, false, Expr_Expr},
-	{STR_LIT("__atomic_sub_acqrel"),      2, false, Expr_Expr},
-	{STR_LIT("__atomic_sub_relaxed"),     2, false, Expr_Expr},
-	{STR_LIT("__atomic_and"),             2, false, Expr_Expr},
-	{STR_LIT("__atomic_and_acq"),         2, false, Expr_Expr},
-	{STR_LIT("__atomic_and_rel"),         2, false, Expr_Expr},
-	{STR_LIT("__atomic_and_acqrel"),      2, false, Expr_Expr},
-	{STR_LIT("__atomic_and_relaxed"),     2, false, Expr_Expr},
-	{STR_LIT("__atomic_nand"),            2, false, Expr_Expr},
-	{STR_LIT("__atomic_nand_acq"),        2, false, Expr_Expr},
-	{STR_LIT("__atomic_nand_rel"),        2, false, Expr_Expr},
-	{STR_LIT("__atomic_nand_acqrel"),     2, false, Expr_Expr},
-	{STR_LIT("__atomic_nand_relaxed"),    2, false, Expr_Expr},
-	{STR_LIT("__atomic_or"),              2, false, Expr_Expr},
-	{STR_LIT("__atomic_or_acq"),          2, false, Expr_Expr},
-	{STR_LIT("__atomic_or_rel"),          2, false, Expr_Expr},
-	{STR_LIT("__atomic_or_acqrel"),       2, false, Expr_Expr},
-	{STR_LIT("__atomic_or_relaxed"),      2, false, Expr_Expr},
-	{STR_LIT("__atomic_xor"),             2, false, Expr_Expr},
-	{STR_LIT("__atomic_xor_acq"),         2, false, Expr_Expr},
-	{STR_LIT("__atomic_xor_rel"),         2, false, Expr_Expr},
-	{STR_LIT("__atomic_xor_acqrel"),      2, false, Expr_Expr},
-	{STR_LIT("__atomic_xor_relaxed"),     2, false, Expr_Expr},
-
-	{STR_LIT("__atomic_xchg"),            2, false, Expr_Expr},
-	{STR_LIT("__atomic_xchg_acq"),        2, false, Expr_Expr},
-	{STR_LIT("__atomic_xchg_rel"),        2, false, Expr_Expr},
-	{STR_LIT("__atomic_xchg_acqrel"),     2, false, Expr_Expr},
-	{STR_LIT("__atomic_xchg_relaxed"),    2, false, Expr_Expr},
-
-	{STR_LIT("__atomic_cxchg"),                    3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchg_acq"),                3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchg_rel"),                3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchg_acqrel"),             3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchg_relaxed"),            3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchg_failrelaxed"),        3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchg_failacq"),            3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchg_acq_failrelaxed"),    3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchg_acqrel_failrelaxed"), 3, false, Expr_Expr},
-
-	{STR_LIT("__atomic_cxchgweak"),                    3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchgweak_acq"),                3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchgweak_rel"),                3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchgweak_acqrel"),             3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchgweak_relaxed"),            3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchgweak_failrelaxed"),        3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchgweak_failacq"),            3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchgweak_acq_failrelaxed"),    3, false, Expr_Expr},
-	{STR_LIT("__atomic_cxchgweak_acqrel_failrelaxed"), 3, false, Expr_Expr},
+	{STR_LIT("atomic_fence"),        0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_fence_acq"),    0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_fence_rel"),    0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_fence_acqrel"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_store"),           2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_store_rel"),       2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_store_relaxed"),   2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_store_unordered"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_load"),            1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_load_acq"),        1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_load_relaxed"),    1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_load_unordered"),  1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_add"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_add_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_add_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_add_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_add_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand"),            2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand_acq"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand_rel"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand_acqrel"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand_relaxed"),    2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or"),              2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or_acq"),          2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or_rel"),          2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or_acqrel"),       2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or_relaxed"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_xchg"),            2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xchg_acq"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xchg_rel"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xchg_acqrel"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xchg_relaxed"),    2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_cxchg"),                    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_acq"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_rel"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_acqrel"),             3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_relaxed"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_failrelaxed"),        3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_failacq"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_acq_failrelaxed"),    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_acqrel_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_cxchgweak"),                    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_acq"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_rel"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_acqrel"),             3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_relaxed"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_failrelaxed"),        3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_failacq"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_acq_failrelaxed"),    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_acqrel_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 };
 
 
@@ -480,9 +487,8 @@ struct Checker {
 
 
 
-gb_global AstPackage *builtin_pkg   = nullptr;
-gb_global Scope *     builtin_scope = nullptr;
-
+gb_global AstPackage *builtin_pkg    = nullptr;
+gb_global AstPackage *intrinsics_pkg = nullptr;
 
 
 HashKey hash_node     (Ast *node)  { return hash_pointer(node); }

+ 4 - 3
src/entity.cpp

@@ -153,9 +153,10 @@ struct Entity {
 	};
 };
 
-bool is_entity_kind_exported(EntityKind kind) {
+bool is_entity_kind_exported(EntityKind kind, bool allow_builtin = false) {
 	switch (kind) {
 	case Entity_Builtin:
+		return allow_builtin;
 	case Entity_ImportName:
 	case Entity_LibraryName:
 	case Entity_Nil:
@@ -164,10 +165,10 @@ bool is_entity_kind_exported(EntityKind kind) {
 	return true;
 }
 
-bool is_entity_exported(Entity *e) {
+bool is_entity_exported(Entity *e, bool allow_builtin = false) {
 	// TODO(bill): Determine the actual exportation rules for imports of entities
 	GB_ASSERT(e != nullptr);
-	if (!is_entity_kind_exported(e->kind)) {
+	if (!is_entity_kind_exported(e->kind, allow_builtin)) {
 		return false;
 	}
 

+ 15 - 5
src/parser.cpp

@@ -4142,6 +4142,17 @@ bool is_import_path_valid(String path) {
 	return false;
 }
 
+
+bool is_package_name_reserved(String const &name) {
+	if (name == "builtin") {
+		return true;
+	} else if (name == "intrinsics") {
+		return true;
+	}
+	return false;
+}
+
+
 bool determine_path_from_string(Parser *p, Ast *node, String base_dir, String original_string, String *path) {
 	GB_ASSERT(path != nullptr);
 
@@ -4212,9 +4223,8 @@ bool determine_path_from_string(Parser *p, Ast *node, String base_dir, String or
 #endif
 	}
 
-
-	if (file_str == "builtin") {
-		*path = str_lit("builtin");
+	if (is_package_name_reserved(file_str)) {
+		*path = file_str;
 	} else {
 		String fullpath = string_trim_whitespace(get_fullpath_relative(a, base_dir, file_str));
 		*path = fullpath;
@@ -4278,7 +4288,7 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<Ast *>
 			import_path = string_trim_whitespace(import_path);
 
 			id->fullpath = import_path;
-			if (import_path == "builtin") {
+			if (is_package_name_reserved(import_path)) {
 				continue;
 			}
 			try_add_import_path(p, import_path, original_string, ast_token(node).pos);
@@ -4425,7 +4435,7 @@ bool parse_file(Parser *p, AstFile *f) {
 			error(package_name, "Invalid package name '_'");
 		} else if (f->pkg->kind != Package_Runtime && package_name.string == "runtime") {
 			error(package_name, "Use of reserved package name '%.*s'", LIT(package_name.string));
-		} else if (package_name.string == "builtin") {
+		} else if (is_package_name_reserved(package_name.string)) {
 			error(package_name, "Use of reserved package name '%.*s'", LIT(package_name.string));
 		}
 	}