| ... | ... | @@ -6,7 +6,8 @@ const Writer = std.ArrayList(u8).Writer; |
| 6 | 6 | const link = @import("../link.zig"); |
| 7 | 7 | const Module = @import("../Module.zig"); |
| 8 | 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 | 11 | const Value = @import("../value.zig").Value; |
| 11 | 12 | const Type = @import("../type.zig").Type; |
| 12 | 13 | const TypedValue = @import("../TypedValue.zig"); |
| ... | ... | @@ -324,51 +325,13 @@ pub fn genDecl(o: *Object) !void { |
| 324 | 325 | try fwd_decl_writer.writeAll(";\n"); |
| 325 | 326 | |
| 326 | 327 | const func: *Module.Fn = func_payload.data; |
| 327 | | const instructions = func.body.instructions; |
| 328 | 328 | const writer = o.code.writer(); |
| 329 | 329 | try writer.writeAll("\n"); |
| 330 | 330 | try o.dg.renderFunctionSignature(writer, is_global); |
| 331 | | if (instructions.len == 0) { |
| 332 | | try writer.writeAll(" {}\n"); |
| 333 | | return; |
| 334 | | } |
| 335 | | |
| 336 | | try writer.writeAll(" {"); |
| 331 | |
| 332 | try genBody(o, func.body); |
| 337 | 333 | |
| 338 | 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 | 335 | } else if (tv.val.tag() == .extern_fn) { |
| 373 | 336 | const writer = o.code.writer(); |
| 374 | 337 | try writer.writeAll("ZIG_EXTERN_C "); |
| ... | ... | @@ -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 | 422 | fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue { |
| 414 | 423 | const writer = o.code.writer(); |
| 415 | 424 | |
| ... | ... | @@ -627,6 +636,14 @@ fn genUnreach(o: *Object, inst: *Inst.NoOp) !CValue { |
| 627 | 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 | 647 | fn genAsm(o: *Object, as: *Inst.Assembly) !CValue { |
| 631 | 648 | if (as.base.isUnused() and !as.is_volatile) |
| 632 | 649 | return CValue.none; |