authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-01-28 20:46:15+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-03-08 00:33:07+02:00
logc22f010fdd2c5ead80cbdc902738a9d023322436
tree681b888df2b3de60678bfbc31984c6bcd9cd9ba4
parentca20d0ea26bba603229377f4843eb8772aeb749d
signature Commit is signed but in an unrecognized format.

stage2 cbe: regular optional types


1 files changed, 30 insertions(+), 11 deletions(-)

src/codegen/c.zig+30-11
...@@ -207,10 +207,12 @@ pub const DeclGen = struct {...@@ -207,10 +207,12 @@ pub const DeclGen = struct {
207 if (t.isPtrLikeOptional()) {207 if (t.isPtrLikeOptional()) {
208 return dg.renderValue(writer, child_type, val);208 return dg.renderValue(writer, child_type, val);
209 }209 }
210 try writer.writeByte('(');
211 try dg.renderType(writer, t);
210 if (val.tag() == .null_value) {212 if (val.tag() == .null_value) {
211 try writer.writeAll("{ .is_null = true }");213 try writer.writeAll("){ .is_null = true }");
212 } else {214 } else {
213 try writer.writeAll("{ .is_null = false, .payload = ");215 try writer.writeAll("){ .is_null = false, .payload = ");
214 try dg.renderValue(writer, child_type, val);216 try dg.renderValue(writer, child_type, val);
215 try writer.writeAll(" }");217 try writer.writeAll(" }");
216 }218 }
...@@ -319,7 +321,11 @@ pub const DeclGen = struct {...@@ -319,7 +321,11 @@ pub const DeclGen = struct {
319 if (t.isPtrLikeOptional()) {321 if (t.isPtrLikeOptional()) {
320 return dg.renderType(w, child_type);322 return dg.renderType(w, child_type);
321 }323 }
322 return dg.fail(dg.decl.src(), "TODO: C backend: more optional types", .{});324
325 // TODO this needs to be typedeffed since different structs are different types.
326 try w.writeAll("struct { ");
327 try dg.renderType(w, child_type);
328 try w.writeAll(" payload; bool is_null; }");
323 },329 },
324 .Null, .Undefined => unreachable, // must be const or comptime330 .Null, .Undefined => unreachable, // must be const or comptime
325 else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement type {s}", .{331 else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement type {s}", .{
...@@ -834,6 +840,7 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {...@@ -834,6 +840,7 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
834fn genIsNull(o: *Object, inst: *Inst.UnOp) !CValue {840fn genIsNull(o: *Object, inst: *Inst.UnOp) !CValue {
835 const writer = o.writer();841 const writer = o.writer();
836 const invert_logic = inst.base.tag == .is_non_null or inst.base.tag == .is_non_null_ptr;842 const invert_logic = inst.base.tag == .is_non_null or inst.base.tag == .is_non_null_ptr;
843 const operator = if (invert_logic) "!=" else "==";
837 const maybe_deref = if (inst.base.tag == .is_null_ptr or inst.base.tag == .is_non_null_ptr) "[0]" else "";844 const maybe_deref = if (inst.base.tag == .is_null_ptr or inst.base.tag == .is_non_null_ptr) "[0]" else "";
838 const operand = try o.resolveInst(inst.operand);845 const operand = try o.resolveInst(inst.operand);
839846
...@@ -843,10 +850,8 @@ fn genIsNull(o: *Object, inst: *Inst.UnOp) !CValue {...@@ -843,10 +850,8 @@ fn genIsNull(o: *Object, inst: *Inst.UnOp) !CValue {
843850
844 if (inst.operand.ty.isPtrLikeOptional()) {851 if (inst.operand.ty.isPtrLikeOptional()) {
845 // operand is a regular pointer, test `operand !=/== NULL`852 // operand is a regular pointer, test `operand !=/== NULL`
846 const operator = if (invert_logic) "!=" else "==";
847 try writer.print("){s} {s} NULL;\n", .{ maybe_deref, operator });853 try writer.print("){s} {s} NULL;\n", .{ maybe_deref, operator });
848 } else {854 } else {
849 const operator = if (invert_logic) "!=" else "==";
850 try writer.print("){s}.is_null {s} true;\n", .{ maybe_deref, operator });855 try writer.print("){s}.is_null {s} true;\n", .{ maybe_deref, operator });
851 }856 }
852 return local;857 return local;
...@@ -856,17 +861,26 @@ fn genOptionalPayload(o: *Object, inst: *Inst.UnOp) !CValue {...@@ -856,17 +861,26 @@ fn genOptionalPayload(o: *Object, inst: *Inst.UnOp) !CValue {
856 const writer = o.writer();861 const writer = o.writer();
857 const operand = try o.resolveInst(inst.operand);862 const operand = try o.resolveInst(inst.operand);
858863
864 const opt_ty = if (inst.operand.ty.zigTypeTag() == .Pointer)
865 inst.operand.ty.elemType()
866 else
867 inst.operand.ty;
868
859 if (opt_ty.isPtrLikeOptional()) {869 if (opt_ty.isPtrLikeOptional()) {
860 // the operand is just a regular pointer, no need to do anything special.870 // the operand is just a regular pointer, no need to do anything special.
871 // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C
861 return operand;872 return operand;
862 }873 }
863874
864 const opt_ty = if (inst.operand.ty.zigTypeTag() == .Pointer)875 const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else ".";
865 inst.operand.ty.elemType()876 const maybe_addrof = if (inst.base.ty.zigTypeTag() == .Pointer) "&" else "";
866 else877
867 inst.operand.ty;878 const local = try o.allocLocal(inst.base.ty, .Const);
879 try writer.print(" = {s}(", .{maybe_addrof});
880 try o.writeCValue(writer, operand);
868881
869 return o.dg.fail(o.dg.decl.src(), "TODO: C backend: genOptionalPayload non ptr-like optionals", .{});882 try writer.print("){s}payload;\n", .{maybe_deref});
883 return local;
870}884}
871885
872fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue {886fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue {
...@@ -878,7 +892,12 @@ fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue {...@@ -878,7 +892,12 @@ fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue {
878 return operand;892 return operand;
879 }893 }
880894
881 return o.dg.fail(o.dg.decl.src(), "TODO: C backend: genWrapOptional non ptr-like optionals", .{});895 // .wrap_optional is used to convert non-optionals into optionals so it can never be null.
896 const local = try o.allocLocal(inst.base.ty, .Const);
897 try writer.writeAll(" = { .is_null = false, .payload =");
898 try o.writeCValue(writer, operand);
899 try writer.writeAll("};\n");
900 return local;
882}901}
883902
884fn IndentWriter(comptime UnderlyingWriter: type) type {903fn IndentWriter(comptime UnderlyingWriter: type) type {