Skip to content

Commit b234b40

Browse files
authored
Implement C long as 64-bit on POSIX (#1918)
* Implement C `long` as 64-bit on POSIX * Fix spelling
1 parent ec44e74 commit b234b40

22 files changed

+510
-368
lines changed

src/core/IronPython.Modules/ModuleOps.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ public static uint GetUnsignedInt(object value, object type) {
376376

377377
public static long GetSignedLong(object value, object type) {
378378
if (TryToIntStrict(value, out BigInteger bi)) {
379-
return unchecked((long)(ulong)(bi & uint.MaxValue));
379+
return unchecked((long)(ulong)(bi & (TypecodeOps.IsCLong32Bit ? uint.MaxValue : ulong.MaxValue)));
380380
}
381381

382382
if (PythonOps.TryGetBoundAttr(value, "_as_parameter_", out object asParam)) {
@@ -388,7 +388,7 @@ public static long GetSignedLong(object value, object type) {
388388

389389
public static ulong GetUnsignedLong(object value, object type) {
390390
if (TryToIntStrict(value, out BigInteger bi)) {
391-
return (ulong)(bi & uint.MaxValue);
391+
return (ulong)(bi & (TypecodeOps.IsCLong32Bit ? uint.MaxValue : ulong.MaxValue));
392392
}
393393

394394
if (PythonOps.TryGetBoundAttr(value, "_as_parameter_", out object asParam)) {

src/core/IronPython.Modules/_ctypes/SimpleType.cs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,11 @@ int INativeType.Size {
182182
return 2;
183183
case SimpleTypeKind.SignedInt:
184184
case SimpleTypeKind.UnsignedInt:
185-
case SimpleTypeKind.SignedLong:
186-
case SimpleTypeKind.UnsignedLong:
187185
case SimpleTypeKind.Single:
188186
return 4;
187+
case SimpleTypeKind.SignedLong:
188+
case SimpleTypeKind.UnsignedLong:
189+
return TypecodeOps.IsCLong32Bit ? 4 : 8;
189190
case SimpleTypeKind.UnsignedLongLong:
190191
case SimpleTypeKind.SignedLongLong:
191192
case SimpleTypeKind.Double:
@@ -220,8 +221,8 @@ object INativeType.GetValue(MemoryHolder/*!*/ owner, object readingFrom, int off
220221
case SimpleTypeKind.UnsignedShort: res = GetIntReturn((ushort)owner.ReadInt16(offset, _swap)); break;
221222
case SimpleTypeKind.SignedInt: res = GetIntReturn(owner.ReadInt32(offset, _swap)); break;
222223
case SimpleTypeKind.UnsignedInt: res = GetIntReturn((uint)owner.ReadInt32(offset, _swap)); break;
223-
case SimpleTypeKind.SignedLong: res = GetIntReturn(owner.ReadInt32(offset, _swap)); break;
224-
case SimpleTypeKind.UnsignedLong: res = GetIntReturn((uint)owner.ReadInt32(offset, _swap)); break;
224+
case SimpleTypeKind.SignedLong: if (TypecodeOps.IsCLong32Bit) goto case SimpleTypeKind.SignedInt; else goto case SimpleTypeKind.SignedLongLong;
225+
case SimpleTypeKind.UnsignedLong: if (TypecodeOps.IsCLong32Bit) goto case SimpleTypeKind.UnsignedInt; else goto case SimpleTypeKind.UnsignedLongLong;
225226
case SimpleTypeKind.SignedLongLong: res = GetIntReturn(owner.ReadInt64(offset, _swap)); break;
226227
case SimpleTypeKind.UnsignedLongLong: res = GetIntReturn((ulong)owner.ReadInt64(offset, _swap)); break;
227228
case SimpleTypeKind.Single: res = GetSingleReturn(owner.ReadInt32(offset, _swap)); break;
@@ -259,8 +260,20 @@ object INativeType.SetValue(MemoryHolder/*!*/ owner, int offset, object value) {
259260
case SimpleTypeKind.UnsignedShort: owner.WriteInt16(offset, unchecked((short)ModuleOps.GetUnsignedShort(value, this)), _swap); break;
260261
case SimpleTypeKind.SignedInt: owner.WriteInt32(offset, ModuleOps.GetSignedInt(value, this), _swap); break;
261262
case SimpleTypeKind.UnsignedInt: owner.WriteInt32(offset, unchecked((int)ModuleOps.GetUnsignedInt(value, this)), _swap); break;
262-
case SimpleTypeKind.SignedLong: owner.WriteInt32(offset, unchecked((int)ModuleOps.GetSignedLong(value, this)), _swap); break;
263-
case SimpleTypeKind.UnsignedLong: owner.WriteInt32(offset, unchecked((int)ModuleOps.GetUnsignedLong(value, this)), _swap); break;
263+
case SimpleTypeKind.SignedLong:
264+
if (TypecodeOps.IsCLong32Bit) {
265+
owner.WriteInt32(offset, unchecked((int)ModuleOps.GetSignedLong(value, this)), _swap);
266+
} else {
267+
owner.WriteInt64(offset, ModuleOps.GetSignedLong(value, this), _swap);
268+
}
269+
break;
270+
case SimpleTypeKind.UnsignedLong:
271+
if (TypecodeOps.IsCLong32Bit) {
272+
owner.WriteInt32(offset, unchecked((int)ModuleOps.GetUnsignedLong(value, this)), _swap);
273+
} else {
274+
owner.WriteInt64(offset, unchecked((long)ModuleOps.GetUnsignedLong(value, this)), _swap);
275+
}
276+
break;
264277
case SimpleTypeKind.UnsignedLongLong: owner.WriteInt64(offset, unchecked((long)ModuleOps.GetUnsignedLongLong(value, this)), _swap); break;
265278
case SimpleTypeKind.SignedLongLong: owner.WriteInt64(offset, ModuleOps.GetSignedLongLong(value, this), _swap); break;
266279
case SimpleTypeKind.Single: owner.WriteInt32(offset, ModuleOps.GetSingleBits(value), _swap); break;
@@ -301,11 +314,13 @@ object INativeType.SetValue(MemoryHolder/*!*/ owner, int offset, object value) {
301314
case SimpleTypeKind.UnsignedShort:
302315
return typeof(ushort);
303316
case SimpleTypeKind.SignedInt:
304-
case SimpleTypeKind.SignedLong:
305317
return typeof(int);
306318
case SimpleTypeKind.UnsignedInt:
307-
case SimpleTypeKind.UnsignedLong:
308319
return typeof(uint);
320+
case SimpleTypeKind.SignedLong:
321+
return TypecodeOps.IsCLong32Bit ? typeof(int) : typeof(long);
322+
case SimpleTypeKind.UnsignedLong:
323+
return TypecodeOps.IsCLong32Bit ? typeof(uint) : typeof(ulong);
309324
case SimpleTypeKind.SignedLongLong:
310325
return typeof(long);
311326
case SimpleTypeKind.UnsignedLongLong:
@@ -589,8 +604,9 @@ private Type GetPythonTypeWorker() {
589604
case SimpleTypeKind.SignedShort:
590605
case SimpleTypeKind.UnsignedShort:
591606
case SimpleTypeKind.SignedInt:
592-
case SimpleTypeKind.SignedLong:
593607
return typeof(int);
608+
case SimpleTypeKind.SignedLong:
609+
return TypecodeOps.IsCLong32Bit ? typeof(int) : typeof(object);
594610
case SimpleTypeKind.UnsignedInt:
595611
case SimpleTypeKind.UnsignedLong:
596612
case SimpleTypeKind.UnsignedLongLong:
@@ -618,7 +634,6 @@ void INativeType.EmitReverseMarshalling(ILGenerator method, LocalOrArg value, Li
618634
break;
619635
case SimpleTypeKind.Boolean:
620636
case SimpleTypeKind.SignedInt:
621-
case SimpleTypeKind.SignedLong:
622637
break;
623638
case SimpleTypeKind.Single:
624639
method.Emit(OpCodes.Conv_R8);
@@ -630,6 +645,10 @@ void INativeType.EmitReverseMarshalling(ILGenerator method, LocalOrArg value, Li
630645
case SimpleTypeKind.UnsignedLongLong:
631646
EmitUIntToObject(method, value);
632647
break;
648+
case SimpleTypeKind.SignedLong:
649+
if (TypecodeOps.IsCLong32Bit) break; // no conversion needed
650+
EmitInt64ToObject(method, value);
651+
break;
633652
case SimpleTypeKind.SignedLongLong:
634653
EmitInt64ToObject(method, value);
635654
break;

src/core/IronPython.Modules/_ctypes/_ctypes.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ public static int set_last_error(int errorCode) {
465465
}
466466

467467
public static int @sizeof(PythonType/*!*/ type) {
468-
if (!(type is INativeType simpleType)) {
468+
if (type is not INativeType simpleType) {
469469
throw PythonOps.TypeError("this type has no size");
470470
}
471471

src/core/IronPython.Modules/_struct.cs

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,25 @@ public void __init__(CodeContext/*!*/ context, object fmt) {
142142
break;
143143
case FormatType.UnsignedInt:
144144
for (int j = 0; j < curFormat.Count; j++) {
145-
WriteUInt(res, _isLittleEndian, GetULongValue(context, curObj++, values));
145+
WriteUInt(res, _isLittleEndian, GetUIntValue(context, curObj++, values));
146+
}
147+
break;
148+
case FormatType.Long:
149+
for (int j = 0; j < curFormat.Count; j++) {
150+
if (_isStandardized || TypecodeOps.IsCLong32Bit) {
151+
WriteInt(res, _isLittleEndian, GetIntValue(context, curObj++, values));
152+
} else {
153+
WriteLong(res, _isLittleEndian, GetLongValue(context, curObj++, values));
154+
}
146155
}
147156
break;
148157
case FormatType.UnsignedLong:
149158
for (int j = 0; j < curFormat.Count; j++) {
150-
WriteUInt(res, _isLittleEndian, GetULongValue(context, curObj++, values));
159+
if (_isStandardized || TypecodeOps.IsCLong32Bit) {
160+
WriteUInt(res, _isLittleEndian, GetUIntValue(context, curObj++, values));
161+
} else {
162+
WriteULong(res, _isLittleEndian, GetULongValue(context, curObj++, values));
163+
}
151164
}
152165
break;
153166
case FormatType.LongLong:
@@ -310,11 +323,28 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] IBufferProtocol/*!*/ b
310323
}
311324
break;
312325
case FormatType.UnsignedInt:
313-
case FormatType.UnsignedLong:
314326
for (int j = 0; j < curFormat.Count; j++) {
315327
res[res_idx++] = BigIntegerOps.__int__(CreateUIntValue(context, ref curIndex, _isLittleEndian, data));
316328
}
317329
break;
330+
case FormatType.Long:
331+
for (int j = 0; j < curFormat.Count; j++) {
332+
if (_isStandardized || TypecodeOps.IsCLong32Bit) {
333+
res[res_idx++] = CreateIntValue(context, ref curIndex, _isLittleEndian, data);
334+
} else {
335+
res[res_idx++] = BigIntegerOps.__int__(CreateLongValue(context, ref curIndex, _isLittleEndian, data));
336+
}
337+
}
338+
break;
339+
case FormatType.UnsignedLong:
340+
for (int j = 0; j < curFormat.Count; j++) {
341+
if (_isStandardized || TypecodeOps.IsCLong32Bit) {
342+
res[res_idx++] = BigIntegerOps.__int__(CreateUIntValue(context, ref curIndex, _isLittleEndian, data));
343+
} else {
344+
res[res_idx++] = BigIntegerOps.__int__(CreateULongValue(context, ref curIndex, _isLittleEndian, data));
345+
}
346+
}
347+
break;
318348
case FormatType.LongLong:
319349
for (int j = 0; j < curFormat.Count; j++) {
320350
res[res_idx++] = BigIntegerOps.__int__(CreateLongValue(context, ref curIndex, _isLittleEndian, data));
@@ -472,14 +502,17 @@ private static Struct CompileAndCache(CodeContext/*!*/ context, string/*!*/ fmt)
472502
count = 1;
473503
break;
474504
case 'i': // int
475-
case 'l': // long
476505
res.Add(new Format(FormatType.Int, count));
477506
count = 1;
478507
break;
479508
case 'I': // unsigned int
480509
res.Add(new Format(FormatType.UnsignedInt, count));
481510
count = 1;
482511
break;
512+
case 'l': // long
513+
res.Add(new Format(FormatType.Long, count));
514+
count = 1;
515+
break;
483516
case 'L': // unsigned long
484517
res.Add(new Format(FormatType.UnsignedLong, count));
485518
count = 1;
@@ -624,7 +657,7 @@ private void InitCountAndSize() {
624657
encodingSize = Align(encodingSize, format.NativeSize);
625658
}
626659

627-
encodingSize += GetNativeSize(format.Type) * format.Count;
660+
encodingSize += GetNativeSize(format.Type, _isStandardized) * format.Count;
628661
}
629662
_encodingCount = encodingCount;
630663
_encodingSize = encodingSize;
@@ -729,6 +762,7 @@ private enum FormatType {
729762

730763
Int,
731764
UnsignedInt,
765+
Long,
732766
UnsignedLong,
733767
Float,
734768

@@ -747,7 +781,7 @@ private enum FormatType {
747781
SizeT,
748782
}
749783

750-
private static int GetNativeSize(FormatType c) {
784+
private static int GetNativeSize(FormatType c, bool isStandardized) {
751785
switch (c) {
752786
case FormatType.Char:
753787
case FormatType.SignedChar:
@@ -765,11 +799,13 @@ private static int GetNativeSize(FormatType c) {
765799
return 2;
766800
case FormatType.Int:
767801
case FormatType.UnsignedInt:
768-
case FormatType.UnsignedLong:
769802
case FormatType.Float:
770803
case FormatType.SignedSizeT:
771804
case FormatType.SizeT:
772805
return 4;
806+
case FormatType.Long:
807+
case FormatType.UnsignedLong:
808+
return isStandardized || TypecodeOps.IsCLong32Bit ? 4 : 8;
773809
case FormatType.LongLong:
774810
case FormatType.UnsignedLongLong:
775811
case FormatType.Double:
@@ -786,16 +822,11 @@ private static int GetNativeSize(FormatType c) {
786822
/// <summary>
787823
/// Struct used to store the format and the number of times it should be repeated.
788824
/// </summary>
789-
private readonly struct Format {
790-
public readonly FormatType Type;
791-
public readonly int Count;
792-
793-
public Format(FormatType type, int count) {
794-
Type = type;
795-
Count = count;
796-
}
825+
private readonly struct Format(FormatType type, int count) {
826+
public readonly FormatType Type = type;
827+
public readonly int Count = count;
797828

798-
public int NativeSize => GetNativeSize(Type);
829+
public int NativeSize => GetNativeSize(Type, isStandardized: false);
799830
}
800831

801832
#endregion
@@ -1106,19 +1137,33 @@ internal static int GetIntValue(CodeContext/*!*/ context, int index, object[] ar
11061137
return res;
11071138
}
11081139

1109-
internal static uint GetULongValue(CodeContext/*!*/ context, int index, object[] args) {
1140+
internal static uint GetUIntValue(CodeContext/*!*/ context, int index, object[] args) {
11101141
BigInteger val = GetIntegerValue(context, index, args);
11111142
if (!val.AsUInt32(out uint res))
11121143
throw Error(context, "argument out of range");
11131144
return res;
11141145
}
11151146

1147+
internal static long GetLongValue(CodeContext/*!*/ context, int index, object[] args) {
1148+
BigInteger val = GetIntegerValue(context, index, args);
1149+
if (!val.AsInt64(out long res))
1150+
throw Error(context, "argument out of range");
1151+
return res;
1152+
}
1153+
1154+
internal static ulong GetULongValue(CodeContext/*!*/ context, int index, object[] args) {
1155+
BigInteger val = GetIntegerValue(context, index, args);
1156+
if (!val.AsUInt64(out ulong res))
1157+
throw Error(context, "argument out of range");
1158+
return res;
1159+
}
1160+
11161161
internal static int GetSignedSizeT(CodeContext/*!*/ context, int index, object[] args) {
11171162
return GetIntValue(context, index, args);
11181163
}
11191164

11201165
internal static uint GetSizeT(CodeContext/*!*/ context, int index, object[] args) {
1121-
return GetULongValue(context, index, args);
1166+
return GetUIntValue(context, index, args);
11221167
}
11231168

11241169
internal static ulong GetPointer(CodeContext/*!*/ context, int index, object[] args) {

0 commit comments

Comments
 (0)