@@ -60,7 +60,8 @@ namespace Slang
60
60
// clear out the old value
61
61
if (usedVal)
62
62
{
63
- *prevLink = nextUse;
63
+ if (prevLink)
64
+ *prevLink = nextUse;
64
65
}
65
66
66
67
init (user, usedVal);
@@ -934,6 +935,19 @@ namespace Slang
934
935
return entry;
935
936
}
936
937
938
+ IRWitnessTable * IRBuilder::lookupWitnessTable (String mangledName)
939
+ {
940
+ IRWitnessTable * result;
941
+ if (sharedBuilder->witnessTableMap .TryGetValue (mangledName, result))
942
+ return result;
943
+ return nullptr ;
944
+ }
945
+
946
+
947
+ void IRBuilder::registerWitnessTable (IRWitnessTable * table)
948
+ {
949
+ sharedBuilder->witnessTableMap [table->mangledName ] = table;
950
+ }
937
951
938
952
IRBlock* IRBuilder::createBlock ()
939
953
{
@@ -1396,7 +1410,7 @@ namespace Slang
1396
1410
struct IRDumpContext
1397
1411
{
1398
1412
StringBuilder* builder;
1399
- int indent;
1413
+ int indent = 0 ;
1400
1414
1401
1415
UInt idCounter = 1 ;
1402
1416
Dictionary<IRValue*, UInt> mapValueToID;
@@ -1588,7 +1602,7 @@ namespace Slang
1588
1602
}
1589
1603
else if (auto proxyVal = dynamic_cast <IRProxyVal*>(val))
1590
1604
{
1591
- dumpOperand (context, proxyVal->inst );
1605
+ dumpOperand (context, proxyVal->inst . usedValue );
1592
1606
}
1593
1607
else
1594
1608
{
@@ -2095,6 +2109,17 @@ namespace Slang
2095
2109
dump (context, " }\n " );
2096
2110
}
2097
2111
2112
+
2113
+ String dumpIRFunc (IRFunc* func)
2114
+ {
2115
+ IRDumpContext dumpContext;
2116
+ StringBuilder sbDump;
2117
+ dumpContext.builder = &sbDump;
2118
+ dumpIRFunc (&dumpContext, func);
2119
+ auto strFunc = sbDump.ToString ();
2120
+ return strFunc;
2121
+ }
2122
+
2098
2123
void dumpIRGlobalVar (
2099
2124
IRDumpContext* context,
2100
2125
IRGlobalVar* var)
@@ -3199,7 +3224,6 @@ namespace Slang
3199
3224
case kIROp_Func :
3200
3225
case kIROp_witness_table :
3201
3226
return cloneGlobalValue (this , (IRGlobalValue*) originalValue);
3202
-
3203
3227
case kIROp_boolConst :
3204
3228
{
3205
3229
IRConstant* c = (IRConstant*)originalValue;
@@ -3246,7 +3270,7 @@ namespace Slang
3246
3270
{
3247
3271
auto proxyVal = witness.Value .As <IRProxyVal>();
3248
3272
SLANG_ASSERT (proxyVal);
3249
- return proxyVal->inst ;
3273
+ return proxyVal->inst . usedValue ;
3250
3274
}
3251
3275
}
3252
3276
}
@@ -3270,16 +3294,20 @@ namespace Slang
3270
3294
}
3271
3295
}
3272
3296
3297
+ IRValue* cloneValue (
3298
+ IRSpecContextBase* context,
3299
+ IRValue* originalValue);
3300
+
3273
3301
RefPtr<Val> cloneSubstitutionArg (
3274
3302
IRSpecContext* context,
3275
3303
Val* val)
3276
3304
{
3277
3305
if (auto proxyVal = dynamic_cast <IRProxyVal*>(val))
3278
3306
{
3279
- auto newIRVal = context-> maybeCloneValue ( proxyVal->inst );
3307
+ auto newIRVal = cloneValue (context, proxyVal->inst . usedValue );
3280
3308
3281
3309
RefPtr<IRProxyVal> newProxyVal = new IRProxyVal ();
3282
- newProxyVal->inst = newIRVal;
3310
+ newProxyVal->inst . init ( nullptr , newIRVal) ;
3283
3311
return newProxyVal;
3284
3312
}
3285
3313
else if (auto type = dynamic_cast <Type*>(val))
@@ -3307,7 +3335,7 @@ namespace Slang
3307
3335
for (auto arg : genSubst->args )
3308
3336
{
3309
3337
auto newArg = cloneSubstitutionArg (context, arg);
3310
- newSubst->args .Add (arg );
3338
+ newSubst->args .Add (newArg );
3311
3339
}
3312
3340
return newSubst;
3313
3341
}
@@ -3436,7 +3464,7 @@ namespace Slang
3436
3464
}
3437
3465
3438
3466
IRWitnessTable* cloneWitnessTableImpl (
3439
- IRSpecContext * context,
3467
+ IRSpecContextBase * context,
3440
3468
IRWitnessTable* originalTable,
3441
3469
IROriginalValuesForClone const & originalValues)
3442
3470
{
@@ -3445,7 +3473,9 @@ namespace Slang
3445
3473
3446
3474
auto mangledName = originalTable->mangledName ;
3447
3475
clonedTable->mangledName = mangledName;
3448
-
3476
+ clonedTable->genericDecl = originalTable->genericDecl ;
3477
+ clonedTable->subTypeDeclRef = originalTable->subTypeDeclRef ;
3478
+ clonedTable->supTypeDeclRef = originalTable->supTypeDeclRef ;
3449
3479
cloneDecorations (context, clonedTable, originalTable);
3450
3480
3451
3481
// Clone the entries in the witness table as well
@@ -3463,7 +3493,7 @@ namespace Slang
3463
3493
}
3464
3494
3465
3495
IRWitnessTable* cloneWitnessTableWithoutRegistering (
3466
- IRSpecContext * context,
3496
+ IRSpecContextBase * context,
3467
3497
IRWitnessTable* originalTable)
3468
3498
{
3469
3499
return cloneWitnessTableImpl (context, originalTable, IROriginalValuesForClone ());
@@ -4008,7 +4038,7 @@ namespace Slang
4008
4038
SLANG_ASSERT (table);
4009
4039
table = cloneWitnessTableWithoutRegistering (context, (IRWitnessTable*)(table));
4010
4040
IRProxyVal * tableVal = new IRProxyVal ();
4011
- tableVal->inst = table;
4041
+ tableVal->inst . init ( nullptr , table) ;
4012
4042
paramSubst->witnessTables .Add (KeyValuePair<RefPtr<Type>, RefPtr<Val>>(subtypeWitness->sup , tableVal));
4013
4043
}
4014
4044
}
@@ -4228,7 +4258,7 @@ namespace Slang
4228
4258
// the pointed-to value and not the proxy type-level `Val`
4229
4259
// instead.
4230
4260
4231
- return context->maybeCloneValue (proxyVal->inst );
4261
+ return context->maybeCloneValue (proxyVal->inst . usedValue );
4232
4262
}
4233
4263
else
4234
4264
{
@@ -4394,6 +4424,69 @@ namespace Slang
4394
4424
return newSubst;
4395
4425
}
4396
4426
4427
+ IRFunc* getSpecializedFunc (
4428
+ IRSharedGenericSpecContext* sharedContext,
4429
+ IRFunc* genericFunc,
4430
+ DeclRef<Decl> specDeclRef);
4431
+
4432
+ IRWitnessTable* specializeWitnessTable (IRSharedGenericSpecContext * sharedContext, IRWitnessTable* originalTable, DeclRef<Decl> specDeclRef)
4433
+ {
4434
+ // First, we want to see if an existing specialization
4435
+ // has already been made. To do that we will need to
4436
+ // compute the mangled name of the specialized function,
4437
+ // so that we can look for existing declarations.
4438
+ String specMangledName;
4439
+ String specializedMangledName = getMangledNameForConformanceWitness (specDeclRef.Substitute (originalTable->subTypeDeclRef ),
4440
+ specDeclRef.Substitute (originalTable->supTypeDeclRef ));
4441
+
4442
+ // TODO: This is a terrible linear search, and we should
4443
+ // avoid it by building a dictionary ahead of time,
4444
+ // as is being done for the `IRSpecContext` used above.
4445
+ // We can probalby use the same basic context, actually.
4446
+ auto module = originalTable->parentModule ;
4447
+ for (auto gv = module->getFirstGlobalValue (); gv; gv = gv->getNextValue ())
4448
+ {
4449
+ if (gv->mangledName == specMangledName)
4450
+ return (IRWitnessTable*)gv;
4451
+ }
4452
+
4453
+ RefPtr<Substitutions> newSubst = cloneSubstitutionsForSpecialization (
4454
+ sharedContext,
4455
+ specDeclRef.substitutions ,
4456
+ originalTable->genericDecl );
4457
+
4458
+ IRGenericSpecContext context;
4459
+ context.shared = sharedContext;
4460
+ context.builder = &sharedContext->builderStorage ;
4461
+ context.subst = newSubst;
4462
+
4463
+ // TODO: other initialization is needed here...
4464
+
4465
+ auto specTable = cloneWitnessTableWithoutRegistering (&context, originalTable);
4466
+
4467
+ // Set up the clone to recognize that it is no longer generic
4468
+ specTable->mangledName = specMangledName;
4469
+ specTable->genericDecl = nullptr ;
4470
+
4471
+ // Specialization of witness tables should trigger cascading specializations
4472
+ // of involved functions.
4473
+ for (auto entry : specTable->entries )
4474
+ {
4475
+ if (entry->satisfyingVal .usedValue ->op == kIROp_Func )
4476
+ {
4477
+ IRFunc* func = (IRFunc*)entry->satisfyingVal .usedValue ;
4478
+ if (func->genericDecl )
4479
+ entry->satisfyingVal .set (getSpecializedFunc (sharedContext, func, specDeclRef));
4480
+ }
4481
+
4482
+ }
4483
+ // We also need to make sure that we register this specialized
4484
+ // function under its mangled name, so that later lookup
4485
+ // steps will find it.
4486
+ insertGlobalValueSymbol (sharedContext, specTable);
4487
+
4488
+ return specTable;
4489
+ }
4397
4490
4398
4491
IRFunc* getSpecializedFunc (
4399
4492
IRSharedGenericSpecContext* sharedContext,
@@ -4415,9 +4508,9 @@ namespace Slang
4415
4508
// as is being done for the `IRSpecContext` used above.
4416
4509
// We can probalby use the same basic context, actually.
4417
4510
auto module = genericFunc->parentModule ;
4418
- for (auto gv = module->getFirstGlobalValue (); gv; gv = gv->getNextValue ())
4511
+ for (auto gv = module->getFirstGlobalValue (); gv; gv = gv->getNextValue ())
4419
4512
{
4420
- if (gv->mangledName == specMangledName)
4513
+ if (gv->mangledName == specMangledName)
4421
4514
return (IRFunc*) gv;
4422
4515
}
4423
4516
@@ -4564,7 +4657,7 @@ namespace Slang
4564
4657
// specialization to perform.
4565
4658
auto func = workList[count-1 ];
4566
4659
workList.RemoveAt (count-1 );
4567
-
4660
+
4568
4661
// We are going to go ahead and walk through
4569
4662
// all the instructions in this function,
4570
4663
// and look for `specialize` operations.
@@ -4596,32 +4689,40 @@ namespace Slang
4596
4689
// specialization here and now.
4597
4690
IRSpecialize* specInst = (IRSpecialize*) ii;
4598
4691
4599
- // We need to check that the value being specialized is
4600
- // a generic function.
4601
- auto genericVal = specInst->genericVal .usedValue ;
4602
- if (genericVal->op != kIROp_Func )
4603
- continue ;
4604
- auto genericFunc = (IRFunc*) genericVal;
4605
- if (!genericFunc->genericDecl )
4606
- continue ;
4607
-
4608
4692
// Now we extract the specialized decl-ref that will
4609
4693
// tell us how to specialize things.
4610
- auto specDeclRefVal = (IRDeclRef*) specInst->specDeclRefVal .usedValue ;
4694
+ auto specDeclRefVal = (IRDeclRef*)specInst->specDeclRefVal .usedValue ;
4611
4695
auto specDeclRef = specDeclRefVal->declRef ;
4612
4696
4613
- // Okay, we have a candidate for specialization here.
4614
- //
4615
- // We will first find or construct a specialized version
4616
- // of the callee funciton/
4617
- auto specFunc = getSpecializedFunc (sharedContext, genericFunc, specDeclRef);
4618
- //
4619
- // Then we will replace the use sites for the `specialize`
4620
- // instruction with uses of the specialized function.
4621
- //
4622
- specInst->replaceUsesWith (specFunc);
4623
-
4624
- specInst->removeAndDeallocate ();
4697
+ // We need to specialize functions and witness tables
4698
+ auto genericVal = specInst->genericVal .usedValue ;
4699
+ if (genericVal->op == kIROp_Func )
4700
+ {
4701
+ auto genericFunc = (IRFunc*)genericVal;
4702
+ if (!genericFunc->genericDecl )
4703
+ continue ;
4704
+
4705
+ // Okay, we have a candidate for specialization here.
4706
+ //
4707
+ // We will first find or construct a specialized version
4708
+ // of the callee funciton/
4709
+ auto specFunc = getSpecializedFunc (sharedContext, genericFunc, specDeclRef);
4710
+ //
4711
+ // Then we will replace the use sites for the `specialize`
4712
+ // instruction with uses of the specialized function.
4713
+ //
4714
+ specInst->replaceUsesWith (specFunc);
4715
+
4716
+ specInst->removeAndDeallocate ();
4717
+ }
4718
+ else if (genericVal->op == kIROp_witness_table )
4719
+ {
4720
+ // specialize a witness table
4721
+ auto originalTable = (IRWitnessTable*)genericVal;
4722
+ auto specWitnessTable = specializeWitnessTable (sharedContext, originalTable, specDeclRef);
4723
+ specInst->replaceUsesWith (specWitnessTable);
4724
+ specInst->removeAndDeallocate ();
4725
+ }
4625
4726
}
4626
4727
break ;
4627
4728
0 commit comments