}
-static int expression_text_mentions_64bit_symbol (const char *p) {
+static int current_token_is_64bit_integer_value_now (void) {
- char name[256];
- int depth = 0;
- int i;
+ struct local_symbol *sym;
+
+ if (tok.kind == TOK_CLLONG || tok.kind == TOK_CULLONG) {
+ return 1;
+ }
+
+ if (tok.kind != TOK_IDENT || !tok.ident) {
+ return 0;
+ }
+
+ sym = find_local_symbol (tok.ident);
+
+ if (sym) {
+ return sym->size == (DATA_LLONG & 0x1f) && !sym->is_floating;
+ }
+
+ if (find_global_symbol (tok.ident) >= 0) {
+ return get_global_symbol_size (tok.ident) == (DATA_LLONG & 0x1f) && !get_global_symbol_floating (tok.ident);
+ }
+
+ return 0;
+
+}
+
+static int current_expression_mentions_64bit_symbol_now (void) {
+
+ /*
+ * Keep this deliberately token based. The old source-text scan was too
+ * broad and could send ordinary runtime expressions through expr_const64(),
+ * which rejects valid code with "integer constant expression expected".
+ */
+ return current_token_is_64bit_integer_value_now ();
+
+}
+
+static int source_starts_long_long_cast_now (const char *p) {
+
+ int saw_long = 0;
if (!p) {
return 0;
}
- while (*p) {
+ while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
+ p++;
+ }
- if (*p == '(') {
+ if (*p != '(') {
+ return 0;
+ }
+
+ p++;
+
+ for (;;) {
+
+ char word[32];
+ int i = 0;
- depth++;
+ while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
p++;
-
- continue;
-
}
if (*p == ')') {
-
- if (depth <= 0) {
- return 0;
- }
-
- depth--;
- p++;
-
- continue;
-
+ return saw_long >= 2;
}
- if (*p == ';' || *p == '{' || *p == '}') {
+ if (!((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || *p == '_')) {
return 0;
}
- if ((unsigned char) *p == '_' || ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z'))) {
+ while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_') {
- i = 0;
-
- while ((unsigned char) *p == '_' || ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z')) || (*p >= '0' && *p <= '9')) {
-
- if (i + 1 < (int) sizeof (name)) {
- name[i++] = *p;
- }
-
- p++;
-
- }
-
- name[i] = 0;
-
- while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
- p++;
- }
-
- if (*p == '.' || (p[0] == '-' && p[1] == '>')) {
- continue;
- }
-
- {
-
- struct local_symbol *sym = find_local_symbol (name);
-
- if (sym && sym->size == (DATA_LLONG & 0x1f) && !sym->is_floating) {
- return 1;
- }
-
- }
-
- if (find_global_symbol (name) >= 0 && get_global_symbol_size (name) == (DATA_LLONG & 0x1f) && !get_global_symbol_floating (name)) {
- return 1;
+ if (i + 1 < (int) sizeof (word)) {
+ word[i++] = *p;
}
- continue;
+ p++;
}
- p++;
-
- }
-
- return 0;
-
-}
-
-static int current_expression_mentions_64bit_symbol_now (void) {
-
- if (expression_text_mentions_64bit_symbol (tok.start)) {
- return 1;
- }
+ word[i] = 0;
+
+ if (strcmp (word, "long") == 0) {
+ saw_long++;
+ } else if (strcmp (word, "signed") != 0 && strcmp (word, "unsigned") != 0) {
+ return 0;
+ }
- if (expression_text_mentions_64bit_symbol (tok.caret)) {
- return 1;
}
-
- return 0;
}
if (!state->ofp) {
return;
}
+
+ /*
+ * The i386 64-bit integer paths already carry the full value in hi:lo.
+ * A cast to long long/unsigned long long must not rebuild the high word
+ * from the low word here.
+ */
+ if ((size & 0x1f) == (DATA_LLONG & 0x1f)) {
+ return;
+ }
if (state->syntax & ASM_SYNTAX_INTEL) {
if (find_global_symbol (name) >= 0) {
- if (get_global_symbol_kind (name) == GLOBAL_SYMBOL_FUNCTION ||
+ if (get_global_symbol_size (name) == (DATA_LLONG & 0x1f) && !get_global_symbol_floating (name)) {
+ emit_load_global64_to_pair (lo, hi, name);
+ } else if (get_global_symbol_kind (name) == GLOBAL_SYMBOL_FUNCTION ||
get_global_symbol_array (name) ||
(!get_global_symbol_pointer_depth (name) &&
get_global_symbol_size (name) > (DATA_PTR & 0x1f))) {
* first string pointer instead of &table.
*/
emit_load_address_to_reg_now (lo, name);
+
if (state->ofp) {
if (state->syntax & ASM_SYNTAX_INTEL) {
}
- } else if (get_global_symbol_size (name) == (DATA_LLONG & 0x1f) && !get_global_symbol_floating (name)) {
- emit_load_global64_to_pair (lo, hi, name);
} else {
emit_load_global_to_reg_ex (lo, name, get_global_symbol_size (name), get_global_symbol_unsigned (name));
return 1;
}
- return current_argument_is_bare_64bit_identifier_now ();
+ if (current_argument_is_bare_64bit_identifier_now ()) {
+ return 1;
+ }
+
+ return source_starts_long_long_cast_now (tok.start) || source_starts_long_long_cast_now (tok.caret);
}
int true_label;
int end_label;
+ if (current_expression_mentions_64bit_symbol_now ()) {
+
+ const char *hi = (strcmp (reg, "edx") == 0) ? "ecx" : "edx";
+
+ emit_load_assignment_rhs_expression_to_pair (reg, hi, rhs_current_operand_is_unsigned_now ());
+ return;
+
+ }
+
if (rhs_current_operand_is_floating_now ()) {
emit_load_floating_rhs_expression_now (DATA_DOUBLE & 0x1f);