public static ABT.Expr GetPointerSubtraction(ABT.Expr ptr, ABT.Expr offset) {
if (ptr.Type.Kind != ABT.ExprTypeKind.POINTER) {
throw new InvalidOperationException("Error: expect a pointer");
}
if (offset.Type.Kind != ABT.ExprTypeKind.LONG) {
throw new InvalidOperationException("Error: expect an integer");
}
if (ptr.IsConstExpr && offset.IsConstExpr) {
Int32 baseAddressValue = (Int32)((ABT.ConstPtr)ptr).Value;
Int32 scaleFactorValue = ((ABT.PointerType)(ptr.Type)).RefType.SizeOf;
Int32 offsetValue = ((ABT.ConstLong)offset).Value;
return new ABT.ConstPtr((UInt32)(baseAddressValue - scaleFactorValue * offsetValue), ptr.Type, offset.Env);
}
return ABT.TypeCast.ToPointer(new ABT.Sub(
ABT.TypeCast.FromPointer(ptr, new ABT.LongType(ptr.Type.IsConst, ptr.Type.IsVolatile), ptr.Env),
new ABT.Multiply(
offset,
new ABT.ConstLong(((ABT.PointerType)(ptr.Type)).RefType.SizeOf, offset.Env)
)
), ptr.Type, offset.Env
);
}