@@ -39,6 +39,23 @@ static void doCopyResultToTempVar(Compiler *comp, Type *type)
39
39
}
40
40
41
41
42
+ static void doEscapeToHeap (Compiler * comp , Type * ptrType )
43
+ {
44
+ // Allocate heap
45
+ genPushIntConst (& comp -> gen , typeSize (& comp -> types , ptrType -> base ));
46
+ genCallBuiltin (& comp -> gen , TYPE_PTR , BUILTIN_NEW );
47
+ doCopyResultToTempVar (comp , ptrType );
48
+
49
+ // Save heap pointer
50
+ genDup (& comp -> gen );
51
+ genPopReg (& comp -> gen , VM_REG_COMMON_0 );
52
+
53
+ // Copy to heap and use heap pointer
54
+ genSwapAssign (& comp -> gen , ptrType -> base -> kind , typeSize (& comp -> types , ptrType -> base ));
55
+ genPushReg (& comp -> gen , VM_REG_COMMON_0 );
56
+ }
57
+
58
+
42
59
static void doIntToRealConv (Compiler * comp , Type * dest , Type * * src , Const * constant , bool lhs )
43
60
{
44
61
BuiltinFunc builtin = lhs ? BUILTIN_REAL_LHS : BUILTIN_REAL ;
@@ -214,22 +231,8 @@ static void doValueToInterfaceConv(Compiler *comp, Type *dest, Type **src, Const
214
231
if (constant )
215
232
comp -> error .handler (comp -> error .context , "Conversion to interface is not allowed in constant expressions" );
216
233
217
- Type * srcPtrType = typeAddPtrTo (& comp -> types , & comp -> blocks , * src );
218
-
219
- // Allocate heap
220
- genPushIntConst (& comp -> gen , typeSize (& comp -> types , * src ));
221
- genCallBuiltin (& comp -> gen , TYPE_PTR , BUILTIN_NEW );
222
- doCopyResultToTempVar (comp , srcPtrType );
223
-
224
- // Save heap pointer
225
- genDup (& comp -> gen );
226
- genPopReg (& comp -> gen , VM_REG_COMMON_0 );
227
-
228
- // Copy to heap and use heap pointer (interfaces accept only pointers as their dynamic types)
229
- genSwapAssign (& comp -> gen , (* src )-> kind , typeSize (& comp -> types , * src ));
230
- genPushReg (& comp -> gen , VM_REG_COMMON_0 );
231
-
232
- * src = srcPtrType ;
234
+ * src = typeAddPtrTo (& comp -> types , & comp -> blocks , * src );
235
+ doEscapeToHeap (comp , * src );
233
236
doPtrToInterfaceConv (comp , dest , src , constant );
234
237
}
235
238
@@ -1121,14 +1124,20 @@ static void parseCompositeLiteral(Compiler *comp, Type **type, Const *constant)
1121
1124
}
1122
1125
1123
1126
1124
- static void parseTypeCastOrCompositeLiteral (Compiler * comp , Ident * ident , Type * * type , Const * constant , bool * isVar , bool * isCall )
1127
+ static void parseTypeCastOrCompositeLiteral (Compiler * comp , Ident * ident , Type * * type , Const * constant , bool * isVar , bool * isCall , bool * isCompLit )
1125
1128
{
1126
1129
* type = parseType (comp , ident );
1127
1130
1128
1131
if (comp -> lex .tok .kind == TOK_LPAR )
1132
+ {
1129
1133
parseTypeCast (comp , type , constant );
1134
+ * isCompLit = false;
1135
+ }
1130
1136
else if (comp -> lex .tok .kind == TOK_LBRACE )
1137
+ {
1131
1138
parseCompositeLiteral (comp , type , constant );
1139
+ * isCompLit = true;
1140
+ }
1132
1141
else
1133
1142
comp -> error .handler (comp -> error .context , "Type cast or composite literal expected" );
1134
1143
@@ -1317,7 +1326,7 @@ static void parseCallSelector(Compiler *comp, Type **type, Const *constant, bool
1317
1326
1318
1327
1319
1328
// selectors = {derefSelector | indexSelector | fieldSelector | callSelector}.
1320
- static void parseSelectors (Compiler * comp , Type * * type , Const * constant , bool * isVar , bool * isCall )
1329
+ static void parseSelectors (Compiler * comp , Type * * type , Const * constant , bool * isVar , bool * isCall , bool * isCompLit )
1321
1330
{
1322
1331
while (comp -> lex .tok .kind == TOK_CARET || comp -> lex .tok .kind == TOK_LBRACKET ||
1323
1332
comp -> lex .tok .kind == TOK_PERIOD || comp -> lex .tok .kind == TOK_LPAR )
@@ -1333,27 +1342,32 @@ static void parseSelectors(Compiler *comp, Type **type, Const *constant, bool *i
1333
1342
case TOK_LPAR : parseCallSelector (comp , type , constant , isVar , isCall ); break ;
1334
1343
default : break ;
1335
1344
} // switch
1345
+
1346
+ * isCompLit = false;
1336
1347
} // while
1337
1348
}
1338
1349
1339
1350
1340
1351
// designator = (primary | typeCast | compositeLiteral) selectors.
1341
- void parseDesignator (Compiler * comp , Type * * type , Const * constant , bool * isVar , bool * isCall )
1352
+ void parseDesignator (Compiler * comp , Type * * type , Const * constant , bool * isVar , bool * isCall , bool * isCompLit )
1342
1353
{
1354
+ * isCompLit = false;
1355
+
1343
1356
Ident * ident = NULL ;
1344
1357
if (comp -> lex .tok .kind == TOK_IDENT && (ident = parseQualIdent (comp )) && ident -> kind != IDENT_TYPE )
1345
1358
parsePrimary (comp , ident , type , constant , isVar , isCall );
1346
1359
else
1347
- parseTypeCastOrCompositeLiteral (comp , ident , type , constant , isVar , isCall );
1360
+ parseTypeCastOrCompositeLiteral (comp , ident , type , constant , isVar , isCall , isCompLit );
1348
1361
1349
- parseSelectors (comp , type , constant , isVar , isCall );
1362
+ parseSelectors (comp , type , constant , isVar , isCall , isCompLit );
1350
1363
}
1351
1364
1352
1365
1353
1366
// designatorList = designator {"," designator}.
1354
1367
void parseDesignatorList (Compiler * comp , Type * * type , Const * constant , bool * isVar , bool * isCall )
1355
1368
{
1356
- parseDesignator (comp , type , constant , isVar , isCall );
1369
+ bool isCompLit ;
1370
+ parseDesignator (comp , type , constant , isVar , isCall , & isCompLit );
1357
1371
1358
1372
if (comp -> lex .tok .kind == TOK_COMMA )
1359
1373
{
@@ -1374,8 +1388,8 @@ void parseDesignatorList(Compiler *comp, Type **type, Const *constant, bool *isV
1374
1388
1375
1389
lexNext (& comp -> lex );
1376
1390
1377
- bool fieldIsVar , fieldIsCall ;
1378
- parseDesignator (comp , & fieldType , NULL , & fieldIsVar , & fieldIsCall );
1391
+ bool fieldIsVar , fieldIsCall , fieldIsCompLit ;
1392
+ parseDesignator (comp , & fieldType , NULL , & fieldIsVar , & fieldIsCall , & fieldIsCompLit );
1379
1393
1380
1394
if (fieldIsVar != * isVar || fieldIsCall != * isCall )
1381
1395
comp -> error .handler (comp -> error .context , "Inconsistent designator list" );
@@ -1400,8 +1414,8 @@ static void parseFactor(Compiler *comp, Type **type, Const *constant)
1400
1414
case TOK_FN :
1401
1415
{
1402
1416
// A designator that isVar is always an addressable quantity (a structured type or a pointer to a value type)
1403
- bool isVar , isCall ;
1404
- parseDesignator (comp , type , constant , & isVar , & isCall );
1417
+ bool isVar , isCall , isCompLit ;
1418
+ parseDesignator (comp , type , constant , & isVar , & isCall , & isCompLit );
1405
1419
if (isVar )
1406
1420
{
1407
1421
if (!typeStructured (* type ))
@@ -1498,14 +1512,19 @@ static void parseFactor(Compiler *comp, Type **type, Const *constant)
1498
1512
1499
1513
lexNext (& comp -> lex );
1500
1514
1501
- bool isVar , isCall ;
1502
- parseDesignator (comp , type , constant , & isVar , & isCall );
1515
+ bool isVar , isCall , isCompLit ;
1516
+ parseDesignator (comp , type , constant , & isVar , & isCall , & isCompLit );
1517
+
1503
1518
if (!isVar )
1504
1519
comp -> error .handler (comp -> error .context , "Unable to take address" );
1505
1520
1506
1521
// A value type is already a pointer, a structured type needs to have it added
1507
1522
if (typeStructured (* type ))
1508
1523
* type = typeAddPtrTo (& comp -> types , & comp -> blocks , * type );
1524
+
1525
+ // Allow returning addresses of composite literals from functions
1526
+ if (isCompLit )
1527
+ doEscapeToHeap (comp , * type );
1509
1528
break ;
1510
1529
}
1511
1530
0 commit comments