| ... | @@ -6,7 +6,8 @@ const Writer = std.ArrayList(u8).Writer; | ... | @@ -6,7 +6,8 @@ const Writer = std.ArrayList(u8).Writer; |
| 6 | const link = @import("../link.zig"); | 6 | const link = @import("../link.zig"); |
| 7 | const Module = @import("../Module.zig"); | 7 | const Module = @import("../Module.zig"); |
| 8 | const Compilation = @import("../Compilation.zig"); | 8 | const Compilation = @import("../Compilation.zig"); |
| 9 | const Inst = @import("../ir.zig").Inst; | 9 | const ir = @import("../ir.zig"); |
| | 10 | const Inst = ir.Inst; |
| 10 | const Value = @import("../value.zig").Value; | 11 | const Value = @import("../value.zig").Value; |
| 11 | const Type = @import("../type.zig").Type; | 12 | const Type = @import("../type.zig").Type; |
| 12 | const TypedValue = @import("../TypedValue.zig"); | 13 | const TypedValue = @import("../TypedValue.zig"); |
| ... | @@ -324,51 +325,13 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -324,51 +325,13 @@ pub fn genDecl(o: *Object) !void { |
| 324 | try fwd_decl_writer.writeAll(";\n"); | 325 | try fwd_decl_writer.writeAll(";\n"); |
| 325 | | 326 | |
| 326 | const func: *Module.Fn = func_payload.data; | 327 | const func: *Module.Fn = func_payload.data; |
| 327 | const instructions = func.body.instructions; | | |
| 328 | const writer = o.code.writer(); | 328 | const writer = o.code.writer(); |
| 329 | try writer.writeAll("\n"); | 329 | try writer.writeAll("\n"); |
| 330 | try o.dg.renderFunctionSignature(writer, is_global); | 330 | try o.dg.renderFunctionSignature(writer, is_global); |
| 331 | if (instructions.len == 0) { | 331 | |
| 332 | try writer.writeAll(" {}\n"); | 332 | try genBody(o, func.body); |
| 333 | return; | | |
| 334 | } | | |
| 335 | | | |
| 336 | try writer.writeAll(" {"); | | |
| 337 | | 333 | |
| 338 | try writer.writeAll("\n"); | 334 | try writer.writeAll("\n"); |
| 339 | for (instructions) |inst| { | | |
| 340 | const result_value = switch (inst.tag) { | | |
| 341 | .add => try genBinOp(o, inst.castTag(.add).?, " + "), | | |
| 342 | .alloc => try genAlloc(o, inst.castTag(.alloc).?), | | |
| 343 | .arg => genArg(o), | | |
| 344 | .assembly => try genAsm(o, inst.castTag(.assembly).?), | | |
| 345 | .block => try genBlock(o, inst.castTag(.block).?), | | |
| 346 | .bitcast => try genBitcast(o, inst.castTag(.bitcast).?), | | |
| 347 | .breakpoint => try genBreakpoint(o, inst.castTag(.breakpoint).?), | | |
| 348 | .call => try genCall(o, inst.castTag(.call).?), | | |
| 349 | .cmp_eq => try genBinOp(o, inst.castTag(.cmp_eq).?, " == "), | | |
| 350 | .cmp_gt => try genBinOp(o, inst.castTag(.cmp_gt).?, " > "), | | |
| 351 | .cmp_gte => try genBinOp(o, inst.castTag(.cmp_gte).?, " >= "), | | |
| 352 | .cmp_lt => try genBinOp(o, inst.castTag(.cmp_lt).?, " < "), | | |
| 353 | .cmp_lte => try genBinOp(o, inst.castTag(.cmp_lte).?, " <= "), | | |
| 354 | .cmp_neq => try genBinOp(o, inst.castTag(.cmp_neq).?, " != "), | | |
| 355 | .dbg_stmt => try genDbgStmt(o, inst.castTag(.dbg_stmt).?), | | |
| 356 | .intcast => try genIntCast(o, inst.castTag(.intcast).?), | | |
| 357 | .load => try genLoad(o, inst.castTag(.load).?), | | |
| 358 | .ret => try genRet(o, inst.castTag(.ret).?), | | |
| 359 | .retvoid => try genRetVoid(o), | | |
| 360 | .store => try genStore(o, inst.castTag(.store).?), | | |
| 361 | .sub => try genBinOp(o, inst.castTag(.sub).?, " - "), | | |
| 362 | .unreach => try genUnreach(o, inst.castTag(.unreach).?), | | |
| 363 | else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}), | | |
| 364 | }; | | |
| 365 | switch (result_value) { | | |
| 366 | .none => {}, | | |
| 367 | else => try o.value_map.putNoClobber(inst, result_value), | | |
| 368 | } | | |
| 369 | } | | |
| 370 | | | |
| 371 | try writer.writeAll("}\n"); | | |
| 372 | } else if (tv.val.tag() == .extern_fn) { | 335 | } else if (tv.val.tag() == .extern_fn) { |
| 373 | const writer = o.code.writer(); | 336 | const writer = o.code.writer(); |
| 374 | try writer.writeAll("ZIG_EXTERN_C "); | 337 | try writer.writeAll("ZIG_EXTERN_C "); |
| ... | @@ -410,6 +373,52 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { | ... | @@ -410,6 +373,52 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 410 | } | 373 | } |
| 411 | } | 374 | } |
| 412 | | 375 | |
| | 376 | pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!void { |
| | 377 | const writer = o.code.writer(); |
| | 378 | if (body.instructions.len == 0) { |
| | 379 | try writer.writeAll(" {}"); |
| | 380 | return; |
| | 381 | } |
| | 382 | |
| | 383 | try writer.writeAll(" {"); |
| | 384 | |
| | 385 | try writer.writeAll("\n"); |
| | 386 | for (body.instructions) |inst| { |
| | 387 | const result_value = switch (inst.tag) { |
| | 388 | .add => try genBinOp(o, inst.castTag(.add).?, " + "), |
| | 389 | .alloc => try genAlloc(o, inst.castTag(.alloc).?), |
| | 390 | .arg => genArg(o), |
| | 391 | .assembly => try genAsm(o, inst.castTag(.assembly).?), |
| | 392 | .block => try genBlock(o, inst.castTag(.block).?), |
| | 393 | .bitcast => try genBitcast(o, inst.castTag(.bitcast).?), |
| | 394 | .breakpoint => try genBreakpoint(o, inst.castTag(.breakpoint).?), |
| | 395 | .call => try genCall(o, inst.castTag(.call).?), |
| | 396 | .cmp_eq => try genBinOp(o, inst.castTag(.cmp_eq).?, " == "), |
| | 397 | .cmp_gt => try genBinOp(o, inst.castTag(.cmp_gt).?, " > "), |
| | 398 | .cmp_gte => try genBinOp(o, inst.castTag(.cmp_gte).?, " >= "), |
| | 399 | .cmp_lt => try genBinOp(o, inst.castTag(.cmp_lt).?, " < "), |
| | 400 | .cmp_lte => try genBinOp(o, inst.castTag(.cmp_lte).?, " <= "), |
| | 401 | .cmp_neq => try genBinOp(o, inst.castTag(.cmp_neq).?, " != "), |
| | 402 | .dbg_stmt => try genDbgStmt(o, inst.castTag(.dbg_stmt).?), |
| | 403 | .intcast => try genIntCast(o, inst.castTag(.intcast).?), |
| | 404 | .load => try genLoad(o, inst.castTag(.load).?), |
| | 405 | .ret => try genRet(o, inst.castTag(.ret).?), |
| | 406 | .retvoid => try genRetVoid(o), |
| | 407 | .store => try genStore(o, inst.castTag(.store).?), |
| | 408 | .sub => try genBinOp(o, inst.castTag(.sub).?, " - "), |
| | 409 | .unreach => try genUnreach(o, inst.castTag(.unreach).?), |
| | 410 | .loop => try genLoop(o, inst.castTag(.loop).?), |
| | 411 | else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}), |
| | 412 | }; |
| | 413 | switch (result_value) { |
| | 414 | .none => {}, |
| | 415 | else => try o.value_map.putNoClobber(inst, result_value), |
| | 416 | } |
| | 417 | } |
| | 418 | |
| | 419 | try writer.writeAll("}"); |
| | 420 | } |
| | 421 | |
| 413 | fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue { | 422 | fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue { |
| 414 | const writer = o.code.writer(); | 423 | const writer = o.code.writer(); |
| 415 | | 424 | |
| ... | @@ -627,6 +636,14 @@ fn genUnreach(o: *Object, inst: *Inst.NoOp) !CValue { | ... | @@ -627,6 +636,14 @@ fn genUnreach(o: *Object, inst: *Inst.NoOp) !CValue { |
| 627 | return CValue.none; | 636 | return CValue.none; |
| 628 | } | 637 | } |
| 629 | | 638 | |
| | 639 | fn genLoop(o: *Object, inst: *Inst.Loop) !CValue { |
| | 640 | try o.indent(); |
| | 641 | try o.code.writer().writeAll("while (true)"); |
| | 642 | try genBody(o, inst.body); |
| | 643 | try o.code.writer().writeAll("\n"); |
| | 644 | return CValue.none; |
| | 645 | } |
| | 646 | |
| 630 | fn genAsm(o: *Object, as: *Inst.Assembly) !CValue { | 647 | fn genAsm(o: *Object, as: *Inst.Assembly) !CValue { |
| 631 | if (as.base.isUnused() and !as.is_volatile) | 648 | if (as.base.isUnused() and !as.is_volatile) |
| 632 | return CValue.none; | 649 | return CValue.none; |