| ... | ... | @@ -3,6 +3,7 @@ tree: aro.Tree, |
| 3 | 3 | bin_file: *link.File, |
| 4 | 4 | arena: Allocator, |
| 5 | 5 | gpa: Allocator, |
| 6 | symbols: std.StringHashMapUnmanaged(*Module.Decl), |
| 6 | 7 | verbose_air: bool, |
| 7 | 8 | |
| 8 | 9 | const builtin = @import("builtin"); |
| ... | ... | @@ -30,12 +31,16 @@ pub fn generateTree(comp: *Compilation, aro_comp: *aro.Compilation, tree: aro.Tr |
| 30 | 31 | .arena = arena, |
| 31 | 32 | .gpa = comp.gpa, |
| 32 | 33 | .verbose_air = comp.verbose_air, |
| 34 | .symbols = .{}, |
| 33 | 35 | }; |
| 36 | defer c.symbols.deinit(comp.gpa); |
| 34 | 37 | |
| 35 | 38 | const node_tags = tree.nodes.items(.tag); |
| 36 | 39 | const node_datas = tree.nodes.items(.data); |
| 37 | | for (tree.root_decls) |decl| { |
| 38 | | switch (node_tags[@enumToInt(decl)]) { |
| 40 | const node_tys = tree.nodes.items(.ty); |
| 41 | |
| 42 | for (tree.root_decls) |decl_node| { |
| 43 | switch (node_tags[@enumToInt(decl_node)]) { |
| 39 | 44 | // these produce no code |
| 40 | 45 | .static_assert, |
| 41 | 46 | .typedef, |
| ... | ... | @@ -45,19 +50,30 @@ pub fn generateTree(comp: *Compilation, aro_comp: *aro.Compilation, tree: aro.Tr |
| 45 | 50 | .struct_decl, |
| 46 | 51 | .union_decl, |
| 47 | 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 | 69 | .static_fn_proto, |
| 53 | 70 | .inline_fn_proto, |
| 54 | 71 | .inline_static_fn_proto, |
| 55 | 72 | .extern_var, |
| 56 | 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 | 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 | 79 | // function definition |
| ... | ... | @@ -65,13 +81,13 @@ pub fn generateTree(comp: *Compilation, aro_comp: *aro.Compilation, tree: aro.Tr |
| 65 | 81 | .static_fn_def, |
| 66 | 82 | .inline_fn_def, |
| 67 | 83 | .inline_static_fn_def, |
| 68 | | => try c.genFn(decl), |
| 84 | => try c.genFn(decl_node), |
| 69 | 85 | |
| 70 | 86 | .@"var", |
| 71 | 87 | .static_var, |
| 72 | 88 | .threadlocal_var, |
| 73 | 89 | .threadlocal_static_var, |
| 74 | | => try c.genVar(decl), |
| 90 | => try c.genVar(decl_node), |
| 75 | 91 | |
| 76 | 92 | else => unreachable, |
| 77 | 93 | } |
| ... | ... | @@ -213,6 +229,17 @@ const Func = struct { |
| 213 | 229 | const coerced = @bitCast([]const u32, refs); |
| 214 | 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 | 245 | 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 | 311 | fn lowerType(c: *Codegen, aro_ty: aro.Type) Allocator.Error!Type { |
| 285 | | _ = c; |
| 286 | 312 | switch (aro_ty.specifier) { |
| 287 | 313 | .void => return Type.void, |
| 288 | 314 | .bool => return Type.bool, |
| ... | ... | @@ -301,19 +327,47 @@ fn lowerType(c: *Codegen, aro_ty: aro.Type) Allocator.Error!Type { |
| 301 | 327 | .double => return Type.initTag(.f64), |
| 302 | 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 | 361 | .complex_float, |
| 305 | 362 | .complex_double, |
| 306 | 363 | .complex_long_double, |
| 307 | 364 | |
| 308 | 365 | // data.sub_type |
| 309 | | .pointer, |
| 310 | 366 | .unspecified_variable_len_array, |
| 311 | 367 | .decayed_unspecified_variable_len_array, |
| 312 | 368 | // data.func |
| 313 | 369 | // int foo(int bar, char baz) and int (void) |
| 314 | 370 | .func, |
| 315 | | // int foo(int bar, char baz, ...) |
| 316 | | .var_args_func, |
| 317 | 371 | // int foo(bar, baz) and int foo() |
| 318 | 372 | // is also var args, but we can give warnings about incorrect amounts of parameters |
| 319 | 373 | .old_style_func, |
| ... | ... | @@ -360,12 +414,18 @@ fn lowerValue(c: *Codegen, aro_ty: aro.Type, aro_val: aro.Value) Allocator.Error |
| 360 | 414 | switch (aro_val.tag) { |
| 361 | 415 | .unavailable => unreachable, |
| 362 | 416 | .int => { |
| 363 | | const is_signed = zig_ty.isSignedInt(); |
| 364 | | if (is_signed) @panic("TODO"); |
| 365 | | return TypedValue{ |
| 366 | | .ty = zig_ty, |
| 367 | | .val = try Value.Tag.int_u64.create(c.arena, aro_val.data.int), |
| 368 | | }; |
| 417 | if (zig_ty.isSignedInt()) { |
| 418 | const signed_int = aro_val.signExtend(aro_ty, c.aro_comp); |
| 419 | return TypedValue{ |
| 420 | .ty = zig_ty, |
| 421 | .val = try Value.Tag.int_i64.create(c.arena, signed_int), |
| 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 | 430 | .float => @panic("TODO"), |
| 371 | 431 | .array => @panic("TODO"), |
| ... | ... | @@ -424,19 +484,13 @@ fn genNode(func: *Func, block: *Block, node: NodeIndex) Error!Air.Inst.Ref { |
| 424 | 484 | try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]), |
| 425 | 485 | ); |
| 426 | 486 | |
| 427 | | return func.addConstant( |
| 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 | | ); |
| 487 | return func.declRef(new_decl); |
| 435 | 488 | }, |
| 436 | 489 | .decl_ref_expr => { |
| 437 | 490 | // TODO locals and arguments |
| 438 | 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 | 495 | .return_stmt => { |
| 442 | 496 | const operand = try genNode(func, block, data.un); |