authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-11 00:33:51-07:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-12 11:18:23+01:00
log91508e10abe4ab82e4f7a4dcdfac178ebd9e52d3
tree305e11d6d354dc6c96a94deff9b040b9b348054b
parent38236533f1d031d31c6d10cbe7d0f8c59a9e3520

LLVM backend: handle unnamed structs when lowering array values

LLVM doesn't support lowering union values, so we have to use unnamed structs to do it, which means any type that contains a union as an element, even if it is nested in another type, has to have a mechanism to detect when it can't be lowered normally and has to resort itself to an unnamed struct. This includes arrays.

1 files changed, 48 insertions(+), 18 deletions(-)

src/codegen/llvm.zig+48-18
...@@ -1371,14 +1371,24 @@ pub const DeclGen = struct {...@@ -1371,14 +1371,24 @@ pub const DeclGen = struct {
1371 const gpa = dg.gpa;1371 const gpa = dg.gpa;
1372 const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len);1372 const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len);
1373 defer gpa.free(llvm_elems);1373 defer gpa.free(llvm_elems);
1374 var need_unnamed = false;
1374 for (elem_vals) |elem_val, i| {1375 for (elem_vals) |elem_val, i| {
1375 llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val });1376 llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val });
1377 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
1378 }
1379 if (need_unnamed) {
1380 return dg.context.constStruct(
1381 llvm_elems.ptr,
1382 @intCast(c_uint, llvm_elems.len),
1383 .True,
1384 );
1385 } else {
1386 const llvm_elem_ty = try dg.llvmType(elem_ty);
1387 return llvm_elem_ty.constArray(
1388 llvm_elems.ptr,
1389 @intCast(c_uint, llvm_elems.len),
1390 );
1376 }1391 }
1377 const llvm_elem_ty = try dg.llvmType(elem_ty);
1378 return llvm_elem_ty.constArray(
1379 llvm_elems.ptr,
1380 @intCast(c_uint, llvm_elems.len),
1381 );
1382 },1392 },
1383 .repeated => {1393 .repeated => {
1384 const val = tv.val.castTag(.repeated).?.data;1394 const val = tv.val.castTag(.repeated).?.data;
...@@ -1389,25 +1399,46 @@ pub const DeclGen = struct {...@@ -1389,25 +1399,46 @@ pub const DeclGen = struct {
1389 const gpa = dg.gpa;1399 const gpa = dg.gpa;
1390 const llvm_elems = try gpa.alloc(*const llvm.Value, len_including_sent);1400 const llvm_elems = try gpa.alloc(*const llvm.Value, len_including_sent);
1391 defer gpa.free(llvm_elems);1401 defer gpa.free(llvm_elems);
1392 for (llvm_elems[0..len]) |*elem| {1402
1393 elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val });1403 var need_unnamed = false;
1404 if (len != 0) {
1405 for (llvm_elems[0..len]) |*elem| {
1406 elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val });
1407 }
1408 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
1394 }1409 }
1410
1395 if (sentinel) |sent| {1411 if (sentinel) |sent| {
1396 llvm_elems[len] = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent });1412 llvm_elems[len] = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent });
1413 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
1414 }
1415
1416 if (need_unnamed) {
1417 return dg.context.constStruct(
1418 llvm_elems.ptr,
1419 @intCast(c_uint, llvm_elems.len),
1420 .True,
1421 );
1422 } else {
1423 const llvm_elem_ty = try dg.llvmType(elem_ty);
1424 return llvm_elem_ty.constArray(
1425 llvm_elems.ptr,
1426 @intCast(c_uint, llvm_elems.len),
1427 );
1397 }1428 }
1398 const llvm_elem_ty = try dg.llvmType(elem_ty);
1399 return llvm_elem_ty.constArray(
1400 llvm_elems.ptr,
1401 @intCast(c_uint, llvm_elems.len),
1402 );
1403 },1429 },
1404 .empty_array_sentinel => {1430 .empty_array_sentinel => {
1405 const elem_ty = tv.ty.elemType();1431 const elem_ty = tv.ty.elemType();
1406 const sent_val = tv.ty.sentinel().?;1432 const sent_val = tv.ty.sentinel().?;
1407 const sentinel = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent_val });1433 const sentinel = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent_val });
1408 const llvm_elems: [1]*const llvm.Value = .{sentinel};1434 const llvm_elems: [1]*const llvm.Value = .{sentinel};
1409 const llvm_elem_ty = try dg.llvmType(elem_ty);1435 const need_unnamed = dg.isUnnamedType(elem_ty, llvm_elems[0]);
1410 return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);1436 if (need_unnamed) {
1437 return dg.context.constStruct(&llvm_elems, llvm_elems.len, .True);
1438 } else {
1439 const llvm_elem_ty = try dg.llvmType(elem_ty);
1440 return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);
1441 }
1411 },1442 },
1412 else => unreachable,1443 else => unreachable,
1413 },1444 },
...@@ -1495,7 +1526,7 @@ pub const DeclGen = struct {...@@ -1495,7 +1526,7 @@ pub const DeclGen = struct {
1495 var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, llvm_field_count);1526 var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, llvm_field_count);
1496 defer llvm_fields.deinit(gpa);1527 defer llvm_fields.deinit(gpa);
14971528
1498 var make_unnamed_struct = false;1529 var need_unnamed = false;
1499 const struct_obj = tv.ty.castTag(.@"struct").?.data;1530 const struct_obj = tv.ty.castTag(.@"struct").?.data;
1500 if (struct_obj.layout == .Packed) {1531 if (struct_obj.layout == .Packed) {
1501 const target = dg.module.getTarget();1532 const target = dg.module.getTarget();
...@@ -1596,14 +1627,13 @@ pub const DeclGen = struct {...@@ -1596,14 +1627,13 @@ pub const DeclGen = struct {
1596 .val = field_val,1627 .val = field_val,
1597 });1628 });
15981629
1599 make_unnamed_struct = make_unnamed_struct or1630 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field_llvm_val);
1600 dg.isUnnamedType(field_ty, field_llvm_val);
16011631
1602 llvm_fields.appendAssumeCapacity(field_llvm_val);1632 llvm_fields.appendAssumeCapacity(field_llvm_val);
1603 }1633 }
1604 }1634 }
16051635
1606 if (make_unnamed_struct) {1636 if (need_unnamed) {
1607 return dg.context.constStruct(1637 return dg.context.constStruct(
1608 llvm_fields.items.ptr,1638 llvm_fields.items.ptr,
1609 @intCast(c_uint, llvm_fields.items.len),1639 @intCast(c_uint, llvm_fields.items.len),