@@ -1368,3 +1368,275 @@ fn var_external_blocks_are_ignored_in_init_functions() {
1368
1368
}
1369
1369
"### )
1370
1370
}
1371
+
1372
+ #[ test]
1373
+ fn ref_to_local_member ( ) {
1374
+ let res = codegen (
1375
+ r"
1376
+ FUNCTION_BLOCK foo
1377
+ VAR
1378
+ s : STRING;
1379
+ ptr : REF_TO STRING := REF(s);
1380
+ alias AT s : STRING;
1381
+ reference_to : REFERENCE TO STRING REF= s;
1382
+ END_VAR
1383
+ END_FUNCTION_BLOCK
1384
+ " ,
1385
+ ) ;
1386
+
1387
+ insta:: assert_snapshot!( res, @r#"
1388
+ ; ModuleID = '<internal>'
1389
+ source_filename = "<internal>"
1390
+
1391
+ %foo = type { [81 x i8], [81 x i8]*, [81 x i8]*, [81 x i8]* }
1392
+
1393
+ @__foo__init = unnamed_addr constant %foo zeroinitializer
1394
+
1395
+ define void @foo(%foo* %0) {
1396
+ entry:
1397
+ %s = getelementptr inbounds %foo, %foo* %0, i32 0, i32 0
1398
+ %ptr = getelementptr inbounds %foo, %foo* %0, i32 0, i32 1
1399
+ %alias = getelementptr inbounds %foo, %foo* %0, i32 0, i32 2
1400
+ %reference_to = getelementptr inbounds %foo, %foo* %0, i32 0, i32 3
1401
+ ret void
1402
+ }
1403
+ ; ModuleID = '__initializers'
1404
+ source_filename = "__initializers"
1405
+
1406
+ %foo = type { [81 x i8], [81 x i8]*, [81 x i8]*, [81 x i8]* }
1407
+
1408
+ @__foo__init = external global %foo
1409
+
1410
+ define void @__init_foo(%foo* %0) {
1411
+ entry:
1412
+ %self = alloca %foo*, align 8
1413
+ store %foo* %0, %foo** %self, align 8
1414
+ %deref = load %foo*, %foo** %self, align 8
1415
+ %ptr = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 1
1416
+ %deref1 = load %foo*, %foo** %self, align 8
1417
+ %s = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 0
1418
+ store [81 x i8]* %s, [81 x i8]** %ptr, align 8
1419
+ %deref2 = load %foo*, %foo** %self, align 8
1420
+ %alias = getelementptr inbounds %foo, %foo* %deref2, i32 0, i32 2
1421
+ %deref3 = load %foo*, %foo** %self, align 8
1422
+ %s4 = getelementptr inbounds %foo, %foo* %deref3, i32 0, i32 0
1423
+ store [81 x i8]* %s4, [81 x i8]** %alias, align 8
1424
+ %deref5 = load %foo*, %foo** %self, align 8
1425
+ %reference_to = getelementptr inbounds %foo, %foo* %deref5, i32 0, i32 3
1426
+ %deref6 = load %foo*, %foo** %self, align 8
1427
+ %s7 = getelementptr inbounds %foo, %foo* %deref6, i32 0, i32 0
1428
+ store [81 x i8]* %s7, [81 x i8]** %reference_to, align 8
1429
+ ret void
1430
+ }
1431
+
1432
+ declare void @foo(%foo*)
1433
+ ; ModuleID = '__init___testproject'
1434
+ source_filename = "__init___testproject"
1435
+
1436
+ @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__init___testproject, i8* null }]
1437
+
1438
+ define void @__init___testproject() {
1439
+ entry:
1440
+ ret void
1441
+ }
1442
+ "# )
1443
+ }
1444
+
1445
+ #[ test]
1446
+ fn ref_to_local_member_shadows_global ( ) {
1447
+ let res = codegen (
1448
+ r"
1449
+ VAR_GLOBAL
1450
+ s : STRING;
1451
+ END_VAR
1452
+
1453
+ FUNCTION_BLOCK foo
1454
+ VAR
1455
+ s : STRING;
1456
+ ptr : REF_TO STRING := REF(s);
1457
+ alias AT s : STRING;
1458
+ reference_to : REFERENCE TO STRING REF= s;
1459
+ END_VAR
1460
+ END_FUNCTION_BLOCK
1461
+ " ,
1462
+ ) ;
1463
+
1464
+ insta:: assert_snapshot!( res, @r#"
1465
+ ; ModuleID = '<internal>'
1466
+ source_filename = "<internal>"
1467
+
1468
+ %foo = type { [81 x i8], [81 x i8]*, [81 x i8]*, [81 x i8]* }
1469
+
1470
+ @s = global [81 x i8] zeroinitializer
1471
+ @__foo__init = unnamed_addr constant %foo zeroinitializer
1472
+
1473
+ define void @foo(%foo* %0) {
1474
+ entry:
1475
+ %s = getelementptr inbounds %foo, %foo* %0, i32 0, i32 0
1476
+ %ptr = getelementptr inbounds %foo, %foo* %0, i32 0, i32 1
1477
+ %alias = getelementptr inbounds %foo, %foo* %0, i32 0, i32 2
1478
+ %reference_to = getelementptr inbounds %foo, %foo* %0, i32 0, i32 3
1479
+ ret void
1480
+ }
1481
+ ; ModuleID = '__initializers'
1482
+ source_filename = "__initializers"
1483
+
1484
+ %foo = type { [81 x i8], [81 x i8]*, [81 x i8]*, [81 x i8]* }
1485
+
1486
+ @__foo__init = external global %foo
1487
+
1488
+ define void @__init_foo(%foo* %0) {
1489
+ entry:
1490
+ %self = alloca %foo*, align 8
1491
+ store %foo* %0, %foo** %self, align 8
1492
+ %deref = load %foo*, %foo** %self, align 8
1493
+ %ptr = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 1
1494
+ %deref1 = load %foo*, %foo** %self, align 8
1495
+ %s = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 0
1496
+ store [81 x i8]* %s, [81 x i8]** %ptr, align 8
1497
+ %deref2 = load %foo*, %foo** %self, align 8
1498
+ %alias = getelementptr inbounds %foo, %foo* %deref2, i32 0, i32 2
1499
+ %deref3 = load %foo*, %foo** %self, align 8
1500
+ %s4 = getelementptr inbounds %foo, %foo* %deref3, i32 0, i32 0
1501
+ store [81 x i8]* %s4, [81 x i8]** %alias, align 8
1502
+ %deref5 = load %foo*, %foo** %self, align 8
1503
+ %reference_to = getelementptr inbounds %foo, %foo* %deref5, i32 0, i32 3
1504
+ %deref6 = load %foo*, %foo** %self, align 8
1505
+ %s7 = getelementptr inbounds %foo, %foo* %deref6, i32 0, i32 0
1506
+ store [81 x i8]* %s7, [81 x i8]** %reference_to, align 8
1507
+ ret void
1508
+ }
1509
+
1510
+ declare void @foo(%foo*)
1511
+ ; ModuleID = '__init___testproject'
1512
+ source_filename = "__init___testproject"
1513
+
1514
+ @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__init___testproject, i8* null }]
1515
+
1516
+ define void @__init___testproject() {
1517
+ entry:
1518
+ ret void
1519
+ }
1520
+ "# )
1521
+ }
1522
+
1523
+ #[ test]
1524
+ fn temporary_variable_ref_to_local_member ( ) {
1525
+ let res = codegen (
1526
+ r"
1527
+ FUNCTION_BLOCK foo
1528
+ VAR
1529
+ s : STRING;
1530
+ END_VAR
1531
+ VAR_TEMP
1532
+ ptr : REF_TO STRING := REF(s);
1533
+ alias AT s : STRING;
1534
+ reference_to : REFERENCE TO STRING REF= s;
1535
+ END_VAR
1536
+ END_FUNCTION_BLOCK
1537
+ " ,
1538
+ ) ;
1539
+
1540
+ insta:: assert_snapshot!( res, @r#"
1541
+ ; ModuleID = '<internal>'
1542
+ source_filename = "<internal>"
1543
+
1544
+ %foo = type { [81 x i8] }
1545
+
1546
+ @__foo__init = unnamed_addr constant %foo zeroinitializer
1547
+
1548
+ define void @foo(%foo* %0) {
1549
+ entry:
1550
+ %s = getelementptr inbounds %foo, %foo* %0, i32 0, i32 0
1551
+ %ptr = alloca [81 x i8]*, align 8
1552
+ %alias = alloca [81 x i8]*, align 8
1553
+ %reference_to = alloca [81 x i8]*, align 8
1554
+ store [81 x i8]* %s, [81 x i8]** %ptr, align 8
1555
+ store [81 x i8]* null, [81 x i8]** %alias, align 8
1556
+ store [81 x i8]* null, [81 x i8]** %reference_to, align 8
1557
+ store [81 x i8]* %s, [81 x i8]** %ptr, align 8
1558
+ store [81 x i8]* %s, [81 x i8]** %alias, align 8
1559
+ store [81 x i8]* %s, [81 x i8]** %reference_to, align 8
1560
+ ret void
1561
+ }
1562
+ ; ModuleID = '__initializers'
1563
+ source_filename = "__initializers"
1564
+
1565
+ %foo = type { [81 x i8] }
1566
+
1567
+ @__foo__init = external global %foo
1568
+
1569
+ define void @__init_foo(%foo* %0) {
1570
+ entry:
1571
+ %self = alloca %foo*, align 8
1572
+ store %foo* %0, %foo** %self, align 8
1573
+ ret void
1574
+ }
1575
+
1576
+ declare void @foo(%foo*)
1577
+ ; ModuleID = '__init___testproject'
1578
+ source_filename = "__init___testproject"
1579
+
1580
+ @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__init___testproject, i8* null }]
1581
+
1582
+ define void @__init___testproject() {
1583
+ entry:
1584
+ ret void
1585
+ }
1586
+ "# )
1587
+ }
1588
+
1589
+ #[ test]
1590
+ fn temporary_variable_ref_to_temporary_variable ( ) {
1591
+ let res = codegen (
1592
+ r"
1593
+ FUNCTION foo
1594
+ VAR
1595
+ ptr : REF_TO STRING := REF(s);
1596
+ alias AT s : STRING;
1597
+ END_VAR
1598
+ VAR_TEMP
1599
+ s : STRING;
1600
+ reference_to : REFERENCE TO STRING REF= alias;
1601
+ END_VAR
1602
+ FUNCTION
1603
+ " ,
1604
+ ) ;
1605
+
1606
+ insta:: assert_snapshot!( res, @r##"
1607
+ ; ModuleID = '<internal>'
1608
+ source_filename = "<internal>"
1609
+
1610
+ define void @foo() {
1611
+ entry:
1612
+ %ptr = alloca [81 x i8]*, align 8
1613
+ %alias = alloca [81 x i8]*, align 8
1614
+ %s = alloca [81 x i8], align 1
1615
+ %reference_to = alloca [81 x i8]*, align 8
1616
+ store [81 x i8]* %s, [81 x i8]** %ptr, align 8
1617
+ store [81 x i8]* null, [81 x i8]** %alias, align 8
1618
+ %0 = bitcast [81 x i8]* %s to i8*
1619
+ call void @llvm.memset.p0i8.i64(i8* align 1 %0, i8 0, i64 ptrtoint ([81 x i8]* getelementptr ([81 x i8], [81 x i8]* null, i32 1) to i64), i1 false)
1620
+ store [81 x i8]* null, [81 x i8]** %reference_to, align 8
1621
+ store [81 x i8]* %s, [81 x i8]** %ptr, align 8
1622
+ store [81 x i8]* %s, [81 x i8]** %alias, align 8
1623
+ %deref = load [81 x i8]*, [81 x i8]** %alias, align 8
1624
+ store [81 x i8]* %deref, [81 x i8]** %reference_to, align 8
1625
+ ret void
1626
+ }
1627
+
1628
+ ; Function Attrs: argmemonly nofree nounwind willreturn writeonly
1629
+ declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #0
1630
+
1631
+ attributes #0 = { argmemonly nofree nounwind willreturn writeonly }
1632
+ ; ModuleID = '__init___testproject'
1633
+ source_filename = "__init___testproject"
1634
+
1635
+ @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__init___testproject, i8* null }]
1636
+
1637
+ define void @__init___testproject() {
1638
+ entry:
1639
+ ret void
1640
+ }
1641
+ "## )
1642
+ }
0 commit comments