From adaa9cf052efad5fee03fffb26f4aef3a6bfcd8b Mon Sep 17 00:00:00 2001 From: collison Date: Tue, 10 Mar 2015 07:10:56 +0000 Subject: 2015-03-10 Michael Collison Backport from trunk r217852. 2014-11-20 Tejas Belagod * config/aarch64/aarch64-protos.h (aarch64_classify_symbol): Fixup prototype. * config/aarch64/aarch64.c (aarch64_expand_mov_immediate, aarch64_cannot_force_const_mem, aarch64_classify_address, aarch64_classify_symbolic_expression): Fixup call to aarch64_classify_symbol. (aarch64_classify_symbol): Add range-checking for symbol + offset addressing for tiny and small models. 2015-03-10 Michael Collison Backport from trunk r217852. 2014-11-20 Tejas Belagod * gcc.target/aarch64/symbol-range.c: New. * gcc.target/aarch64/symbol-range-tiny.c: New. git-svn-id: svn://gcc.gnu.org/svn/gcc/branches/linaro/gcc-4_9-branch@221300 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/config/aarch64/aarch64-protos.h | 2 +- gcc/config/aarch64/aarch64.c | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'gcc/config') diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 379df12031f..b0e5a31e3e7 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -216,7 +216,7 @@ bool aarch64_uimm12_shift (HOST_WIDE_INT); const char *aarch64_output_casesi (rtx *); const char *aarch64_rewrite_selected_cpu (const char *name); -enum aarch64_symbol_type aarch64_classify_symbol (rtx, +enum aarch64_symbol_type aarch64_classify_symbol (rtx, rtx, enum aarch64_symbol_context); enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx); enum reg_class aarch64_regno_regclass (unsigned); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index eb4554bdd83..4bbcca74eb9 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1324,7 +1324,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) before we start classifying the symbol. */ split_const (imm, &base, &offset); - sty = aarch64_classify_symbol (base, SYMBOL_CONTEXT_ADR); + sty = aarch64_classify_symbol (base, offset, SYMBOL_CONTEXT_ADR); switch (sty) { case SYMBOL_FORCE_TO_MEM: @@ -2994,7 +2994,7 @@ aarch64_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) split_const (x, &base, &offset); if (GET_CODE (base) == SYMBOL_REF || GET_CODE (base) == LABEL_REF) { - if (aarch64_classify_symbol (base, SYMBOL_CONTEXT_ADR) + if (aarch64_classify_symbol (base, offset, SYMBOL_CONTEXT_ADR) != SYMBOL_FORCE_TO_MEM) return true; else @@ -3408,7 +3408,7 @@ aarch64_classify_address (struct aarch64_address_info *info, rtx sym, offs; split_const (info->offset, &sym, &offs); if (GET_CODE (sym) == SYMBOL_REF - && (aarch64_classify_symbol (sym, SYMBOL_CONTEXT_MEM) + && (aarch64_classify_symbol (sym, offs, SYMBOL_CONTEXT_MEM) == SYMBOL_SMALL_ABSOLUTE)) { /* The symbol and offset must be aligned to the access size. */ @@ -3465,7 +3465,7 @@ aarch64_classify_symbolic_expression (rtx x, rtx offset; split_const (x, &x, &offset); - return aarch64_classify_symbol (x, context); + return aarch64_classify_symbol (x, offset, context); } @@ -6607,7 +6607,7 @@ aarch64_classify_tls_symbol (rtx x) LABEL_REF X in context CONTEXT. */ enum aarch64_symbol_type -aarch64_classify_symbol (rtx x, +aarch64_classify_symbol (rtx x, rtx offset, enum aarch64_symbol_context context ATTRIBUTE_UNUSED) { if (GET_CODE (x) == LABEL_REF) @@ -6641,12 +6641,25 @@ aarch64_classify_symbol (rtx x, switch (aarch64_cmodel) { case AARCH64_CMODEL_TINY: - if (SYMBOL_REF_WEAK (x)) + /* When we retreive symbol + offset address, we have to make sure + the offset does not cause overflow of the final address. But + we have no way of knowing the address of symbol at compile time + so we can't accurately say if the distance between the PC and + symbol + offset is outside the addressible range of +/-1M in the + TINY code model. So we rely on images not being greater than + 1M and cap the offset at 1M and anything beyond 1M will have to + be loaded using an alternative mechanism. */ + if (SYMBOL_REF_WEAK (x) + || INTVAL (offset) < -1048575 || INTVAL (offset) > 1048575) return SYMBOL_FORCE_TO_MEM; return SYMBOL_TINY_ABSOLUTE; case AARCH64_CMODEL_SMALL: - if (SYMBOL_REF_WEAK (x)) + /* Same reasoning as the tiny code model, but the offset cap here is + 4G. */ + if (SYMBOL_REF_WEAK (x) + || INTVAL (offset) < (HOST_WIDE_INT) -4294967263 + || INTVAL (offset) > (HOST_WIDE_INT) 4294967264) return SYMBOL_FORCE_TO_MEM; return SYMBOL_SMALL_ABSOLUTE; -- cgit v1.2.3