@@ -1368,3 +1368,275 @@ fn var_external_blocks_are_ignored_in_init_functions() {
13681368 }
13691369 "### )
13701370}
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