Browse Source

Remove need for __llvm_core

gingerBill 7 years ago
parent
commit
398109ac84
10 changed files with 75 additions and 73 deletions
  1. 25 25
      core/bits/bits.odin
  2. 1 1
      core/math/math.odin
  3. 4 4
      core/mem/mem.odin
  4. 1 1
      core/runtime/core.odin
  5. 23 23
      core/runtime/internal.odin
  6. 4 1
      examples/demo/demo.odin
  7. 1 1
      src/check_decl.cpp
  8. 3 6
      src/checker.cpp
  9. 3 1
      src/ir.cpp
  10. 10 10
      src/parser.cpp

+ 25 - 25
core/bits/bits.odin

@@ -22,7 +22,7 @@ I16_MAX  ::  -I16_MIN - 1;
 I32_MAX  ::  -I32_MIN - 1;
 I64_MAX  ::  -I64_MIN - 1;
 
-foreign __llvm_core {
+foreign {
 	@(link_name="llvm.ctpop.i8")        __llvm_ctpop8   :: proc(u8)   ->   u8 ---;
 	@(link_name="llvm.ctpop.i16")       __llvm_ctpop16  :: proc(u16)  ->  u16 ---;
 	@(link_name="llvm.ctpop.i32")       __llvm_ctpop32  :: proc(u32)  ->  u32 ---;
@@ -122,14 +122,14 @@ to_le_u64  :: proc(i:  u64) ->  u64 { when os.ENDIAN == "little" { return i; } e
 to_le_uint :: proc(i: uint) -> uint { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
 
 
-overflowing_add_u8   :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
-overflowing_add_i8   :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
-overflowing_add_u16  :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
-overflowing_add_i16  :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
-overflowing_add_u32  :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
-overflowing_add_i32  :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
-overflowing_add_u64  :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
-overflowing_add_i64  :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
+overflowing_add_u8   :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign { @(link_name="llvm.uadd.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   --- }; return op(lhs, rhs); }
+overflowing_add_i8   :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign { @(link_name="llvm.sadd.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   --- }; return op(lhs, rhs); }
+overflowing_add_u16  :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign { @(link_name="llvm.uadd.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  --- }; return op(lhs, rhs); }
+overflowing_add_i16  :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign { @(link_name="llvm.sadd.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  --- }; return op(lhs, rhs); }
+overflowing_add_u32  :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign { @(link_name="llvm.uadd.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  --- }; return op(lhs, rhs); }
+overflowing_add_i32  :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign { @(link_name="llvm.sadd.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  --- }; return op(lhs, rhs); }
+overflowing_add_u64  :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign { @(link_name="llvm.uadd.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  --- }; return op(lhs, rhs); }
+overflowing_add_i64  :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign { @(link_name="llvm.sadd.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  --- }; return op(lhs, rhs); }
 overflowing_add_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
 		x, ok := overflowing_add_u32(u32(lhs), u32(rhs));
@@ -157,14 +157,14 @@ overflowing_add :: proc[
 	overflowing_add_uint, overflowing_add_int,
 ];
 
-overflowing_sub_u8   :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
-overflowing_sub_i8   :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
-overflowing_sub_u16  :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
-overflowing_sub_i16  :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
-overflowing_sub_u32  :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
-overflowing_sub_i32  :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
-overflowing_sub_u64  :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
-overflowing_sub_i64  :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
+overflowing_sub_u8   :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign { @(link_name="llvm.usub.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   --- }; return op(lhs, rhs); }
+overflowing_sub_i8   :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign { @(link_name="llvm.ssub.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   --- }; return op(lhs, rhs); }
+overflowing_sub_u16  :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign { @(link_name="llvm.usub.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  --- }; return op(lhs, rhs); }
+overflowing_sub_i16  :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign { @(link_name="llvm.ssub.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  --- }; return op(lhs, rhs); }
+overflowing_sub_u32  :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign { @(link_name="llvm.usub.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  --- }; return op(lhs, rhs); }
+overflowing_sub_i32  :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign { @(link_name="llvm.ssub.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  --- }; return op(lhs, rhs); }
+overflowing_sub_u64  :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign { @(link_name="llvm.usub.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  --- }; return op(lhs, rhs); }
+overflowing_sub_i64  :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign { @(link_name="llvm.ssub.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  --- }; return op(lhs, rhs); }
 overflowing_sub_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
 		x, ok := overflowing_sub_u32(u32(lhs), u32(rhs));
@@ -193,14 +193,14 @@ overflowing_sub :: proc[
 ];
 
 
-overflowing_mul_u8   :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
-overflowing_mul_i8   :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
-overflowing_mul_u16  :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
-overflowing_mul_i16  :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
-overflowing_mul_u32  :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
-overflowing_mul_i32  :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
-overflowing_mul_u64  :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
-overflowing_mul_i64  :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
+overflowing_mul_u8   :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign { @(link_name="llvm.umul.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   --- }; return op(lhs, rhs); }
+overflowing_mul_i8   :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign { @(link_name="llvm.smul.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   --- }; return op(lhs, rhs); }
+overflowing_mul_u16  :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign { @(link_name="llvm.umul.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  --- }; return op(lhs, rhs); }
+overflowing_mul_i16  :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign { @(link_name="llvm.smul.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  --- }; return op(lhs, rhs); }
+overflowing_mul_u32  :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign { @(link_name="llvm.umul.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  --- }; return op(lhs, rhs); }
+overflowing_mul_i32  :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign { @(link_name="llvm.smul.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  --- }; return op(lhs, rhs); }
+overflowing_mul_u64  :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign { @(link_name="llvm.umul.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  --- }; return op(lhs, rhs); }
+overflowing_mul_i64  :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign { @(link_name="llvm.smul.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  --- }; return op(lhs, rhs); }
 overflowing_mul_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
 		x, ok := overflowing_mul_u32(u32(lhs), u32(rhs));

+ 1 - 1
core/math/math.odin

@@ -31,7 +31,7 @@ QUAT_IDENTITY := Quat{x = 0, y = 0, z = 0, w = 1};
 
 
 @(default_calling_convention="c")
-foreign __llvm_core {
+foreign _ {
 	@(link_name="llvm.sqrt.f32")
 	sqrt_f32 :: proc(x: f32) -> f32 ---;
 	@(link_name="llvm.sqrt.f64")

+ 4 - 4
core/mem/mem.odin

@@ -2,7 +2,7 @@ package mem
 
 import "core:raw"
 
-foreign __llvm_core {
+foreign _ {
 	@(link_name = "llvm.bswap.i16") swap16 :: proc(b: u16) -> u16 ---;
 	@(link_name = "llvm.bswap.i32") swap32 :: proc(b: u32) -> u32 ---;
 	@(link_name = "llvm.bswap.i64") swap64 :: proc(b: u64) -> u64 ---;
@@ -12,7 +12,7 @@ swap :: proc[swap16, swap32, swap64];
 
 set :: proc "contextless" (data: rawptr, value: i32, len: int) -> rawptr {
 	if data == nil do return nil;
-	foreign __llvm_core {
+	foreign _ {
 		when size_of(rawptr) == 8 {
 			@(link_name="llvm.memset.p0i8.i64")
 			llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---;
@@ -30,7 +30,7 @@ zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
 copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
 	if src == nil do return dst;
 	// NOTE(bill): This _must_ be implemented like C's memmove
-	foreign __llvm_core {
+	foreign _ {
 		when size_of(rawptr) == 8 {
 			@(link_name="llvm.memmove.p0i8.p0i8.i64")
 			llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
@@ -45,7 +45,7 @@ copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
 copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
 	if src == nil do return dst;
 	// NOTE(bill): This _must_ be implemented like C's memcpy
-	foreign __llvm_core {
+	foreign _ {
 		when size_of(rawptr) == 8 {
 			@(link_name="llvm.memcpy.p0i8.p0i8.i64")
 	 		llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;

+ 1 - 1
core/runtime/core.odin

@@ -270,7 +270,7 @@ typeid_base_without_enum :: proc "contextless" (id: typeid) -> typeid {
 
 
 @(default_calling_convention = "c")
-foreign __llvm_core {
+foreign {
 	@(link_name="llvm.assume")
 	assume :: proc(cond: bool) ---;
 

+ 23 - 23
core/runtime/internal.odin

@@ -321,56 +321,56 @@ __slice_expr_error_loc :: inline proc "contextless" (using loc := #caller_locati
 
 
 @(default_calling_convention = "c")
-foreign __llvm_core {
-	@(link_name="llvm.sqrt.f32") __sqrt_f32 :: proc(x: f32) -> f32 ---;
-	@(link_name="llvm.sqrt.f64") __sqrt_f64 :: proc(x: f64) -> f64 ---;
+foreign {
+	@(link_name="llvm.sqrt.f32") __sqrt_f32 :: proc(x: f32) -> f32 ---
+	@(link_name="llvm.sqrt.f64") __sqrt_f64 :: proc(x: f64) -> f64 ---
 
-	@(link_name="llvm.sin.f32") __sin_f32  :: proc(θ: f32) -> f32 ---;
-	@(link_name="llvm.sin.f64") __sin_f64  :: proc(θ: f64) -> f64 ---;
+	@(link_name="llvm.sin.f32") __sin_f32  :: proc(θ: f32) -> f32 ---
+	@(link_name="llvm.sin.f64") __sin_f64  :: proc(θ: f64) -> f64 ---
 
-	@(link_name="llvm.cos.f32") __cos_f32  :: proc(θ: f32) -> f32 ---;
-	@(link_name="llvm.cos.f64") __cos_f64  :: proc(θ: f64) -> f64 ---;
+	@(link_name="llvm.cos.f32") __cos_f32  :: proc(θ: f32) -> f32 ---
+	@(link_name="llvm.cos.f64") __cos_f64  :: proc(θ: f64) -> f64 ---
 
-	@(link_name="llvm.pow.f32") __pow_f32  :: proc(x, power: f32) -> f32 ---;
-	@(link_name="llvm.pow.f64") __pow_f64  :: proc(x, power: f64) -> f64 ---;
+	@(link_name="llvm.pow.f32") __pow_f32  :: proc(x, power: f32) -> f32 ---
+	@(link_name="llvm.pow.f64") __pow_f64  :: proc(x, power: f64) -> f64 ---
 
-	@(link_name="llvm.fmuladd.f32") fmuladd32  :: proc(a, b, c: f32) -> f32 ---;
-	@(link_name="llvm.fmuladd.f64") fmuladd64  :: proc(a, b, c: f64) -> f64 ---;
+	@(link_name="llvm.fmuladd.f32") fmuladd32  :: proc(a, b, c: f32) -> f32 ---
+	@(link_name="llvm.fmuladd.f64") fmuladd64  :: proc(a, b, c: f64) -> f64 ---
 }
 __abs_f32 :: inline proc "contextless" (x: f32) -> f32 {
-	foreign __llvm_core {
-		@(link_name="llvm.fabs.f32") _abs :: proc "c" (x: f32) -> f32 ---;
+	foreign {
+		@(link_name="llvm.fabs.f32") _abs :: proc "c" (x: f32) -> f32 ---
 	}
 	return _abs(x);
 }
 __abs_f64 :: inline proc "contextless" (x: f64) -> f64 {
-	foreign __llvm_core {
-		@(link_name="llvm.fabs.f64") _abs :: proc "c" (x: f64) -> f64 ---;
+	foreign {
+		@(link_name="llvm.fabs.f64") _abs :: proc "c" (x: f64) -> f64 ---
 	}
 	return _abs(x);
 }
 
 __min_f32 :: proc(a, b: f32) -> f32 {
-	foreign __llvm_core {
-		@(link_name="llvm.minnum.f32") _min :: proc "c" (a, b: f32) -> f32 ---;
+	foreign {
+		@(link_name="llvm.minnum.f32") _min :: proc "c" (a, b: f32) -> f32 ---
 	}
 	return _min(a, b);
 }
 __min_f64 :: proc(a, b: f64) -> f64 {
-	foreign __llvm_core {
-		@(link_name="llvm.minnum.f64") _min :: proc "c" (a, b: f64) -> f64 ---;
+	foreign {
+		@(link_name="llvm.minnum.f64") _min :: proc "c" (a, b: f64) -> f64 ---
 	}
 	return _min(a, b);
 }
 __max_f32 :: proc(a, b: f32) -> f32 {
-	foreign __llvm_core {
-		@(link_name="llvm.maxnum.f32") _max :: proc "c" (a, b: f32) -> f32 ---;
+	foreign {
+		@(link_name="llvm.maxnum.f32") _max :: proc "c" (a, b: f32) -> f32 ---
 	}
 	return _max(a, b);
 }
 __max_f64 :: proc(a, b: f64) -> f64 {
-	foreign __llvm_core {
-		@(link_name="llvm.maxnum.f64") _max :: proc "c" (a, b: f64) -> f64 ---;
+	foreign {
+		@(link_name="llvm.maxnum.f64") _max :: proc "c" (a, b: f64) -> f64 ---
 	}
 	return _max(a, b);
 }

+ 4 - 1
examples/demo/demo.odin

@@ -739,7 +739,7 @@ deprecated_attribute :: proc() {
 }
 
 main :: proc() {
-	when true {
+	when false {
 		general_stuff();
 		union_type();
 		parametric_polymorphism();
@@ -753,5 +753,8 @@ main :: proc() {
 		cstring_example();
 		deprecated_attribute();
 	}
+
+	x := f32(-123);
+	fmt.println(abs(x));
 }
 

+ 1 - 1
src/check_decl.cpp

@@ -459,7 +459,7 @@ void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
 		Entity *found = scope_lookup_entity(ctx->scope, name);
 		if (found == nullptr) {
 			if (is_blank_ident(name)) {
-				error(ident, "'_' cannot be used as a value type");
+				// NOTE(bill): link against nothing
 			} else {
 				error(ident, "Undeclared name: %.*s", LIT(name));
 			}

+ 3 - 6
src/checker.cpp

@@ -575,14 +575,11 @@ void init_universal_scope(void) {
 	add_global_constant(str_lit("false"), t_untyped_bool, exact_value_bool(false));
 
 	add_global_entity(alloc_entity_nil(str_lit("nil"), t_untyped_nil));
-	add_global_entity(alloc_entity_library_name(universal_scope,
-	                                            make_token_ident(str_lit("__llvm_core")), t_invalid,
-	                                            str_lit(""), str_lit("__llvm_core")));
+	// add_global_entity(alloc_entity_library_name(universal_scope,
+	//                                             make_token_ident(str_lit("__llvm_core")), t_invalid,
+	//                                             str_lit(""), str_lit("__llvm_core")));
 
 	// TODO(bill): Set through flags in the compiler
-	// add_global_string_constant(str_lit("ODIN_OS"),      bc->ODIN_OS);
-	// add_global_string_constant(str_lit("ODIN_ARCH"),    bc->ODIN_ARCH);
-	// add_global_string_constant(str_lit("ODIN_ENDIAN"),  bc->ODIN_ENDIAN);
 	add_global_string_constant(str_lit("ODIN_VENDOR"),  bc->ODIN_VENDOR);
 	add_global_string_constant(str_lit("ODIN_VERSION"), bc->ODIN_VERSION);
 	add_global_string_constant(str_lit("ODIN_ROOT"),    bc->ODIN_ROOT);

+ 3 - 1
src/ir.cpp

@@ -1327,7 +1327,9 @@ irValue *ir_add_global_string_array(irModule *m, String string) {
 }
 
 void ir_add_foreign_library_path(irModule *m, Entity *e) {
-	GB_ASSERT(e != nullptr);
+	if (e == nullptr) {
+		return;
+	}
 	GB_ASSERT(e->kind == Entity_LibraryName);
 	GB_ASSERT(e->LibraryName.used);
 

+ 10 - 10
src/parser.cpp

@@ -1318,7 +1318,7 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
 	case AstNode_BitFieldType:
 		return true;
 	case AstNode_ProcLit:
-		return s->ProcLit.body != nullptr;
+		return true;
 
 	case AstNode_PackageDecl:
 	case AstNode_ImportDecl:
@@ -2410,6 +2410,8 @@ AstNode *parse_foreign_block(AstFile *f, Token token) {
 	AstNode *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) {
+		foreign_library = ast_ident(f, blank_token);
 	} else {
 		foreign_library = parse_ident(f);
 	}
@@ -2421,19 +2423,16 @@ AstNode *parse_foreign_block(AstFile *f, Token token) {
 	defer (f->in_foreign_block = prev_in_foreign_block);
 	f->in_foreign_block = true;
 
-	if (f->curr_token.kind != Token_OpenBrace) {
-		parse_foreign_block_decl(f, &decls);
-	} else {
-		open = expect_token(f, Token_OpenBrace);
 
-		while (f->curr_token.kind != Token_CloseBrace &&
-		       f->curr_token.kind != Token_EOF) {
-			parse_foreign_block_decl(f, &decls);
-		}
+	open = expect_token(f, Token_OpenBrace);
 
-		close = expect_token(f, Token_CloseBrace);
+	while (f->curr_token.kind != Token_CloseBrace &&
+	       f->curr_token.kind != Token_EOF) {
+		parse_foreign_block_decl(f, &decls);
 	}
 
+	close = expect_token(f, Token_CloseBrace);
+
 	AstNode *decl = ast_foreign_block_decl(f, token, foreign_library, open, close, decls, docs);
 	expect_semicolon(f, decl);
 	return decl;
@@ -3512,6 +3511,7 @@ AstNode *parse_foreign_decl(AstFile *f) {
 	switch (f->curr_token.kind) {
 	case Token_export:
 	case Token_Ident:
+	case Token_OpenBrace:
 		return parse_foreign_block(f, token);
 
 	case Token_import: {