From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id 2C9EA3858D28 for ; Fri, 19 Aug 2022 01:31:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2C9EA3858D28 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=loongson.cn Received: from localhost.localdomain (unknown [117.136.87.65]) by localhost.localdomain (Coremail) with SMTP id AQAAf8CxYOL55_5iikYEAA--.22252S2; Fri, 19 Aug 2022 09:31:39 +0800 (CST) From: Tiezhu Yang To: gdb-patches@sourceware.org Subject: [COMMITTED PATCH] gdb: LoongArch: Handle variadic arguments Date: Fri, 19 Aug 2022 09:31:22 +0800 Message-Id: <20220819013122.4673-1-yangtiezhu@loongson.cn> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CM-TRANSID: AQAAf8CxYOL55_5iikYEAA--.22252S2 X-Coremail-Antispam: 1UD129KBjvJXoW3XrWxZFyxZw47Jw13CF1xKrg_yoWxKrWfpF W3CFnxAF4rXw43twnrJan8XFWxA3y8tw1jyF4Yyry0kan8Gwn2qF1rC3WYvFyUWr18XFW2 vanaqa43AF45JaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUyqb7Iv0xC_Kw4lb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I2 0VC2zVCF04k26cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rw A2F7IY1VAKz4vEj48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xII jxv20xvEc7CjxVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4 vEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40E FcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr 0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JMxAIw28IcxkI7VAKI48J MxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwV AFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUJVWUXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv2 0xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAIw20EY4 v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AK xVWUJVW8JbIYCTnIWIevJa73UjIFyTuYvjxUgg_TUUUUU X-CM-SenderInfo: p1dqw3xlh2x3gn0dqz5rrqw2lrqou0/ X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 Aug 2022 01:31:45 -0000 According to LoongArch ELF ABI specification [1], variadic arguments are passed in GARs in the same manner as named arguments. And after a variadic argument has been passed on the stack, all future arguments will also be passed on the stack, i.e., the last argument register may be left unused due to the aligned register pair rule. long double data tpye is passed in an aligned GAR pair, the first register in the pair is even-numbered. [1] https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html Signed-off-by: Tiezhu Yang --- gdb/loongarch-tdep.c | 105 +++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 29 deletions(-) diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c index e63ff01854d..71a2cfb0d86 100644 --- a/gdb/loongarch-tdep.c +++ b/gdb/loongarch-tdep.c @@ -570,6 +570,8 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, size_t len = TYPE_LENGTH (type); int align = type_align (type); enum type_code code = type->code (); + struct type *func_type = check_typedef (value_type (function)); + bool varargs = (func_type->has_varargs () && i >= func_type->num_fields ()); switch (code) { @@ -606,26 +608,63 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, case TYPE_CODE_FLT: if (len == 2 * regsize) { - /* long double type is passed in a pair of GAR, - with the low-order GRLEN bits in the lower-numbered register - and the high-order GRLEN bits in the higher-numbered register. - If exactly one register is available, - the low-order GRLEN bits are passed in the register - and the high-order GRLEN bits are passed on the stack. - If no GAR is available, it's passed on the stack. */ - if (gar >= 2) + if (!varargs) { - pass_in_gar (regcache, gar--, val); - pass_in_gar (regcache, gar--, val + regsize); - } - else if (gar == 1) - { - pass_in_gar (regcache, gar--, val); - pass_on_stack (regcache, val + regsize, len - regsize, align, &addr); + /* long double type is passed in a pair of GAR, + with the low-order GRLEN bits in the lower-numbered register + and the high-order GRLEN bits in the higher-numbered register. + If exactly one register is available, + the low-order GRLEN bits are passed in the register + and the high-order GRLEN bits are passed on the stack. + If no GAR is available, it's passed on the stack. */ + if (gar >= 2) + { + pass_in_gar (regcache, gar--, val); + pass_in_gar (regcache, gar--, val + regsize); + } + else if (gar == 1) + { + pass_in_gar (regcache, gar--, val); + pass_on_stack (regcache, val + regsize, len - regsize, align, &addr); + } + else + { + pass_on_stack (regcache, val, len, align, &addr); + } } else { - pass_on_stack (regcache, val, len, align, &addr); + /* Variadic arguments are passed in GARs + in the same manner as named arguments. + And after a variadic argument has been passed on the stack, + all future arguments will also be passed on the stack, + i.e., the last argument register may be left unused + due to the aligned register pair rule. + long double data tpye is passed in an aligned GAR pair, + the first register in the pair is even-numbered. */ + if (gar >= 2) + { + if (gar % 2 == 0) + { + pass_in_gar (regcache, gar--, val); + pass_in_gar (regcache, gar--, val + regsize); + } + else + { + gar--; + pass_in_gar (regcache, gar--, val); + pass_in_gar (regcache, gar--, val + regsize); + } + } + else if (gar == 1) + { + gar--; + pass_on_stack (regcache, val, len, align, &addr); + } + else + { + pass_on_stack (regcache, val, len, align, &addr); + } } } else @@ -633,7 +672,7 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, /* The other floating-point type is passed in FAR. If no FAR is available, it's passed in GAR. If no GAR is available, it's passed on the stack. */ - if (far > 0) + if (!varargs && far > 0) pass_in_far (regcache, far--, val); else if (gar > 0) pass_in_gar (regcache, gar--, val); @@ -673,7 +712,7 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, if no GAR is available, the value is passed on the stack. */ if (floating_point_members == 1) { - if (far > 0) + if (!varargs && far > 0) pass_in_far (regcache, far--, val); else if (gar > 0) pass_in_gar (regcache, gar--, val); @@ -688,7 +727,7 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, and passed on the stack if no GAR is available. */ else if (floating_point_members == 2) { - if (far >= 2) + if (!varargs && far >= 2) { pass_in_far (regcache, far--, val); pass_in_far (regcache, far--, val + align); @@ -724,7 +763,7 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, If no GAR is available, it's passed on the stack. */ else if (floating_point_members == 1 && fixed_point_members == 1) { - if (far > 0 && gar > 0) + if (!varargs && far > 0 && gar > 0) { if (first_member_is_fixed_point == false) { @@ -799,8 +838,16 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, } else if (gar == 1) { - pass_in_gar (regcache, gar--, val); - pass_on_stack (regcache, val + regsize, len - regsize, align, &addr); + if (!varargs) + { + pass_in_gar (regcache, gar--, val); + pass_on_stack (regcache, val + regsize, len - regsize, align, &addr); + } + else + { + gar--; + pass_on_stack (regcache, val, len, align, &addr); + } } else { @@ -823,7 +870,7 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, else if ((len == 16 && floating_point_members == 2) || (len == 12 && floating_point_members == 2)) { - if (far >= 2) + if (!varargs && far >= 2) { pass_in_far (regcache, far--, val); pass_in_far (regcache, far--, val + regsize); @@ -859,7 +906,7 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, the low-order bits are in the GAR and the high-order bits are on the stack; And it's passed on the stack if no GAR is available. */ - if (far > 0 && gar > 0) + if (!varargs && far > 0 && gar > 0) { if (first_member_is_fixed_point == false) { @@ -872,17 +919,17 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, pass_in_far (regcache, far--, val + regsize); } } - else if (far == 0 && gar >= 2) + else if ((!varargs && far == 0 && gar >= 2) || (varargs && gar >= 2)) { pass_in_gar (regcache, gar--, val); pass_in_gar (regcache, gar--, val + regsize); } - else if (far == 0 && gar == 1) + else if ((!varargs && far == 0 && gar == 1) || (varargs && gar == 1)) { pass_in_gar (regcache, gar--, val); pass_on_stack (regcache, val + regsize, len - regsize, align, &addr); } - else if (far == 0 && gar == 0) + else if ((!varargs && far == 0 && gar == 0) || (varargs && gar == 0)) { pass_on_stack (regcache, val, len, align, &addr); } @@ -990,7 +1037,7 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, and the high-order float member bits in the higher-numbered FAR. If the number of available FAR is less than 2, it's passed in a GAR, and passed on the stack if no GAR is available. */ - if (far >= 2) + if (!varargs && far >= 2) { pass_in_far (regcache, far--, val); pass_in_far (regcache, far--, val + align); @@ -1019,7 +1066,7 @@ loongarch_push_dummy_call (struct gdbarch *gdbarch, and the high-order bits are on stack, and passed on the stack if no GAR is available. */ { - if (far >= 2) + if (!varargs && far >= 2) { pass_in_far (regcache, far--, val); pass_in_far (regcache, far--, val + align); -- 2.27.0