mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-07 13:39:43 +08:00
Use gdb_gmp for scalar arithmetic
This changes gdb to use scalar arithmetic for expression evaluation. I suspect this patch is not truly complete, as there may be code paths that still don't correctly handle 128-bit integers. However, many things do work now. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30190
This commit is contained in:
parent
d784fa8fb2
commit
303a881f87
2
gdb/NEWS
2
gdb/NEWS
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
*** Changes since GDB 13
|
*** Changes since GDB 13
|
||||||
|
|
||||||
|
* GDB now has some support for integer types larger than 64 bits.
|
||||||
|
|
||||||
* Removed targets and native configurations
|
* Removed targets and native configurations
|
||||||
|
|
||||||
GDB no longer supports AIX 4.x, AIX 5.x and AIX 6.x. The minimum supported
|
GDB no longer supports AIX 4.x, AIX 5.x and AIX 6.x. The minimum supported
|
||||||
|
65
gdb/testsuite/gdb.rust/onetwoeight.exp
Normal file
65
gdb/testsuite/gdb.rust/onetwoeight.exp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# Copyright (C) 2023 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Test expression parsing and evaluation that requires Rust compiler.
|
||||||
|
|
||||||
|
load_lib rust-support.exp
|
||||||
|
require allow_rust_tests
|
||||||
|
|
||||||
|
set v [split [rust_compiler_version] .]
|
||||||
|
if {[lindex $v 0] == 1 && [lindex $v 1] < 43} {
|
||||||
|
untested "128-bit ints require rust 1.43 or greater"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
standard_testfile .rs
|
||||||
|
if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug rust}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
set line [gdb_get_line_number "BREAK"]
|
||||||
|
if {![runto ${srcfile}:$line]} {
|
||||||
|
untested "could not run to breakpoint"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test "print x" " = 340282366920938463463374607431768211455"
|
||||||
|
gdb_test "print y" " = 170141183460469231731687303715884105727"
|
||||||
|
|
||||||
|
gdb_test "print x / 2" " = 170141183460469231731687303715884105727"
|
||||||
|
gdb_test "print sm * 2" " = 170141183460469231731687303715884105726"
|
||||||
|
gdb_test "print sm + sm" " = 170141183460469231731687303715884105726"
|
||||||
|
gdb_test "print x - y" " = 170141183460469231731687303715884105728"
|
||||||
|
gdb_test "print -y" " = -170141183460469231731687303715884105727"
|
||||||
|
gdb_test "print +y" " = 170141183460469231731687303715884105727"
|
||||||
|
|
||||||
|
gdb_test "print/x x" " = 0xffffffffffffffffffffffffffffffff"
|
||||||
|
gdb_test "print x % 4" " = 3"
|
||||||
|
gdb_test "print !x" " = 0"
|
||||||
|
|
||||||
|
gdb_test "print x < 0" " = false"
|
||||||
|
gdb_test "print -y < 0" " = true"
|
||||||
|
gdb_test "print x > y" " = true"
|
||||||
|
gdb_test "print y >= y" " = true"
|
||||||
|
gdb_test "print y <= y" " = true"
|
||||||
|
gdb_test "print y == y" " = true"
|
||||||
|
gdb_test "print x != y" " = true"
|
||||||
|
|
||||||
|
gdb_test "print sm << 2" "= 340282366920938463463374607431768211452"
|
||||||
|
gdb_test "print x >> 2" "= 85070591730234615865843651857942052863"
|
||||||
|
|
||||||
|
gdb_test "print/x x & mask" " = 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0"
|
||||||
|
gdb_test "print/x x ^ mask" " = 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"
|
||||||
|
gdb_test "print/x mask | (mask >> 4)" " = 0xffffffffffffffffffffffffffffffff"
|
31
gdb/testsuite/gdb.rust/onetwoeight.rs
Normal file
31
gdb/testsuite/gdb.rust/onetwoeight.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (C) 2023 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
#![allow(unused_assignments)]
|
||||||
|
|
||||||
|
|
||||||
|
fn empty() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main () {
|
||||||
|
let x : u128 = 340_282_366_920_938_463_463_374_607_431_768_211_455;
|
||||||
|
let sm : u128 = x /4;
|
||||||
|
let y : i128 = 170_141_183_460_469_231_731_687_303_715_884_105_727;
|
||||||
|
let mask : u128 = 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0;
|
||||||
|
|
||||||
|
empty(); // BREAK
|
||||||
|
}
|
30
gdb/utils.c
30
gdb/utils.c
@ -723,36 +723,6 @@ myread (int desc, char *addr, int len)
|
|||||||
return orglen;
|
return orglen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See utils.h. */
|
|
||||||
|
|
||||||
ULONGEST
|
|
||||||
uinteger_pow (ULONGEST v1, LONGEST v2)
|
|
||||||
{
|
|
||||||
if (v2 < 0)
|
|
||||||
{
|
|
||||||
if (v1 == 0)
|
|
||||||
error (_("Attempt to raise 0 to negative power."));
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The Russian Peasant's Algorithm. */
|
|
||||||
ULONGEST v;
|
|
||||||
|
|
||||||
v = 1;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (v2 & 1L)
|
|
||||||
v *= v1;
|
|
||||||
v2 >>= 1;
|
|
||||||
if (v2 == 0)
|
|
||||||
return v;
|
|
||||||
v1 *= v1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* An RAII class that sets up to handle input and then tears down
|
/* An RAII class that sets up to handle input and then tears down
|
||||||
|
@ -303,13 +303,6 @@ extern pid_t wait_to_die_with_timeout (pid_t pid, int *status, int timeout);
|
|||||||
|
|
||||||
extern int myread (int, char *, int);
|
extern int myread (int, char *, int);
|
||||||
|
|
||||||
/* Integer exponentiation: Return V1**V2, where both arguments
|
|
||||||
are integers.
|
|
||||||
|
|
||||||
Requires V1 != 0 if V2 < 0.
|
|
||||||
Returns 1 for 0 ** 0. */
|
|
||||||
extern ULONGEST uinteger_pow (ULONGEST v1, LONGEST v2);
|
|
||||||
|
|
||||||
/* Resource limits used by getrlimit and setrlimit. */
|
/* Resource limits used by getrlimit and setrlimit. */
|
||||||
|
|
||||||
enum resource_limit_kind
|
enum resource_limit_kind
|
||||||
|
467
gdb/valarith.c
467
gdb/valarith.c
@ -34,13 +34,6 @@ static struct value *value_subscripted_rvalue (struct value *array,
|
|||||||
LONGEST index,
|
LONGEST index,
|
||||||
LONGEST lowerbound);
|
LONGEST lowerbound);
|
||||||
|
|
||||||
/* Define whether or not the C operator '/' truncates towards zero for
|
|
||||||
differently signed operands (truncation direction is undefined in C). */
|
|
||||||
|
|
||||||
#ifndef TRUNCATION_TOWARDS_ZERO
|
|
||||||
#define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Given a pointer, return the size of its target.
|
/* Given a pointer, return the size of its target.
|
||||||
If the pointer type is void *, then return 1.
|
If the pointer type is void *, then return 1.
|
||||||
If the target type is incomplete, then error out.
|
If the target type is incomplete, then error out.
|
||||||
@ -726,36 +719,6 @@ value_concat (struct value *arg1, struct value *arg2)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Integer exponentiation: V1**V2, where both arguments are
|
|
||||||
integers. Requires V1 != 0 if V2 < 0. Returns 1 for 0 ** 0. */
|
|
||||||
|
|
||||||
static LONGEST
|
|
||||||
integer_pow (LONGEST v1, LONGEST v2)
|
|
||||||
{
|
|
||||||
if (v2 < 0)
|
|
||||||
{
|
|
||||||
if (v1 == 0)
|
|
||||||
error (_("Attempt to raise 0 to negative power."));
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The Russian Peasant's Algorithm. */
|
|
||||||
LONGEST v;
|
|
||||||
|
|
||||||
v = 1;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (v2 & 1L)
|
|
||||||
v *= v1;
|
|
||||||
v2 >>= 1;
|
|
||||||
if (v2 == 0)
|
|
||||||
return v;
|
|
||||||
v1 *= v1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Obtain argument values for binary operation, converting from
|
/* Obtain argument values for binary operation, converting from
|
||||||
other types if one of them is not floating point. */
|
other types if one of them is not floating point. */
|
||||||
@ -1099,33 +1062,39 @@ type_length_bits (type *type)
|
|||||||
both negative and too-large shift amounts, which are undefined, and
|
both negative and too-large shift amounts, which are undefined, and
|
||||||
would crash a GDB built with UBSan. Depending on the current
|
would crash a GDB built with UBSan. Depending on the current
|
||||||
language, if the shift is not valid, this either warns and returns
|
language, if the shift is not valid, this either warns and returns
|
||||||
false, or errors out. Returns true if valid. */
|
false, or errors out. Returns true and sets NBITS if valid. */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
check_valid_shift_count (enum exp_opcode op, type *result_type,
|
check_valid_shift_count (enum exp_opcode op, type *result_type,
|
||||||
type *shift_count_type, ULONGEST shift_count)
|
type *shift_count_type, const gdb_mpz &shift_count,
|
||||||
|
unsigned long &nbits)
|
||||||
{
|
{
|
||||||
if (!shift_count_type->is_unsigned () && (LONGEST) shift_count < 0)
|
if (!shift_count_type->is_unsigned ())
|
||||||
{
|
{
|
||||||
auto error_or_warning = [] (const char *msg)
|
LONGEST count = shift_count.as_integer<LONGEST> ();
|
||||||
{
|
if (count < 0)
|
||||||
/* Shifts by a negative amount are always an error in Go. Other
|
{
|
||||||
languages are more permissive and their compilers just warn or
|
auto error_or_warning = [] (const char *msg)
|
||||||
have modes to disable the errors. */
|
{
|
||||||
if (current_language->la_language == language_go)
|
/* Shifts by a negative amount are always an error in Go. Other
|
||||||
error (("%s"), msg);
|
languages are more permissive and their compilers just warn or
|
||||||
else
|
have modes to disable the errors. */
|
||||||
warning (("%s"), msg);
|
if (current_language->la_language == language_go)
|
||||||
};
|
error (("%s"), msg);
|
||||||
|
else
|
||||||
|
warning (("%s"), msg);
|
||||||
|
};
|
||||||
|
|
||||||
if (op == BINOP_RSH)
|
if (op == BINOP_RSH)
|
||||||
error_or_warning (_("right shift count is negative"));
|
error_or_warning (_("right shift count is negative"));
|
||||||
else
|
else
|
||||||
error_or_warning (_("left shift count is negative"));
|
error_or_warning (_("left shift count is negative"));
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shift_count >= type_length_bits (result_type))
|
nbits = shift_count.as_integer<unsigned long> ();
|
||||||
|
if (nbits >= type_length_bits (result_type))
|
||||||
{
|
{
|
||||||
/* In Go, shifting by large amounts is defined. Be silent and
|
/* In Go, shifting by large amounts is defined. Be silent and
|
||||||
still return false, as the caller's error path does the right
|
still return false, as the caller's error path does the right
|
||||||
@ -1249,283 +1218,127 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
|||||||
else
|
else
|
||||||
result_type = promotion_type (type1, type2);
|
result_type = promotion_type (type1, type2);
|
||||||
|
|
||||||
if (result_type->is_unsigned ())
|
gdb_mpz v1 = value_as_mpz (arg1);
|
||||||
|
gdb_mpz v2 = value_as_mpz (arg2);
|
||||||
|
gdb_mpz v;
|
||||||
|
|
||||||
|
switch (op)
|
||||||
{
|
{
|
||||||
LONGEST v2_signed = value_as_long (arg2);
|
case BINOP_ADD:
|
||||||
ULONGEST v1, v2, v = 0;
|
v = v1 + v2;
|
||||||
|
break;
|
||||||
|
|
||||||
v1 = (ULONGEST) value_as_long (arg1);
|
case BINOP_SUB:
|
||||||
v2 = (ULONGEST) v2_signed;
|
v = v1 - v2;
|
||||||
|
break;
|
||||||
|
|
||||||
switch (op)
|
case BINOP_MUL:
|
||||||
|
v = v1 * v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_DIV:
|
||||||
|
case BINOP_INTDIV:
|
||||||
|
if (v2.sgn () != 0)
|
||||||
|
v = v1 / v2;
|
||||||
|
else
|
||||||
|
error (_("Division by zero"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_EXP:
|
||||||
|
v = v1.pow (v2.as_integer<unsigned long> ());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_REM:
|
||||||
|
if (v2.sgn () != 0)
|
||||||
|
v = v1 % v2;
|
||||||
|
else
|
||||||
|
error (_("Division by zero"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_MOD:
|
||||||
|
/* Knuth 1.2.4, integer only. Note that unlike the C '%' op,
|
||||||
|
v1 mod 0 has a defined value, v1. */
|
||||||
|
if (v2.sgn () == 0)
|
||||||
{
|
{
|
||||||
case BINOP_ADD:
|
v = v1;
|
||||||
v = v1 + v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_SUB:
|
|
||||||
v = v1 - v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_MUL:
|
|
||||||
v = v1 * v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_DIV:
|
|
||||||
case BINOP_INTDIV:
|
|
||||||
if (v2 != 0)
|
|
||||||
v = v1 / v2;
|
|
||||||
else
|
|
||||||
error (_("Division by zero"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_EXP:
|
|
||||||
v = uinteger_pow (v1, v2_signed);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_REM:
|
|
||||||
if (v2 != 0)
|
|
||||||
v = v1 % v2;
|
|
||||||
else
|
|
||||||
error (_("Division by zero"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_MOD:
|
|
||||||
/* Knuth 1.2.4, integer only. Note that unlike the C '%' op,
|
|
||||||
v1 mod 0 has a defined value, v1. */
|
|
||||||
if (v2 == 0)
|
|
||||||
{
|
|
||||||
v = v1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v = v1 / v2;
|
|
||||||
/* Note floor(v1/v2) == v1/v2 for unsigned. */
|
|
||||||
v = v1 - (v2 * v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_LSH:
|
|
||||||
if (!check_valid_shift_count (op, result_type, type2, v2))
|
|
||||||
v = 0;
|
|
||||||
else
|
|
||||||
v = v1 << v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_RSH:
|
|
||||||
if (!check_valid_shift_count (op, result_type, type2, v2))
|
|
||||||
v = 0;
|
|
||||||
else
|
|
||||||
v = v1 >> v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_BITWISE_AND:
|
|
||||||
v = v1 & v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_BITWISE_IOR:
|
|
||||||
v = v1 | v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_BITWISE_XOR:
|
|
||||||
v = v1 ^ v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_MIN:
|
|
||||||
v = v1 < v2 ? v1 : v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_MAX:
|
|
||||||
v = v1 > v2 ? v1 : v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_EQUAL:
|
|
||||||
v = v1 == v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_NOTEQUAL:
|
|
||||||
v = v1 != v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_LESS:
|
|
||||||
v = v1 < v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_GTR:
|
|
||||||
v = v1 > v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_LEQ:
|
|
||||||
v = v1 <= v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_GEQ:
|
|
||||||
v = v1 >= v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
error (_("Invalid binary operation on numbers."));
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
val = value::allocate (result_type);
|
|
||||||
store_unsigned_integer (val->contents_raw ().data (),
|
|
||||||
val->type ()->length (),
|
|
||||||
type_byte_order (result_type),
|
|
||||||
v);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LONGEST v1, v2, v = 0;
|
|
||||||
|
|
||||||
v1 = value_as_long (arg1);
|
|
||||||
v2 = value_as_long (arg2);
|
|
||||||
|
|
||||||
switch (op)
|
|
||||||
{
|
{
|
||||||
case BINOP_ADD:
|
v = v1 / v2;
|
||||||
v = v1 + v2;
|
/* Note floor(v1/v2) == v1/v2 for unsigned. */
|
||||||
break;
|
v = v1 - (v2 * v);
|
||||||
|
|
||||||
case BINOP_SUB:
|
|
||||||
/* Avoid runtime error: signed integer overflow: \
|
|
||||||
0 - -9223372036854775808 cannot be represented in type
|
|
||||||
'long int'. */
|
|
||||||
v = (ULONGEST)v1 - (ULONGEST)v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_MUL:
|
|
||||||
v = v1 * v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_DIV:
|
|
||||||
case BINOP_INTDIV:
|
|
||||||
if (v2 != 0)
|
|
||||||
v = v1 / v2;
|
|
||||||
else
|
|
||||||
error (_("Division by zero"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_EXP:
|
|
||||||
v = integer_pow (v1, v2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_REM:
|
|
||||||
if (v2 != 0)
|
|
||||||
v = v1 % v2;
|
|
||||||
else
|
|
||||||
error (_("Division by zero"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_MOD:
|
|
||||||
/* Knuth 1.2.4, integer only. Note that unlike the C '%' op,
|
|
||||||
X mod 0 has a defined value, X. */
|
|
||||||
if (v2 == 0)
|
|
||||||
{
|
|
||||||
v = v1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v = v1 / v2;
|
|
||||||
/* Compute floor. */
|
|
||||||
if (TRUNCATION_TOWARDS_ZERO && (v < 0) && ((v1 % v2) != 0))
|
|
||||||
{
|
|
||||||
v--;
|
|
||||||
}
|
|
||||||
v = v1 - (v2 * v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_LSH:
|
|
||||||
if (!check_valid_shift_count (op, result_type, type2, v2))
|
|
||||||
v = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Cast to unsigned to avoid undefined behavior on
|
|
||||||
signed shift overflow (unless C++20 or later),
|
|
||||||
which would crash GDB when built with UBSan.
|
|
||||||
Note we don't warn on left signed shift overflow,
|
|
||||||
because starting with C++20, that is actually
|
|
||||||
defined behavior. Also, note GDB assumes 2's
|
|
||||||
complement throughout. */
|
|
||||||
v = (ULONGEST) v1 << v2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_RSH:
|
|
||||||
if (!check_valid_shift_count (op, result_type, type2, v2))
|
|
||||||
{
|
|
||||||
/* Pretend the too-large shift was decomposed in a
|
|
||||||
number of smaller shifts. An arithmetic signed
|
|
||||||
right shift of a negative number always yields -1
|
|
||||||
with such semantics. This is the right thing to
|
|
||||||
do for Go, and we might as well do it for
|
|
||||||
languages where it is undefined. Also, pretend a
|
|
||||||
shift by a negative number was a shift by the
|
|
||||||
negative number cast to unsigned, which is the
|
|
||||||
same as shifting by a too-large number. */
|
|
||||||
if (v1 < 0)
|
|
||||||
v = -1;
|
|
||||||
else
|
|
||||||
v = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
v = v1 >> v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_BITWISE_AND:
|
|
||||||
v = v1 & v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_BITWISE_IOR:
|
|
||||||
v = v1 | v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_BITWISE_XOR:
|
|
||||||
v = v1 ^ v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_MIN:
|
|
||||||
v = v1 < v2 ? v1 : v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_MAX:
|
|
||||||
v = v1 > v2 ? v1 : v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_EQUAL:
|
|
||||||
v = v1 == v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_NOTEQUAL:
|
|
||||||
v = v1 != v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_LESS:
|
|
||||||
v = v1 < v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_GTR:
|
|
||||||
v = v1 > v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_LEQ:
|
|
||||||
v = v1 <= v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BINOP_GEQ:
|
|
||||||
v = v1 >= v2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
error (_("Invalid binary operation on numbers."));
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
val = value::allocate (result_type);
|
case BINOP_LSH:
|
||||||
store_signed_integer (val->contents_raw ().data (),
|
{
|
||||||
val->type ()->length (),
|
unsigned long nbits;
|
||||||
type_byte_order (result_type),
|
if (!check_valid_shift_count (op, result_type, type2, v2, nbits))
|
||||||
v);
|
v = 0;
|
||||||
|
else
|
||||||
|
v = v1 << nbits;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_RSH:
|
||||||
|
{
|
||||||
|
unsigned long nbits;
|
||||||
|
if (!check_valid_shift_count (op, result_type, type2, v2, nbits))
|
||||||
|
v = 0;
|
||||||
|
else
|
||||||
|
v = v1 >> nbits;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_BITWISE_AND:
|
||||||
|
v = v1 & v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_BITWISE_IOR:
|
||||||
|
v = v1 | v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_BITWISE_XOR:
|
||||||
|
v = v1 ^ v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_MIN:
|
||||||
|
v = v1 < v2 ? v1 : v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_MAX:
|
||||||
|
v = v1 > v2 ? v1 : v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_EQUAL:
|
||||||
|
v = v1 == v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_NOTEQUAL:
|
||||||
|
v = v1 != v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_LESS:
|
||||||
|
v = v1 < v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_GTR:
|
||||||
|
v = v1 > v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_LEQ:
|
||||||
|
v = v1 <= v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BINOP_GEQ:
|
||||||
|
v = v1 >= v2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error (_("Invalid binary operation on numbers."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val = value_from_mpz (result_type, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
@ -1944,7 +1757,11 @@ value_complement (struct value *arg1)
|
|||||||
type = check_typedef (arg1->type ());
|
type = check_typedef (arg1->type ());
|
||||||
|
|
||||||
if (is_integral_type (type))
|
if (is_integral_type (type))
|
||||||
val = value_from_longest (type, ~value_as_long (arg1));
|
{
|
||||||
|
gdb_mpz num = value_as_mpz (arg1);
|
||||||
|
num.complement ();
|
||||||
|
val = value_from_mpz (type, num);
|
||||||
|
}
|
||||||
else if (type->code () == TYPE_CODE_ARRAY && type->is_vector ())
|
else if (type->code () == TYPE_CODE_ARRAY && type->is_vector ())
|
||||||
{
|
{
|
||||||
struct type *eltype = check_typedef (type->target_type ());
|
struct type *eltype = check_typedef (type->target_type ());
|
||||||
|
14
gdb/valops.c
14
gdb/valops.c
@ -570,7 +570,7 @@ value_cast (struct type *type, struct value *arg2)
|
|||||||
&& (scalar || code2 == TYPE_CODE_PTR
|
&& (scalar || code2 == TYPE_CODE_PTR
|
||||||
|| code2 == TYPE_CODE_MEMBERPTR))
|
|| code2 == TYPE_CODE_MEMBERPTR))
|
||||||
{
|
{
|
||||||
LONGEST longest;
|
gdb_mpz longest;
|
||||||
|
|
||||||
/* When we cast pointers to integers, we mustn't use
|
/* When we cast pointers to integers, we mustn't use
|
||||||
gdbarch_pointer_to_address to find the address the pointer
|
gdbarch_pointer_to_address to find the address the pointer
|
||||||
@ -579,12 +579,14 @@ value_cast (struct type *type, struct value *arg2)
|
|||||||
sees a cast as a simple reinterpretation of the pointer's
|
sees a cast as a simple reinterpretation of the pointer's
|
||||||
bits. */
|
bits. */
|
||||||
if (code2 == TYPE_CODE_PTR)
|
if (code2 == TYPE_CODE_PTR)
|
||||||
longest = extract_unsigned_integer
|
longest = extract_unsigned_integer (arg2->contents (),
|
||||||
(arg2->contents (), type_byte_order (type2));
|
type_byte_order (type2));
|
||||||
else
|
else
|
||||||
longest = value_as_long (arg2);
|
longest = value_as_mpz (arg2);
|
||||||
return value_from_longest (to_type, convert_to_boolean ?
|
if (convert_to_boolean)
|
||||||
(LONGEST) (longest ? 1 : 0) : longest);
|
longest = bool (longest);
|
||||||
|
|
||||||
|
return value_from_mpz (to_type, longest);
|
||||||
}
|
}
|
||||||
else if (code1 == TYPE_CODE_PTR && (code2 == TYPE_CODE_INT
|
else if (code1 == TYPE_CODE_PTR && (code2 == TYPE_CODE_INT
|
||||||
|| code2 == TYPE_CODE_ENUM
|
|| code2 == TYPE_CODE_ENUM
|
||||||
|
Loading…
Reference in New Issue
Block a user