in ironclad-apps/tools/DafnyCC/DafnyCC.cs [724:869]
void CompileDatatype2(Type t, TypeApply app)
{
string dataName = app.AppName();
string suffix = dataName.Substring(((UserDefinedType)t).Name.Length);
bool isSeq = dataName.StartsWith("Seq_");
string lemma = isSeq ? "call proc_Seq__Cons__All" + suffix + "();" : "";
TextWriter iwriter = heapIWriter;
List<DatatypeCtor> ctors = compileDatatypes[app].AsDatatype.Ctors;
Func<string,string> dataIs = c => isSeq ? ("is_" + c + "(data)") : ("data is " + c);
string tags = String.Join(" || ", ctors.Select(c =>
"(r.regs[x] == Tag_" + dataName + "_" + c.Name + " && " + dataIs(
Compile_Constructor(t, c.Name, app.typeArgs).AppName()) + ")"));
iwriter.WriteLine(loadTagDecl(dataName, tags));
heapWriter.WriteLine("implementation loadTag_" + dataName
+ "(my r_old:regs, const my core_state:core_state, const linear stk:mem, const linear statics:mem, const linear io:IOState, linear mems_old:mems, $commonVars:commonVars, $gcVars:gcVars, $toAbs:[int]int, $absMem:[int][int]int, $stacksFrames:[int]Frames, objLayouts:[int]ObjLayout, heap:Heap, x:int, y:opn_mem, data:"
+ dataName + ", abs:int, obj:int)");
heapWriter.WriteLine(" returns(my r:regs, linear mems:mems)");
heapWriter.WriteLine("{");
heapWriter.WriteLine(" assert THeapValue(objLayouts, true, $toAbs, obj, abs);");
heapWriter.WriteLine(" assert THeapInv($absMem, objLayouts, heap);");
heapWriter.WriteLine(" " + lemma);
heapWriter.WriteLine(" call r, mems := gcLoadField(r_old, core_state, stk, statics, io, mems_old,");
heapWriter.WriteLine(" $commonVars, $gcVars, $absMem, $toAbs, $stacksFrames, objLayouts,");
heapWriter.WriteLine(" x, y, obj - 4, 2);");
heapWriter.WriteLine("}");
foreach (var ctor in ctors)
{
var ints = ctor.Formals.Where(x => !IsPtrType(app.AppType(x.Type))).ToList();
var ptrs = ctor.Formals.Where(x => IsPtrType(app.AppType(x.Type))).ToList();
var sorted = ints.Concat(ptrs).ToList();
string ctorName = Compile_Constructor(t, ctor.Name, app.typeArgs).AppName();
string cons = isSeq ? ("_" + ctorName) : ctorName;
string parms = String.Join(", ", ctor.Formals.Select(
c => "arg_" + c.Name + ":" + TypeString(app.AppType(c.Type))));
string args = String.Join(", ", ctor.Formals.Select(c => "arg_" + c.Name));
int argRetSize = 4 + 4 * Math.Max(ints.Count, ptrs.Count);
heapIWriter.WriteLine("const stack_size__DafnyCC__Proc_Alloc_" + ctorName + ":int := 256;");
iwriter.WriteLine(allocDecl1(
dataName,
ctorName,
cons,
parms,
args,
argRetSize.ToString()));
string triggers = (IPSize == 8) ? String.Format("{0} && {1}", GcTO64(1), GcTO(3)) : GcTO(1);
for (int i = 0; i < ints.Count; i++)
{
string val = "stk_old.map[r_old.regs[ESP] + "
+ (IPSize + 4 * i) + "]";
iwriter.WriteLine("requires " + CompileBase.IntEqTyped(app.AppType(ints[i].Type), "arg_" + ints[i].Name, val) + ";");
triggers += String.Format(" && {0}", (IPSize == 8 ? StackTO64(i + 1): StackTO(i + 1)));
}
for (int i = 0; i < ptrs.Count; i++)
{
iwriter.WriteLine("requires StackAbsSlot(heap_old, $stacksFrames_old, r_old.regs[ESP] + "
+ (IPSize + 4 + 4 * i) + " + stackGcOffset) == Abs_" + TypeString(app.AppType(ptrs[i].Type))
+ "(arg_" + ptrs[i].Name + ");");
triggers += String.Format(" && {0}", (IPSize == 8 ? GcTO64(i + 2): GcTO(i + 2)));
}
iwriter.WriteLine(allocDecl2(
dataName,
cons,
PreserveHeap(minVerify),
args));
heapWriter.WriteLine(allocImpl1(
dataName,
ctor.Name,
ctorName,
cons,
parms,
args,
(12 + 4 * sorted.Count).ToString(),
(12 + 4 * ints.Count).ToString(),
triggers,
lemma));
for (int i = 0; i < ints.Count; i++)
{
heapWriter.WriteLine(allocImplInt(
dataName,
ctorName,
ints[i].Name,
(12 + IPSize + 4 * i).ToString()));
}
for (int i = 0; i < ptrs.Count; i++)
{
heapWriter.WriteLine(allocImplPtr(
dataName,
ctorName,
ptrs[i].Name,
(RegAlloc.stackGcOffset + 16 + IPSize + 4 * i).ToString() + "/* stackGcOffset + 16 + IPSize + " + (4 * i) + " */"));
}
heapWriter.WriteLine(allocImpl2(
dataName,
ctorName,
(RegAlloc.stackGcOffset + 12 + IPSize).ToString() + "/* stackGcOffset + 12 + IPSize */"));
for (int i = 0; i < sorted.Count; i++)
{
var formal = sorted[i];
iwriter.WriteLine(loadField(
dataName,
dataIs(ctorName),
formal.Name));
if (IsPtrType(app.AppType(formal.Type)))
{
iwriter.WriteLine("ensures HeapAbsData(heap, $absMem_old[abs]["
+ (3 + i) + "]) == Abs_" + TypeString(app.AppType(formal.Type))
+ "(" + formal.Name + (isSeq ? "_" : "#") + ctorName + "(data));");
iwriter.WriteLine("ensures HeapValue(objLayouts_old, true, $toAbs_old, r.regs[x], $absMem_old[abs]["
+ (3 + i) + "]);");
if (DafnySpec.IsArrayType(app.AppType(formal.Type)))
{
iwriter.WriteLine("ensures $absMem_old[abs][" + (3+i) + "] == " + formal.Name + "#" + ctorName + "(data).arrAbs;");
}
}
else
{
iwriter.WriteLine("ensures " + CompileBase.IntEqTyped(
app.AppType(formal.Type), formal.Name + (isSeq ? "_" : "#") + ctorName + "(data)", "r.regs[x]")
+ ";");
}
heapWriter.WriteLine("implementation loadField_" + dataName + "_" + formal.Name
+ "(my r_old:regs, const my core_state:core_state, const linear stk:mem, const linear statics:mem, const linear io:IOState, linear mems_old:mems, $commonVars:commonVars, $gcVars:gcVars, $toAbs:[int]int, $absMem:[int][int]int, $stacksFrames:[int]Frames, objLayouts:[int]ObjLayout, heap:Heap, x:int, y:opn_mem, data:"
+ dataName + ", abs:int, obj:int)");
heapWriter.WriteLine(" returns(my r:regs, linear mems:mems)");
heapWriter.WriteLine("{");
heapWriter.WriteLine(" assert THeapValue(objLayouts, true, $toAbs, obj, abs);");
heapWriter.WriteLine(" assert THeapInv($absMem, objLayouts, heap);");
heapWriter.WriteLine(" call r, mems := gcLoadField(r_old, core_state, stk, statics, io, mems_old, $commonVars, $gcVars, $absMem, $toAbs, $stacksFrames, objLayouts,");
heapWriter.WriteLine(" x, y, obj - 4, " + (3 + i) + ");");
heapWriter.WriteLine(" assert THeapValue(objLayouts, true, $toAbs, r.regs[x], $absMem[abs][" + (3 + i) + "]);");
heapWriter.WriteLine("}");
}
}
}