public override ArmadaRValue GetRValue(IToken tok, ResolutionContext context) { var top = context.GetRValueTopStackFrame(); var correct_frame_type = AH.MakeExprDotName(top, $"Armada_StackFrame_{methodName}?", new BoolType()); var crashAvoidance = new UndefinedBehaviorAvoidanceConstraint(correct_frame_type); var addr = AH.MakeExprDotName(top, $"{methodName}'AddrOf'{name}", new PointerType(ty)); var h = context.GetRValueHeap(); var valid = AH.GetInvocationOfValidPointer(h, addr, ty); if (valid == null) { context.Fail(tok, "Type {ty} is not supported on the heap, and thus not for addressable stack variables either"); return(null); } crashAvoidance.Add(valid); var val = AH.GetInvocationOfDereferencePointer(h, addr, ty); if (val == null) { context.Fail(tok, "Type {ty} is not supported on the heap, and thus not for addressable stack variables either"); } return(new ArmadaRValue(crashAvoidance, val)); }
public override ArmadaLValue ApplySeqSelect(IToken i_tok, ResolutionContext context, ArmadaRValue idx1, Type ty) { if (!(type is SizedArrayType)) { context.Fail(i_tok, "Attempt to obtain element of non-array type"); return(null); } SizedArrayType st = (SizedArrayType)type; if (!AH.TypesMatch(st.Range, ty)) { context.Fail(i_tok, $"Element of type {st.Range} used as type {ty}"); return(null); } var crashAvoidance = address.UndefinedBehaviorAvoidance + idx1.UndefinedBehaviorAvoidance; var s = context.GetLValueState(); var mem = AH.MakeExprDotName(s, "mem", "Armada_SharedMemory"); var h = AH.MakeExprDotName(mem, "heap", "Armada_Heap"); var tree = AH.MakeExprDotName(h, "tree", "Armada_Tree"); crashAvoidance.Add(AH.MakeInExpr(address.Val, tree)); var node = AH.MakeSeqSelectExpr(tree, address.Val, "Armada_Node"); var children = AH.MakeExprDotName(node, "children", AH.MakeChildrenType()); var idx1_as_int = AH.ConvertToIntIfNotInt(idx1.Val); var field = AH.MakeApply1("Armada_FieldArrayIndex", idx1_as_int, "Armada_Field"); var child = AH.MakeSeqSelectExpr(children, field, new PointerType(st.Range)); crashAvoidance.Add(AH.MakeInExpr(field, children)); return(new AddressableArmadaLValue(i_tok, st.Range, new ArmadaRValue(crashAvoidance, child))); }
public override ArmadaRValue GetRValue(IToken tok, ResolutionContext context) { var s = context.GetRValueState(); var addrs = AH.MakeExprDotName(s, "addrs", "Armada_Addrs"); var addr = AH.MakeExprDotName(addrs, name, new PointerType(ty)); var h = context.GetRValueHeap(); var valid = AH.GetInvocationOfValidPointer(h, addr, ty); if (valid == null) { context.Fail(tok, "Type {ty} is currently not supported in the heap"); return(null); } var crashAvoidance = new UndefinedBehaviorAvoidanceConstraint(valid); var val = AH.GetInvocationOfDereferencePointer(h, addr, ty); if (val == null) { context.Fail(tok, "Type {ty} is currently not supported in the heap"); } return(new ArmadaRValue(crashAvoidance, val)); }
public override ArmadaLValue ApplyExprDotName(IToken i_tok, ResolutionContext context, string fieldName, Type ty) { if (!(type is UserDefinedType)) { context.Fail(i_tok, $"Attempt to take a field ({fieldName}) of non-struct, non-datatype type {type}"); return(null); } UserDefinedType ut = (UserDefinedType)type; if (context.symbols.DoesStructExist(ut.Name)) { Type fieldType = context.symbols.GetStructFieldType(ut.Name, fieldName); if (fieldType == null) { context.Fail(i_tok, $"Attempt to take non-existent field ({fieldName}) in struct type {ut.Name}"); return(null); } if (!AH.TypesMatch(fieldType, ty)) { context.Fail(i_tok, $"Field {fieldName} of type {fieldType} used as type {ty}"); return(null); } } return(new UnaddressableFieldArmadaLValue(i_tok, ty, this, crashAvoidance, fieldName, false)); }
public override ArmadaLValue ApplySeqSelect(IToken i_tok, ResolutionContext context, ArmadaRValue idx1, Type indexType, Type exprType) { if (!(type is SizedArrayType)) { context.Fail(i_tok, "Attempt to obtain element of non-array type"); return(null); } SizedArrayType st = (SizedArrayType)type; if (!AH.TypesMatch(st.Range, exprType)) { context.Fail(i_tok, $"Element of type {st.Range} used as type {exprType}"); return(null); } var crashAvoidance = address.UndefinedBehaviorAvoidance + idx1.UndefinedBehaviorAvoidance; var s = context.GetLValueState(); var h = $"({s}).mem.heap"; var idx1_as_int = AH.ConvertToIntIfNotInt(idx1.Val, indexType); crashAvoidance.Add($"{address.Val} in {h}.tree"); crashAvoidance.Add($"0 <= {idx1_as_int} < |{h}.tree[{address.Val}].children|"); var child = $"{h}.tree[{address.Val}].children[{idx1_as_int}]"; return(new AddressableArmadaLValue(i_tok, st.Range, new ArmadaRValue(crashAvoidance, child))); }
public override ArmadaLValue ApplyExprDotName(IToken i_tok, ResolutionContext context, string fieldName, Type ty) { if (!(type is UserDefinedType)) { context.Fail(i_tok, $"Attempt to take a field ({fieldName}) of non-struct type {type}"); return(null); } UserDefinedType ut = (UserDefinedType)type; if (!context.symbols.DoesStructExist(ut.Name)) { context.Fail(i_tok, $"Attempt to take a field ({fieldName}) of non struct type {ut.Name}"); return(null); } Type fieldType = context.symbols.GetStructFieldType(ut.Name, fieldName); if (fieldType == null) { context.Fail(i_tok, $"Attempt to take non-existent field ({fieldName}) in struct type {ut.Name}"); return(null); } if (!AH.TypesMatch(fieldType, ty)) { context.Fail(i_tok, $"Field {fieldName} of type {fieldType} used as type {ty}"); return(null); } var crashAvoidance = address.UndefinedBehaviorAvoidance; var s = context.GetLValueState(); var mem = AH.MakeExprDotName(s, "mem", "Armada_SharedMemory"); var h = AH.MakeExprDotName(mem, "heap", "Armada_Heap"); var tree = AH.MakeExprDotName(h, "tree", "Armada_Tree"); crashAvoidance.Add(AH.MakeInExpr(address.Val, tree)); var node = AH.MakeSeqSelectExpr(tree, address.Val, "Armada_Node"); var children = AH.MakeExprDotName(node, "children", AH.MakeChildrenType()); var field = AH.MakeApply1("Armada_FieldStruct", AH.MakeNameSegment($"Armada_FieldType_{ut.Name}'{fieldName}", "Armada_FieldType"), "Armada_Field"); var child = AH.MakeSeqSelectExpr(children, field, new PointerType(fieldType)); crashAvoidance.Add(AH.MakeInExpr(field, children)); return(new AddressableArmadaLValue(i_tok, fieldType, new ArmadaRValue(crashAvoidance, child))); }
public override ArmadaRValue GetRValue(IToken tok, ResolutionContext context) { var addr = $"({context.GetRValueState()}).addrs.{name}"; var h = context.GetRValueHeap(); var valid = AH.GetInvocationOfValidPointer(h, addr, ty); if (valid == null) { context.Fail(tok, $"Type {ty} is currently not supported in the heap"); return(null); } var crashAvoidance = new UndefinedBehaviorAvoidanceConstraint(valid); var val = AH.GetInvocationOfDereferencePointer(h, addr, ty); if (val == null) { context.Fail(tok, $"Type {ty} is currently not supported in the heap"); } return(new ArmadaRValue(crashAvoidance, val)); }
public override ArmadaLValue ApplySeqSelect(IToken i_tok, ResolutionContext context, ArmadaRValue idx1, Type indexType, Type exprType) { var me = GetValueInLValueState(context); var sz = $"|{me}|"; var newUndefinedBehaviorAvoidance = GetUndefinedBehaviorAvoidanceConstraint() + idx1.UndefinedBehaviorAvoidance; var idx1val = AH.ConvertToIntIfNotInt(idx1.Val, indexType); if (type is SizedArrayType) { SizedArrayType st = (SizedArrayType)type; if (!AH.TypesMatch(st.Range, exprType)) { context.Fail(i_tok, $"Element of type {st.Range} used as type {exprType}"); return(null); } newUndefinedBehaviorAvoidance.Add($"0 <= {idx1val} < {sz}"); } else if (type is SeqType) { newUndefinedBehaviorAvoidance.Add($"0 <= {idx1val} < {sz}"); } else if (type is MapType) { // There's no need to consider it undefined behavior if idx1.Val isn't in this map, since we're just // using it as an lvalue. It's fine to update an element of a map that isn't yet in its domain. // So we don't need to do: // newUndefinedBehaviorAvoidance.Add($"({idx1.Val}) in ({me})"); return(new UnaddressableIndexArmadaLValue(i_tok, exprType, this, newUndefinedBehaviorAvoidance, idx1.Val)); } else { context.Fail(i_tok, $"Attempt to index into something that isn't an array, seq, or map"); return(null); } return(new UnaddressableIndexArmadaLValue(i_tok, exprType, this, newUndefinedBehaviorAvoidance, idx1val)); }
public override ArmadaLValue ApplyExprDotName(IToken i_tok, ResolutionContext context, string fieldName, Type targetType) { if (!(type is UserDefinedType)) { context.Fail(i_tok, $"Attempt to take a field ({fieldName}) of non-struct type {type}"); return(null); } UserDefinedType ut = (UserDefinedType)type; if (!context.symbols.DoesStructExist(ut.Name)) { context.Fail(i_tok, $"Attempt to take a field ({fieldName}) of non struct type {ut.Name}"); return(null); } Type fieldType = context.symbols.GetStructFieldType(ut.Name, fieldName); if (fieldType == null) { context.Fail(i_tok, $"Attempt to take non-existent field ({fieldName}) in struct type {ut.Name}"); return(null); } if (!AH.TypesMatch(fieldType, targetType)) { context.Fail(i_tok, $"Field {fieldName} of type {fieldType} used as type {targetType}"); return(null); } var crashAvoidance = address.UndefinedBehaviorAvoidance; var s = context.GetLValueState(); var h = $"({s}).mem.heap"; int fieldPos = context.symbols.GetStructFieldPos(ut.Name, fieldName); crashAvoidance.Add($"{address.Val} in {h}.tree"); crashAvoidance.Add($"0 <= {fieldPos} < |{h}.tree[{address.Val}].children|"); var child = $"{h}.tree[{address.Val}].children[{fieldPos}]"; return(new AddressableArmadaLValue(i_tok, fieldType, new ArmadaRValue(crashAvoidance, child))); }
public override ArmadaLValue ApplySeqSelect(IToken i_tok, ResolutionContext context, ArmadaRValue idx1, Type ty) { var me = GetValueInLValueState(context); var sz = AH.MakeCardinalityExpr(me); var newUndefinedBehaviorAvoidance = GetUndefinedBehaviorAvoidanceConstraint() + idx1.UndefinedBehaviorAvoidance; var idx1val = AH.ConvertToIntIfNotInt(idx1.Val); if (type is SizedArrayType) { SizedArrayType st = (SizedArrayType)type; if (!AH.TypesMatch(st.Range, ty)) { context.Fail(i_tok, $"Element of type {st.Range} used as type {ty}"); return(null); } newUndefinedBehaviorAvoidance.Add(AH.MakeLeExpr(AH.MakeZero(), idx1val)); newUndefinedBehaviorAvoidance.Add(AH.MakeLtExpr(idx1val, sz)); } else if (type is SeqType) { newUndefinedBehaviorAvoidance.Add(AH.MakeLeExpr(AH.MakeZero(), idx1val)); newUndefinedBehaviorAvoidance.Add(AH.MakeLtExpr(idx1val, sz)); } else if (type is MapType) { newUndefinedBehaviorAvoidance.Add(AH.MakeInExpr(idx1val, me)); } else { context.Fail(i_tok, $"Attempt to index into something that isn't an array, seq, or map"); return(null); } return(new UnaddressableIndexArmadaLValue(i_tok, ty, this, newUndefinedBehaviorAvoidance, idx1val)); }
public override ArmadaRValue GetRValue(IToken tok, ResolutionContext context) { var crashAvoidance = new UndefinedBehaviorAvoidanceConstraint(); var addr = $"({context.GetRValueTopStackFrame()}).{methodName}.AddrOf'{name}"; var h = context.GetRValueHeap(); var valid = AH.GetInvocationOfValidPointer(h, addr, ty); if (valid == null) { context.Fail(tok, $"Type {ty} is not supported on the heap, and thus not for addressable stack variables either"); return(null); } crashAvoidance.Add(valid); var val = AH.GetInvocationOfDereferencePointer(h, addr, ty); if (val == null) { context.Fail(tok, $"Type {ty} is not supported on the heap, and thus not for addressable stack variables either"); } return(new ArmadaRValue(crashAvoidance, val)); }
public Expression UpdateTotalStateWithStoreBufferEntry(ResolutionContext context, IConstraintCollector constraintCollector, Expression val_new) { if (NoTSO()) { return(UpdateTotalStateLocationDirectly(context, constraintCollector, val_new)); } if (!AH.IsPrimitiveType(type)) { context.Fail(tok, "Can't do TSO write to non-primitive type; try using ::= instead of :="); return(null); } var entry = GetStoreBufferEntry(val_new); if (entry == null) { context.Fail(tok, "Can't do a TSO write to that location; try using ::= instead of :="); return(null); } return(AH.MakeApply3("Armada_AppendToThreadStoreBuffer", context.GetLValueState(), context.tid, entry, "Armada_TotalState")); }
public string UpdateTotalStateWithStoreBufferEntry(ResolutionContext context, IConstraintCollector constraintCollector, string val_new, ArmadaPC pc) { if (NoTSO()) { return(UpdateTotalStateLocationDirectly(context, constraintCollector, val_new)); } if (!AH.IsPrimitiveType(type)) { context.Fail(tok, "Can't do TSO write to non-primitive type; try using ::= instead of :="); return(null); } var entry = GetStoreBufferEntry(val_new, pc); if (entry == null) { context.Fail(tok, "Can't do a TSO write to that location; try using ::= instead of :="); return(null); } return($"Armada_AppendToThreadStoreBuffer({context.GetLValueState()}, {context.tid}, {entry})"); }
public virtual Expression GetValueInLValueState(ResolutionContext context) { context.Fail("Internal error: GetValueInLValueState not supported"); return(null); }