| ... | @@ -290,6 +290,8 @@ pub const Fn = struct { | ... | @@ -290,6 +290,8 @@ pub const Fn = struct { |
| 290 | }, | 290 | }, |
| 291 | owner_decl: *Decl, | 291 | owner_decl: *Decl, |
| 292 | | 292 | |
| | 293 | is_pub: bool, |
| | 294 | |
| 293 | /// This memory is temporary and points to stack memory for the duration | 295 | /// This memory is temporary and points to stack memory for the duration |
| 294 | /// of Fn analysis. | 296 | /// of Fn analysis. |
| 295 | pub const Analysis = struct { | 297 | pub const Analysis = struct { |
| ... | @@ -323,7 +325,11 @@ pub const Fn = struct { | ... | @@ -323,7 +325,11 @@ pub const Fn = struct { |
| 323 | pub const Var = struct { | 325 | pub const Var = struct { |
| 324 | value: ?Value, | 326 | value: ?Value, |
| 325 | owner_decl: *Decl, | 327 | owner_decl: *Decl, |
| | 328 | |
| | 329 | is_pub: bool, |
| | 330 | is_extern: bool, |
| 326 | is_mutable: bool, | 331 | is_mutable: bool, |
| | 332 | is_threadlocal: bool, |
| 327 | }; | 333 | }; |
| 328 | | 334 | |
| 329 | pub const Scope = struct { | 335 | pub const Scope = struct { |
| ... | @@ -1241,6 +1247,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1241,6 +1247,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1241 | }; | 1247 | }; |
| 1242 | defer fn_type_scope.instructions.deinit(self.gpa); | 1248 | defer fn_type_scope.instructions.deinit(self.gpa); |
| 1243 | | 1249 | |
| | 1250 | const is_pub = fn_proto.getTrailer("visib_token") != null; |
| 1244 | const body_node = fn_proto.getTrailer("body_node") orelse | 1251 | const body_node = fn_proto.getTrailer("body_node") orelse |
| 1245 | return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{}); | 1252 | return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{}); |
| 1246 | | 1253 | |
| ... | @@ -1378,6 +1385,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1378,6 +1385,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1378 | new_func.* = .{ | 1385 | new_func.* = .{ |
| 1379 | .analysis = .{ .queued = fn_zir }, | 1386 | .analysis = .{ .queued = fn_zir }, |
| 1380 | .owner_decl = decl, | 1387 | .owner_decl = decl, |
| | 1388 | .is_pub = is_pub, |
| 1381 | }; | 1389 | }; |
| 1382 | fn_payload.* = .{ .func = new_func }; | 1390 | fn_payload.* = .{ .func = new_func }; |
| 1383 | | 1391 | |
| ... | @@ -1430,13 +1438,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1430,13 +1438,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1430 | | 1438 | |
| 1431 | decl.analysis = .in_progress; | 1439 | decl.analysis = .in_progress; |
| 1432 | | 1440 | |
| 1433 | const is_extern = blk: { | | |
| 1434 | const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse | | |
| 1435 | break :blk false; | | |
| 1436 | break :blk tree.token_ids[maybe_extern_token] == .Keyword_extern; | | |
| 1437 | }; | | |
| 1438 | const is_mutable = tree.token_ids[var_decl.mut_token] == .Keyword_var; | | |
| 1439 | | | |
| 1440 | // We need the memory for the Type to go into the arena for the Decl | 1441 | // We need the memory for the Type to go into the arena for the Decl |
| 1441 | var decl_arena = std.heap.ArenaAllocator.init(self.gpa); | 1442 | var decl_arena = std.heap.ArenaAllocator.init(self.gpa); |
| 1442 | errdefer decl_arena.deinit(); | 1443 | errdefer decl_arena.deinit(); |
| ... | @@ -1451,6 +1452,32 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1451,6 +1452,32 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1451 | }; | 1452 | }; |
| 1452 | defer block_scope.instructions.deinit(self.gpa); | 1453 | defer block_scope.instructions.deinit(self.gpa); |
| 1453 | | 1454 | |
| | 1455 | const is_pub = var_decl.getTrailer("visib_token") != null; |
| | 1456 | const is_extern = blk: { |
| | 1457 | const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse |
| | 1458 | break :blk false; |
| | 1459 | break :blk tree.token_ids[maybe_extern_token] == .Keyword_extern; |
| | 1460 | }; |
| | 1461 | if (var_decl.getTrailer("lib_name")) |lib_name| { |
| | 1462 | assert(is_extern); |
| | 1463 | return self.failNode(&block_scope.base, lib_name, "TODO implement function library name", .{}); |
| | 1464 | } |
| | 1465 | const is_mutable = tree.token_ids[var_decl.mut_token] == .Keyword_var; |
| | 1466 | const is_threadlocal = if (var_decl.getTrailer("thread_local_token")) |some| blk: { |
| | 1467 | if (!is_mutable) { |
| | 1468 | return self.failTok(&block_scope.base, some, "threadlocal variable cannot be constant", .{}); |
| | 1469 | } |
| | 1470 | break :blk true; |
| | 1471 | } else false; |
| | 1472 | assert(var_decl.getTrailer("comptime_token") == null); |
| | 1473 | if (var_decl.getTrailer("align_node")) |align_expr| { |
| | 1474 | return self.failNode(&block_scope.base, align_expr, "TODO implement function align expression", .{}); |
| | 1475 | } |
| | 1476 | if (var_decl.getTrailer("section_node")) |sect_expr| { |
| | 1477 | return self.failNode(&block_scope.base, sect_expr, "TODO implement function section expression", .{}); |
| | 1478 | } |
| | 1479 | |
| | 1480 | |
| 1454 | const explicit_type = blk: { | 1481 | const explicit_type = blk: { |
| 1455 | const type_node = var_decl.getTrailer("type_node") orelse | 1482 | const type_node = var_decl.getTrailer("type_node") orelse |
| 1456 | break :blk null; | 1483 | break :blk null; |
| ... | @@ -1543,7 +1570,10 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1543,7 +1570,10 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1543 | new_variable.* = .{ | 1570 | new_variable.* = .{ |
| 1544 | .value = value, | 1571 | .value = value, |
| 1545 | .owner_decl = decl, | 1572 | .owner_decl = decl, |
| | 1573 | .is_pub = is_pub, |
| | 1574 | .is_extern = is_extern, |
| 1546 | .is_mutable = is_mutable, | 1575 | .is_mutable = is_mutable, |
| | 1576 | .is_threadlocal = is_threadlocal, |
| 1547 | }; | 1577 | }; |
| 1548 | var_payload.* = .{ .variable = new_variable }; | 1578 | var_payload.* = .{ .variable = new_variable }; |
| 1549 | | 1579 | |
| ... | @@ -2394,7 +2424,7 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn | ... | @@ -2394,7 +2424,7 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn |
| 2394 | | 2424 | |
| 2395 | const decl_tv = try decl.typedValue(); | 2425 | const decl_tv = try decl.typedValue(); |
| 2396 | if (decl_tv.val.tag() == .variable) { | 2426 | if (decl_tv.val.tag() == .variable) { |
| 2397 | return self.getVarRef(scope, src, decl_tv); | 2427 | return self.analyzeVarRef(scope, src, decl_tv); |
| 2398 | } | 2428 | } |
| 2399 | const ty = try self.singlePtrType(scope, src, false, decl_tv.ty); | 2429 | const ty = try self.singlePtrType(scope, src, false, decl_tv.ty); |
| 2400 | const val_payload = try scope.arena().create(Value.Payload.DeclRef); | 2430 | const val_payload = try scope.arena().create(Value.Payload.DeclRef); |
| ... | @@ -2406,11 +2436,11 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn | ... | @@ -2406,11 +2436,11 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn |
| 2406 | }); | 2436 | }); |
| 2407 | } | 2437 | } |
| 2408 | | 2438 | |
| 2409 | fn getVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst { | 2439 | fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst { |
| 2410 | const variable = tv.val.cast(Value.Payload.Variable).?.variable; | 2440 | const variable = tv.val.cast(Value.Payload.Variable).?.variable; |
| 2411 | | 2441 | |
| 2412 | const ty = try self.singlePtrType(scope, src, variable.is_mutable, tv.ty); | 2442 | const ty = try self.singlePtrType(scope, src, variable.is_mutable, tv.ty); |
| 2413 | if (!variable.is_mutable and variable.value != null) { | 2443 | if (!variable.is_mutable and !variable.is_extern and variable.value != null) { |
| 2414 | const val_payload = try scope.arena().create(Value.Payload.RefVal); | 2444 | const val_payload = try scope.arena().create(Value.Payload.RefVal); |
| 2415 | val_payload.* = .{ .val = variable.value.? }; | 2445 | val_payload.* = .{ .val = variable.value.? }; |
| 2416 | return self.constInst(scope, src, .{ | 2446 | return self.constInst(scope, src, .{ |