| ... | @@ -3,6 +3,7 @@ tree: aro.Tree, | ... | @@ -3,6 +3,7 @@ tree: aro.Tree, |
| 3 | bin_file: *link.File, | 3 | bin_file: *link.File, |
| 4 | arena: Allocator, | 4 | arena: Allocator, |
| 5 | gpa: Allocator, | 5 | gpa: Allocator, |
| | 6 | symbols: std.StringHashMapUnmanaged(*Module.Decl), |
| 6 | verbose_air: bool, | 7 | verbose_air: bool, |
| 7 | | 8 | |
| 8 | const builtin = @import("builtin"); | 9 | const builtin = @import("builtin"); |
| ... | @@ -30,12 +31,16 @@ pub fn generateTree(comp: *Compilation, aro_comp: *aro.Compilation, tree: aro.Tr | ... | @@ -30,12 +31,16 @@ pub fn generateTree(comp: *Compilation, aro_comp: *aro.Compilation, tree: aro.Tr |
| 30 | .arena = arena, | 31 | .arena = arena, |
| 31 | .gpa = comp.gpa, | 32 | .gpa = comp.gpa, |
| 32 | .verbose_air = comp.verbose_air, | 33 | .verbose_air = comp.verbose_air, |
| | 34 | .symbols = .{}, |
| 33 | }; | 35 | }; |
| | 36 | defer c.symbols.deinit(comp.gpa); |
| 34 | | 37 | |
| 35 | const node_tags = tree.nodes.items(.tag); | 38 | const node_tags = tree.nodes.items(.tag); |
| 36 | const node_datas = tree.nodes.items(.data); | 39 | const node_datas = tree.nodes.items(.data); |
| 37 | for (tree.root_decls) |decl| { | 40 | const node_tys = tree.nodes.items(.ty); |
| 38 | switch (node_tags[@enumToInt(decl)]) { | 41 | |
| | 42 | for (tree.root_decls) |decl_node| { |
| | 43 | switch (node_tags[@enumToInt(decl_node)]) { |
| 39 | // these produce no code | 44 | // these produce no code |
| 40 | .static_assert, | 45 | .static_assert, |
| 41 | .typedef, | 46 | .typedef, |
| ... | @@ -45,19 +50,30 @@ pub fn generateTree(comp: *Compilation, aro_comp: *aro.Compilation, tree: aro.Tr | ... | @@ -45,19 +50,30 @@ pub fn generateTree(comp: *Compilation, aro_comp: *aro.Compilation, tree: aro.Tr |
| 45 | .struct_decl, | 50 | .struct_decl, |
| 46 | .union_decl, | 51 | .union_decl, |
| 47 | .enum_decl, | 52 | .enum_decl, |
| 48 | => {}, | 53 | => continue, |
| | 54 | |
| | 55 | // symbol definitions |
| | 56 | .fn_proto => { |
| | 57 | const mod = comp.bin_file.options.module.?; |
| | 58 | const name = c.tree.tokSlice(node_datas[@enumToInt(decl_node)].decl.name); |
| | 59 | const fn_proto_ty = node_tys[@enumToInt(decl_node)]; |
| | 60 | const zig_fn_ty = try c.lowerType(fn_proto_ty); |
| | 61 | const new_decl = try mod.createAnonymousDecl2(.{ |
| | 62 | .ty = zig_fn_ty, |
| | 63 | .val = undefined, |
| | 64 | }, name); |
| | 65 | new_decl.val = try Value.Tag.extern_fn.create(c.arena, new_decl); |
| | 66 | try c.symbols.put(c.gpa, name, new_decl); |
| | 67 | }, |
| 49 | | 68 | |
| 50 | // define symbol | | |
| 51 | .fn_proto, | | |
| 52 | .static_fn_proto, | 69 | .static_fn_proto, |
| 53 | .inline_fn_proto, | 70 | .inline_fn_proto, |
| 54 | .inline_static_fn_proto, | 71 | .inline_static_fn_proto, |
| 55 | .extern_var, | 72 | .extern_var, |
| 56 | .threadlocal_extern_var, | 73 | .threadlocal_extern_var, |
| 57 | => { | 74 | => { |
| 58 | const name = c.tree.tokSlice(node_datas[@enumToInt(decl)].decl.name); | 75 | const name = c.tree.tokSlice(node_datas[@enumToInt(decl_node)].decl.name); |
| 59 | log.debug("ignoring the opportunity to define a symbol named {s}", .{name}); | 76 | log.debug("ignoring the opportunity to define a symbol named {s}", .{name}); |
| 60 | //_ = try c.obj.declareSymbol(.@"undefined", name, .Strong, .external, 0, 0); | | |
| 61 | }, | 77 | }, |
| 62 | | 78 | |
| 63 | // function definition | 79 | // function definition |
| ... | @@ -65,13 +81,13 @@ pub fn generateTree(comp: *Compilation, aro_comp: *aro.Compilation, tree: aro.Tr | ... | @@ -65,13 +81,13 @@ pub fn generateTree(comp: *Compilation, aro_comp: *aro.Compilation, tree: aro.Tr |
| 65 | .static_fn_def, | 81 | .static_fn_def, |
| 66 | .inline_fn_def, | 82 | .inline_fn_def, |
| 67 | .inline_static_fn_def, | 83 | .inline_static_fn_def, |
| 68 | => try c.genFn(decl), | 84 | => try c.genFn(decl_node), |
| 69 | | 85 | |
| 70 | .@"var", | 86 | .@"var", |
| 71 | .static_var, | 87 | .static_var, |
| 72 | .threadlocal_var, | 88 | .threadlocal_var, |
| 73 | .threadlocal_static_var, | 89 | .threadlocal_static_var, |
| 74 | => try c.genVar(decl), | 90 | => try c.genVar(decl_node), |
| 75 | | 91 | |
| 76 | else => unreachable, | 92 | else => unreachable, |
| 77 | } | 93 | } |
| ... | @@ -213,6 +229,17 @@ const Func = struct { | ... | @@ -213,6 +229,17 @@ const Func = struct { |
| 213 | const coerced = @bitCast([]const u32, refs); | 229 | const coerced = @bitCast([]const u32, refs); |
| 214 | func.air_extra.appendSliceAssumeCapacity(coerced); | 230 | func.air_extra.appendSliceAssumeCapacity(coerced); |
| 215 | } | 231 | } |
| | 232 | |
| | 233 | fn declRef(func: *Func, decl: *Module.Decl) !Air.Inst.Ref { |
| | 234 | return func.addConstant( |
| | 235 | try Type.ptr(func.codegen.arena, .{ |
| | 236 | .pointee_type = decl.ty, |
| | 237 | .mutable = false, |
| | 238 | .@"addrspace" = decl.@"addrspace", |
| | 239 | }), |
| | 240 | try Value.Tag.decl_ref.create(func.codegen.arena, decl), |
| | 241 | ); |
| | 242 | } |
| 216 | }; | 243 | }; |
| 217 | | 244 | |
| 218 | fn genFn(c: *Codegen, decl_node: NodeIndex) !void { | 245 | fn genFn(c: *Codegen, decl_node: NodeIndex) !void { |
| ... | @@ -282,7 +309,6 @@ fn genFn(c: *Codegen, decl_node: NodeIndex) !void { | ... | @@ -282,7 +309,6 @@ fn genFn(c: *Codegen, decl_node: NodeIndex) !void { |
| 282 | } | 309 | } |
| 283 | | 310 | |
| 284 | fn lowerType(c: *Codegen, aro_ty: aro.Type) Allocator.Error!Type { | 311 | fn lowerType(c: *Codegen, aro_ty: aro.Type) Allocator.Error!Type { |
| 285 | _ = c; | | |
| 286 | switch (aro_ty.specifier) { | 312 | switch (aro_ty.specifier) { |
| 287 | .void => return Type.void, | 313 | .void => return Type.void, |
| 288 | .bool => return Type.bool, | 314 | .bool => return Type.bool, |
| ... | @@ -301,19 +327,47 @@ fn lowerType(c: *Codegen, aro_ty: aro.Type) Allocator.Error!Type { | ... | @@ -301,19 +327,47 @@ fn lowerType(c: *Codegen, aro_ty: aro.Type) Allocator.Error!Type { |
| 301 | .double => return Type.initTag(.f64), | 327 | .double => return Type.initTag(.f64), |
| 302 | .long_double => return Type.initTag(.c_longdouble), | 328 | .long_double => return Type.initTag(.c_longdouble), |
| 303 | | 329 | |
| | 330 | // int foo(int bar, char baz, ...) |
| | 331 | .var_args_func => { |
| | 332 | const param_types = try c.arena.alloc(Type, aro_ty.data.func.params.len); |
| | 333 | for (param_types) |*ty, i| { |
| | 334 | ty.* = try c.lowerType(aro_ty.data.func.params[i].ty); |
| | 335 | } |
| | 336 | |
| | 337 | const zig_ty = try Type.Tag.function.create(c.arena, .{ |
| | 338 | .param_types = param_types, |
| | 339 | .comptime_params = undefined, |
| | 340 | .return_type = try c.lowerType(aro_ty.data.func.return_type), |
| | 341 | .alignment = 0, |
| | 342 | .cc = .C, |
| | 343 | .is_var_args = true, |
| | 344 | .is_generic = false, |
| | 345 | }); |
| | 346 | return zig_ty; |
| | 347 | }, |
| | 348 | |
| | 349 | .pointer => { |
| | 350 | const zig_ty = try Type.ptr(c.arena, .{ |
| | 351 | .pointee_type = try c.lowerType(aro_ty.data.sub_type.*), |
| | 352 | .@"addrspace" = .generic, |
| | 353 | .mutable = !aro_ty.qual.@"const", |
| | 354 | .@"volatile" = aro_ty.qual.@"volatile", |
| | 355 | .@"allowzero" = true, |
| | 356 | .size = .C, |
| | 357 | }); |
| | 358 | return zig_ty; |
| | 359 | }, |
| | 360 | |
| 304 | .complex_float, | 361 | .complex_float, |
| 305 | .complex_double, | 362 | .complex_double, |
| 306 | .complex_long_double, | 363 | .complex_long_double, |
| 307 | | 364 | |
| 308 | // data.sub_type | 365 | // data.sub_type |
| 309 | .pointer, | | |
| 310 | .unspecified_variable_len_array, | 366 | .unspecified_variable_len_array, |
| 311 | .decayed_unspecified_variable_len_array, | 367 | .decayed_unspecified_variable_len_array, |
| 312 | // data.func | 368 | // data.func |
| 313 | // int foo(int bar, char baz) and int (void) | 369 | // int foo(int bar, char baz) and int (void) |
| 314 | .func, | 370 | .func, |
| 315 | // int foo(int bar, char baz, ...) | | |
| 316 | .var_args_func, | | |
| 317 | // int foo(bar, baz) and int foo() | 371 | // int foo(bar, baz) and int foo() |
| 318 | // is also var args, but we can give warnings about incorrect amounts of parameters | 372 | // is also var args, but we can give warnings about incorrect amounts of parameters |
| 319 | .old_style_func, | 373 | .old_style_func, |
| ... | @@ -360,12 +414,18 @@ fn lowerValue(c: *Codegen, aro_ty: aro.Type, aro_val: aro.Value) Allocator.Error | ... | @@ -360,12 +414,18 @@ fn lowerValue(c: *Codegen, aro_ty: aro.Type, aro_val: aro.Value) Allocator.Error |
| 360 | switch (aro_val.tag) { | 414 | switch (aro_val.tag) { |
| 361 | .unavailable => unreachable, | 415 | .unavailable => unreachable, |
| 362 | .int => { | 416 | .int => { |
| 363 | const is_signed = zig_ty.isSignedInt(); | 417 | if (zig_ty.isSignedInt()) { |
| 364 | if (is_signed) @panic("TODO"); | 418 | const signed_int = aro_val.signExtend(aro_ty, c.aro_comp); |
| 365 | return TypedValue{ | 419 | return TypedValue{ |
| 366 | .ty = zig_ty, | 420 | .ty = zig_ty, |
| 367 | .val = try Value.Tag.int_u64.create(c.arena, aro_val.data.int), | 421 | .val = try Value.Tag.int_i64.create(c.arena, signed_int), |
| 368 | }; | 422 | }; |
| | 423 | } else { |
| | 424 | return TypedValue{ |
| | 425 | .ty = zig_ty, |
| | 426 | .val = try Value.Tag.int_u64.create(c.arena, aro_val.data.int), |
| | 427 | }; |
| | 428 | } |
| 369 | }, | 429 | }, |
| 370 | .float => @panic("TODO"), | 430 | .float => @panic("TODO"), |
| 371 | .array => @panic("TODO"), | 431 | .array => @panic("TODO"), |
| ... | @@ -424,19 +484,13 @@ fn genNode(func: *Func, block: *Block, node: NodeIndex) Error!Air.Inst.Ref { | ... | @@ -424,19 +484,13 @@ fn genNode(func: *Func, block: *Block, node: NodeIndex) Error!Air.Inst.Ref { |
| 424 | try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]), | 484 | try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]), |
| 425 | ); | 485 | ); |
| 426 | | 486 | |
| 427 | return func.addConstant( | 487 | return func.declRef(new_decl); |
| 428 | try Type.ptr(func.codegen.arena, .{ | | |
| 429 | .pointee_type = new_decl.ty, | | |
| 430 | .mutable = false, | | |
| 431 | .@"addrspace" = new_decl.@"addrspace", | | |
| 432 | }), | | |
| 433 | try Value.Tag.decl_ref.create(func.codegen.arena, new_decl), | | |
| 434 | ); | | |
| 435 | }, | 488 | }, |
| 436 | .decl_ref_expr => { | 489 | .decl_ref_expr => { |
| 437 | // TODO locals and arguments | 490 | // TODO locals and arguments |
| 438 | const name = tree.tokSlice(data.decl_ref); | 491 | const name = tree.tokSlice(data.decl_ref); |
| 439 | std.debug.panic("TODO decl_ref_expr {s}", .{name}); | 492 | const decl = func.codegen.symbols.get(name).?; |
| | 493 | return func.declRef(decl); |
| 440 | }, | 494 | }, |
| 441 | .return_stmt => { | 495 | .return_stmt => { |
| 442 | const operand = try genNode(func, block, data.un); | 496 | const operand = try genNode(func, block, data.un); |