Andreas,
sorry for the delay. It takes me some time to get around the compiler code.
So this is what's happening (line numbers might be a bit off because of my changes):
1) the string "2147483648" is parsed and converted to an asQWORD (0x80000000). Since the 31st bit is set, this value is saved as a signed int64
compiler.cpp:9037 ctx->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), val);
(gdb) n
9043 ctx->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), val);
(gdb) n
9030 asCString value(&script->code[vnode->tokenPos], vnode->tokenLength);
(gdb) p ctx->type.GetConstantQW()
$28 = 2147483648
(gdb) p/x ctx->type.GetConstantQW()
$29 = 0x80000000
2) the operator ttMinus is applied and the value is now 0xffffffff80000000
compiler.cpp:10661 ctx->type.SetConstantQW(-(asINT64)ctx->type.GetConstantQW());
10666 else if( ctx->type.dataType.IsIntegerType() && ctx->type.dataType.GetSizeInMemoryDWords() == 2 )
(gdb)
10667 ctx->type.SetConstantQW(-(asINT64)ctx->type.GetConstantQW());
(gdb)
10678 return 0;
(gdb) p ctx->type.GetConstantQW()
$38 = 18446744071562067968
(gdb) p/x ctx->type.GetConstantQW()
$39 = 0xffffffff80000000
3) the assignment is evaluated and the value is implicitly converted to ttInt32. For that, in asCCompiler::ImplicitConversionConstant you just change the type from ttInt64 to ttInt. In a little endian system, nothing else needs to be done, since later, when you read the asDWORD from the union, you're going to read the right portion of the number. But in a big endian, you read the first half (0xffffffff).
What my patch tried to do, unsuccessfully, was to do the right conversion at ::ImplicitConversionConstant time, instead of just overwriting the variable type to the target's type right away.
Should I dig in deeper or do you think that's enough?