| ... | ... | @@ -290,6 +290,8 @@ pub const Fn = struct { |
| 290 | 290 | }, |
| 291 | 291 | owner_decl: *Decl, |
| 292 | 292 | |
| 293 | is_pub: bool, |
| 294 | |
| 293 | 295 | /// This memory is temporary and points to stack memory for the duration |
| 294 | 296 | /// of Fn analysis. |
| 295 | 297 | pub const Analysis = struct { |
| ... | ... | @@ -323,7 +325,11 @@ pub const Fn = struct { |
| 323 | 325 | pub const Var = struct { |
| 324 | 326 | value: ?Value, |
| 325 | 327 | owner_decl: *Decl, |
| 328 | |
| 329 | is_pub: bool, |
| 330 | is_extern: bool, |
| 326 | 331 | is_mutable: bool, |
| 332 | is_threadlocal: bool, |
| 327 | 333 | }; |
| 328 | 334 | |
| 329 | 335 | pub const Scope = struct { |
| ... | ... | @@ -1241,6 +1247,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1241 | 1247 | }; |
| 1242 | 1248 | defer fn_type_scope.instructions.deinit(self.gpa); |
| 1243 | 1249 | |
| 1250 | const is_pub = fn_proto.getTrailer("visib_token") != null; |
| 1244 | 1251 | const body_node = fn_proto.getTrailer("body_node") orelse |
| 1245 | 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 | 1385 | new_func.* = .{ |
| 1379 | 1386 | .analysis = .{ .queued = fn_zir }, |
| 1380 | 1387 | .owner_decl = decl, |
| 1388 | .is_pub = is_pub, |
| 1381 | 1389 | }; |
| 1382 | 1390 | fn_payload.* = .{ .func = new_func }; |
| 1383 | 1391 | |
| ... | ... | @@ -1430,13 +1438,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1430 | 1438 | |
| 1431 | 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 | 1441 | // We need the memory for the Type to go into the arena for the Decl |
| 1441 | 1442 | var decl_arena = std.heap.ArenaAllocator.init(self.gpa); |
| 1442 | 1443 | errdefer decl_arena.deinit(); |
| ... | ... | @@ -1451,6 +1452,32 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1451 | 1452 | }; |
| 1452 | 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 | 1481 | const explicit_type = blk: { |
| 1455 | 1482 | const type_node = var_decl.getTrailer("type_node") orelse |
| 1456 | 1483 | break :blk null; |
| ... | ... | @@ -1543,7 +1570,10 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1543 | 1570 | new_variable.* = .{ |
| 1544 | 1571 | .value = value, |
| 1545 | 1572 | .owner_decl = decl, |
| 1573 | .is_pub = is_pub, |
| 1574 | .is_extern = is_extern, |
| 1546 | 1575 | .is_mutable = is_mutable, |
| 1576 | .is_threadlocal = is_threadlocal, |
| 1547 | 1577 | }; |
| 1548 | 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 | 2424 | |
| 2395 | 2425 | const decl_tv = try decl.typedValue(); |
| 2396 | 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 | 2429 | const ty = try self.singlePtrType(scope, src, false, decl_tv.ty); |
| 2400 | 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 | 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 | 2440 | const variable = tv.val.cast(Value.Payload.Variable).?.variable; |
| 2411 | 2441 | |
| 2412 | 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 | 2444 | const val_payload = try scope.arena().create(Value.Payload.RefVal); |
| 2415 | 2445 | val_payload.* = .{ .val = variable.value.? }; |
| 2416 | 2446 | return self.constInst(scope, src, .{ |