| ... | ... | @@ -251,10 +251,42 @@ pub const DeclGen = struct { |
| 251 | 251 | return error.AnalysisFail; |
| 252 | 252 | } |
| 253 | 253 | |
| 254 | fn renderDeclValue( |
| 255 | dg: *DeclGen, |
| 256 | writer: anytype, |
| 257 | ty: Type, |
| 258 | val: Value, |
| 259 | decl: *Decl, |
| 260 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 261 | decl.alive = true; |
| 262 | |
| 263 | if (ty.isSlice()) { |
| 264 | try writer.writeByte('('); |
| 265 | try dg.renderType(writer, ty); |
| 266 | try writer.writeAll("){"); |
| 267 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 268 | try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val); |
| 269 | try writer.writeAll(", "); |
| 270 | try writer.print("{d}", .{val.sliceLen()}); |
| 271 | try writer.writeAll("}"); |
| 272 | return; |
| 273 | } |
| 274 | |
| 275 | // Determine if we must pointer cast. |
| 276 | assert(decl.has_tv); |
| 277 | if (ty.eql(decl.ty)) { |
| 278 | try writer.print("&{s}", .{decl.name}); |
| 279 | } else { |
| 280 | try writer.writeAll("("); |
| 281 | try dg.renderType(writer, ty); |
| 282 | try writer.print(")&{s}", .{decl.name}); |
| 283 | } |
| 284 | } |
| 285 | |
| 254 | 286 | fn renderValue( |
| 255 | 287 | dg: *DeclGen, |
| 256 | 288 | writer: anytype, |
| 257 | | t: Type, |
| 289 | ty: Type, |
| 258 | 290 | val: Value, |
| 259 | 291 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 260 | 292 | if (val.isUndef()) { |
| ... | ... | @@ -264,50 +296,50 @@ pub const DeclGen = struct { |
| 264 | 296 | return writer.writeAll("{}"); |
| 265 | 297 | //return dg.fail("TODO: C backend: implement renderValue undef", .{}); |
| 266 | 298 | } |
| 267 | | switch (t.zigTypeTag()) { |
| 299 | switch (ty.zigTypeTag()) { |
| 268 | 300 | .Int => { |
| 269 | | if (t.isSignedInt()) |
| 301 | if (ty.isSignedInt()) |
| 270 | 302 | return writer.print("{d}", .{val.toSignedInt()}); |
| 271 | 303 | return writer.print("{d}", .{val.toUnsignedInt()}); |
| 272 | 304 | }, |
| 273 | | .Pointer => switch (t.ptrSize()) { |
| 274 | | .Slice => { |
| 305 | .Float => { |
| 306 | if (ty.floatBits(dg.module.getTarget()) <= 64) { |
| 307 | return writer.print("{x}", .{val.toFloat(f64)}); |
| 308 | } |
| 309 | return dg.fail("TODO: C backend: implement lowering large float values", .{}); |
| 310 | }, |
| 311 | .Pointer => switch (val.tag()) { |
| 312 | .null_value, .zero => try writer.writeAll("NULL"), |
| 313 | .one => try writer.writeAll("1"), |
| 314 | .decl_ref => { |
| 315 | const decl = val.castTag(.decl_ref).?.data; |
| 316 | return dg.renderDeclValue(writer, ty, val, decl); |
| 317 | }, |
| 318 | .variable => { |
| 319 | const decl = val.castTag(.variable).?.data.owner_decl; |
| 320 | return dg.renderDeclValue(writer, ty, val, decl); |
| 321 | }, |
| 322 | .slice => { |
| 323 | const slice = val.castTag(.slice).?.data; |
| 324 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 325 | |
| 275 | 326 | try writer.writeByte('('); |
| 276 | | try dg.renderType(writer, t); |
| 327 | try dg.renderType(writer, ty); |
| 277 | 328 | try writer.writeAll("){"); |
| 278 | | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 279 | | try dg.renderValue(writer, t.slicePtrFieldType(&buf), val); |
| 329 | try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr); |
| 280 | 330 | try writer.writeAll(", "); |
| 281 | | try writer.print("{d}", .{val.sliceLen()}); |
| 331 | try dg.renderValue(writer, Type.usize, slice.len); |
| 282 | 332 | try writer.writeAll("}"); |
| 283 | 333 | }, |
| 284 | | else => switch (val.tag()) { |
| 285 | | .null_value, .zero => try writer.writeAll("NULL"), |
| 286 | | .one => try writer.writeAll("1"), |
| 287 | | .decl_ref => { |
| 288 | | const decl = val.castTag(.decl_ref).?.data; |
| 289 | | decl.alive = true; |
| 290 | | |
| 291 | | // Determine if we must pointer cast. |
| 292 | | assert(decl.has_tv); |
| 293 | | if (t.eql(decl.ty)) { |
| 294 | | try writer.print("&{s}", .{decl.name}); |
| 295 | | } else { |
| 296 | | try writer.writeAll("("); |
| 297 | | try dg.renderType(writer, t); |
| 298 | | try writer.print(")&{s}", .{decl.name}); |
| 299 | | } |
| 300 | | }, |
| 301 | | .function => { |
| 302 | | const func = val.castTag(.function).?.data; |
| 303 | | try writer.print("{s}", .{func.owner_decl.name}); |
| 304 | | }, |
| 305 | | .extern_fn => { |
| 306 | | const decl = val.castTag(.extern_fn).?.data; |
| 307 | | try writer.print("{s}", .{decl.name}); |
| 308 | | }, |
| 309 | | else => unreachable, |
| 334 | .function => { |
| 335 | const func = val.castTag(.function).?.data; |
| 336 | try writer.print("{s}", .{func.owner_decl.name}); |
| 310 | 337 | }, |
| 338 | .extern_fn => { |
| 339 | const decl = val.castTag(.extern_fn).?.data; |
| 340 | try writer.print("{s}", .{decl.name}); |
| 341 | }, |
| 342 | else => unreachable, |
| 311 | 343 | }, |
| 312 | 344 | .Array => { |
| 313 | 345 | // First try specific tag representations for more efficiency. |
| ... | ... | @@ -325,14 +357,14 @@ pub const DeclGen = struct { |
| 325 | 357 | |
| 326 | 358 | try writer.writeAll("{"); |
| 327 | 359 | var index: usize = 0; |
| 328 | | const len = t.arrayLen(); |
| 329 | | const elem_ty = t.elemType(); |
| 360 | const len = ty.arrayLen(); |
| 361 | const elem_ty = ty.elemType(); |
| 330 | 362 | while (index < len) : (index += 1) { |
| 331 | 363 | if (index != 0) try writer.writeAll(","); |
| 332 | 364 | const elem_val = try val.elemValue(&arena.allocator, index); |
| 333 | 365 | try dg.renderValue(writer, elem_ty, elem_val); |
| 334 | 366 | } |
| 335 | | if (t.sentinel()) |sentinel_val| { |
| 367 | if (ty.sentinel()) |sentinel_val| { |
| 336 | 368 | if (index != 0) try writer.writeAll(","); |
| 337 | 369 | try dg.renderValue(writer, elem_ty, sentinel_val); |
| 338 | 370 | } |
| ... | ... | @@ -343,12 +375,12 @@ pub const DeclGen = struct { |
| 343 | 375 | .Bool => return writer.print("{}", .{val.toBool()}), |
| 344 | 376 | .Optional => { |
| 345 | 377 | var opt_buf: Type.Payload.ElemType = undefined; |
| 346 | | const payload_type = t.optionalChild(&opt_buf); |
| 347 | | if (t.isPtrLikeOptional()) { |
| 378 | const payload_type = ty.optionalChild(&opt_buf); |
| 379 | if (ty.isPtrLikeOptional()) { |
| 348 | 380 | return dg.renderValue(writer, payload_type, val); |
| 349 | 381 | } |
| 350 | 382 | try writer.writeByte('('); |
| 351 | | try dg.renderType(writer, t); |
| 383 | try dg.renderType(writer, ty); |
| 352 | 384 | try writer.writeAll("){"); |
| 353 | 385 | if (val.castTag(.opt_payload)) |pl| { |
| 354 | 386 | const payload_val = pl.data; |
| ... | ... | @@ -374,8 +406,8 @@ pub const DeclGen = struct { |
| 374 | 406 | } |
| 375 | 407 | }, |
| 376 | 408 | .ErrorUnion => { |
| 377 | | const error_type = t.errorUnionSet(); |
| 378 | | const payload_type = t.errorUnionPayload(); |
| 409 | const error_type = ty.errorUnionSet(); |
| 410 | const payload_type = ty.errorUnionPayload(); |
| 379 | 411 | |
| 380 | 412 | if (!payload_type.hasCodeGenBits()) { |
| 381 | 413 | // We use the error type directly as the type. |
| ... | ... | @@ -384,7 +416,7 @@ pub const DeclGen = struct { |
| 384 | 416 | } |
| 385 | 417 | |
| 386 | 418 | try writer.writeByte('('); |
| 387 | | try dg.renderType(writer, t); |
| 419 | try dg.renderType(writer, ty); |
| 388 | 420 | try writer.writeAll("){"); |
| 389 | 421 | if (val.castTag(.eu_payload)) |pl| { |
| 390 | 422 | const payload_val = pl.data; |
| ... | ... | @@ -401,10 +433,10 @@ pub const DeclGen = struct { |
| 401 | 433 | switch (val.tag()) { |
| 402 | 434 | .enum_field_index => { |
| 403 | 435 | const field_index = val.castTag(.enum_field_index).?.data; |
| 404 | | switch (t.tag()) { |
| 436 | switch (ty.tag()) { |
| 405 | 437 | .enum_simple => return writer.print("{d}", .{field_index}), |
| 406 | 438 | .enum_full, .enum_nonexhaustive => { |
| 407 | | const enum_full = t.cast(Type.Payload.EnumFull).?.data; |
| 439 | const enum_full = ty.cast(Type.Payload.EnumFull).?.data; |
| 408 | 440 | if (enum_full.values.count() != 0) { |
| 409 | 441 | const tag_val = enum_full.values.keys()[field_index]; |
| 410 | 442 | return dg.renderValue(writer, enum_full.tag_ty, tag_val); |
| ... | ... | @@ -417,7 +449,7 @@ pub const DeclGen = struct { |
| 417 | 449 | }, |
| 418 | 450 | else => { |
| 419 | 451 | var int_tag_ty_buffer: Type.Payload.Bits = undefined; |
| 420 | | const int_tag_ty = t.intTagType(&int_tag_ty_buffer); |
| 452 | const int_tag_ty = ty.intTagType(&int_tag_ty_buffer); |
| 421 | 453 | return dg.renderValue(writer, int_tag_ty, val); |
| 422 | 454 | }, |
| 423 | 455 | } |
| ... | ... | @@ -431,11 +463,11 @@ pub const DeclGen = struct { |
| 431 | 463 | |
| 432 | 464 | // Determine if we must pointer cast. |
| 433 | 465 | assert(decl.has_tv); |
| 434 | | if (t.eql(decl.ty)) { |
| 466 | if (ty.eql(decl.ty)) { |
| 435 | 467 | try writer.print("&{s}", .{decl.name}); |
| 436 | 468 | } else { |
| 437 | 469 | try writer.writeAll("("); |
| 438 | | try dg.renderType(writer, t); |
| 470 | try dg.renderType(writer, ty); |
| 439 | 471 | try writer.print(")&{s}", .{decl.name}); |
| 440 | 472 | } |
| 441 | 473 | }, |
| ... | ... | @@ -451,8 +483,40 @@ pub const DeclGen = struct { |
| 451 | 483 | }, |
| 452 | 484 | else => unreachable, |
| 453 | 485 | }, |
| 454 | | else => |e| return dg.fail("TODO: C backend: implement value {s}", .{ |
| 455 | | @tagName(e), |
| 486 | .Struct => { |
| 487 | const field_vals = val.castTag(.@"struct").?.data; |
| 488 | |
| 489 | try ty.renderFullyQualifiedName(writer); |
| 490 | try writer.writeAll("{"); |
| 491 | |
| 492 | for (field_vals) |field_val, i| { |
| 493 | const field_ty = ty.structFieldType(i); |
| 494 | if (!field_ty.hasCodeGenBits()) continue; |
| 495 | |
| 496 | if (i != 0) try writer.writeAll(","); |
| 497 | try dg.renderValue(writer, field_ty, field_val); |
| 498 | } |
| 499 | |
| 500 | try writer.writeAll("}"); |
| 501 | }, |
| 502 | |
| 503 | .ComptimeInt => unreachable, |
| 504 | .ComptimeFloat => unreachable, |
| 505 | .Type => unreachable, |
| 506 | .EnumLiteral => unreachable, |
| 507 | .Void => unreachable, |
| 508 | .NoReturn => unreachable, |
| 509 | .Undefined => unreachable, |
| 510 | .Null => unreachable, |
| 511 | .BoundFn => unreachable, |
| 512 | .Opaque => unreachable, |
| 513 | |
| 514 | .Union, |
| 515 | .Frame, |
| 516 | .AnyFrame, |
| 517 | .Vector, |
| 518 | => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{ |
| 519 | @tagName(tag), |
| 456 | 520 | }), |
| 457 | 521 | } |
| 458 | 522 | } |