Skip to content

Commit a19e339

Browse files
committed
Implement cloning of IInterimOperands. The 'block' parameter is required so nested IResultingInstructions can know which BasicBlock they're within.
1 parent 4722d86 commit a19e339

4 files changed

Lines changed: 56 additions & 3 deletions

File tree

src/kOS.Safe/Compilation/IR/IInterimOperand.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,11 @@ public interface IInterimOperand
3131
/// </summary>
3232
/// <returns><c>true</c> if the operands are equal, otherwise <c>false</c>.</returns>
3333
bool Equals(IInterimOperand other);
34+
35+
/// <summary>
36+
/// Clones this instance.
37+
/// </summary>
38+
/// <param name="block">The block within which this instance is being cloned.</param>
39+
IInterimOperand Clone(BasicBlock block);
3440
}
3541
}

src/kOS.Safe/Compilation/IR/IRInstruction.cs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ public bool SwapOperands()
255255
}
256256
return true;
257257
}
258+
259+
public IInterimOperand Clone(BasicBlock block)
260+
=> new IRBinaryOp(block, (BinaryOpcode)SetSourceLocation(Operation), Left.Clone(block), Right.Clone(block));
261+
258262
public override IEnumerable<Opcode> EmitOpcodes()
259263
{
260264
foreach (Opcode opcode in Left.EmitOpcodes())
@@ -264,6 +268,7 @@ public override IEnumerable<Opcode> EmitOpcodes()
264268
Operation.Label = string.Empty;
265269
yield return SetSourceLocation(Operation);
266270
}
271+
267272
public override string ToString()
268273
=> Operation.ToString();
269274
public bool Equals(IInterimOperand other)
@@ -340,6 +345,9 @@ public IRUnaryOp(BasicBlock block, Opcode operation, IInterimOperand operand) :
340345
Operation = operation;
341346
Operand = operand;
342347
}
348+
349+
public IInterimOperand Clone(BasicBlock block)
350+
=> new IRUnaryOp(block, Operation, Operand.Clone(block));
343351
public override IEnumerable<Opcode> EmitOpcodes()
344352
{
345353
foreach (Opcode opcode in Operand.EmitOpcodes())
@@ -477,6 +485,8 @@ public IRNonVarPush(BasicBlock block, Opcode opcode) : base(opcode, block)
477485
{
478486
Operation = opcode;
479487
}
488+
public IInterimOperand Clone(BasicBlock block)
489+
=> new IRNonVarPush(block, Operation);
480490
public override IEnumerable<Opcode> EmitOpcodes()
481491
{
482492
Operation.Label = string.Empty;
@@ -501,6 +511,8 @@ public IRSuffixGet(BasicBlock block, IInterimOperand obj, OpcodeGetMember opcode
501511
Object = obj;
502512
Suffix = opcodeGetMember.Identifier;
503513
}
514+
public IInterimOperand Clone(BasicBlock block)
515+
=> new IRSuffixGet(block, Object.Clone(block), new OpcodeGetMember(Suffix) { SourceLine = SourceLine, SourceColumn = SourceColumn });
504516
public override IEnumerable<Opcode> EmitOpcodes()
505517
{
506518
foreach (Opcode opcode in Object.EmitOpcodes())
@@ -533,7 +545,6 @@ public InterimConstantValue Evaluate()
533545
if (!IsInvariant)
534546
throw new InvalidOperationException();
535547
throw new NotImplementedException();
536-
// MUSTFIX:
537548
#pragma warning disable CS0162 // Unreachable code detected
538549
Encapsulation.Structure obj = (Encapsulation.Structure)(Object as IEvaluatableToConstant).Evaluate()?.Value;
539550
#pragma warning restore CS0162 // Unreachable code detected
@@ -633,6 +644,8 @@ public IRIndexGet(BasicBlock block, IInterimOperand obj, IInterimOperand index,
633644
Object = obj;
634645
Index = index;
635646
}
647+
public IInterimOperand Clone(BasicBlock block)
648+
=> new IRIndexGet(block, Object.Clone(block), Index.Clone(block), new OpcodeGetIndex() { SourceLine = SourceLine, SourceColumn = SourceColumn });
636649
public override IEnumerable<Opcode> EmitOpcodes()
637650
{
638651
foreach (Opcode opcode in Object.EmitOpcodes())
@@ -664,7 +677,6 @@ public InterimConstantValue Evaluate()
664677
{
665678
if (!IsInvariant)
666679
throw new InvalidOperationException();
667-
// MUSTFIX:
668680
throw new NotImplementedException();
669681
//((Encapsulation.IIndexable)Object).GetIndex();
670682
}
@@ -795,6 +807,17 @@ public override IEnumerable<Opcode> EmitOpcodes()
795807
yield return SetSourceLocation(new OpcodeBranchJump() { DestinationLabel = False.Label });
796808
}
797809
}
810+
public IRBranch Clone(BasicBlock block)
811+
{
812+
BranchOpcode opcode;
813+
if (PreferFalse)
814+
opcode = new OpcodeBranchIfFalse();
815+
else
816+
opcode = new OpcodeBranchIfTrue();
817+
opcode.SourceLine = SourceLine;
818+
opcode.SourceColumn = SourceColumn;
819+
return new IRBranch(block, Condition.Clone(block), True, False, opcode);
820+
}
798821
public override string ToString()
799822
=> string.Format("{{br.? {0}/{1}}}", True.Label, False.Label);
800823
public override bool Equals(object obj)
@@ -838,13 +861,22 @@ private bool IsCallInvariant()
838861
}
839862
private Type GetDefaultReturnType()
840863
{
841-
IRCodePart.IRFunction function = Block.CodePart.GetFunction(this);
864+
IRCodePart.IRFunction function = Block?.CodePart?.GetFunction(this);
865+
if (function != null)
866+
return function.Returns.Type;
842867
if (Optimization.Optimizer.FunctionManager.Exists(Function.Replace("()", "")))
843868
return Optimization.Optimizer.FunctionManager.FunctionReturnType(Function.Replace("()", ""));
844869
if (!Direct && IndirectMethod is IRSuffixGetMethod suffixGetMethod)
845870
return suffixGetMethod.Type;
846871
return typeof(Encapsulation.Structure);
847872
}
873+
public IInterimOperand Clone(BasicBlock block)
874+
=> new IRCall(block, new OpcodeCall(Function)
875+
{
876+
Direct = Direct,
877+
SourceLine = SourceLine,
878+
SourceColumn = SourceColumn
879+
}, EmitArgMarker, Arguments);
848880
public override IEnumerable<Opcode> EmitOpcodes()
849881
{
850882
if (EmitArgMarker)

src/kOS.Safe/Compilation/IR/InterimConstantValue.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public override string ToString()
4646

4747
InterimConstantValue IEvaluatableToConstant.Evaluate()
4848
=> this;
49+
50+
IInterimOperand IInterimOperand.Clone(BasicBlock _)
51+
=> this;
4952
}
5053

5154
public class IRRelocateLater : InterimConstantValue
@@ -90,5 +93,8 @@ public class IRParameter : IInterimOperand
9093
public IEnumerable<Opcode> EmitOpcodes() => System.Linq.Enumerable.Empty<Opcode>();
9194
public bool Equals(IInterimOperand other)
9295
=> other == this;
96+
// This shouldn't need to be implemented... Shouldn't.
97+
public IInterimOperand Clone(BasicBlock _)
98+
=> throw new NotImplementedException();
9399
}
94100
}

src/kOS.Safe/Compilation/IR/InterimVariables.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ public InterimVariableReference(string name, short sourceLine, short sourceColum
3030
SourceColumn = sourceColumn;
3131
}
3232

33+
public IInterimOperand Clone(BasicBlock _)
34+
=> this;
35+
3336
public IEnumerable<Opcode> EmitOpcodes()
3437
{
3538
yield return new OpcodePush(Name)
@@ -78,6 +81,9 @@ public InterimResolvedReference(SSADefinition reference, short sourceLine, short
7881
SourceColumn = sourceColumn;
7982
}
8083

84+
public IInterimOperand Clone(BasicBlock _)
85+
=> this;
86+
8187
public IEnumerable<Opcode> EmitOpcodes()
8288
{
8389
yield return new OpcodePush(Name)
@@ -160,6 +166,9 @@ public void AddReference(SSADefinition reference)
160166
references.Add(reference);
161167
}
162168

169+
public IInterimOperand Clone(BasicBlock _)
170+
=> new InterimUnresolvedReference(References, SourceLine, SourceColumn);
171+
163172
public IEnumerable<Opcode> EmitOpcodes()
164173
{
165174
yield return new OpcodePush(Name)

0 commit comments

Comments
 (0)