Re: [patch] Set calling convention of methods

Jonas Maebe
2009-10-01T09:18:20Z

Sorry for the delayed reply. I recently moved and don't have Internet
access yet at home.

On 30 Sep 2009, at 18:25, Joel Brobecker wrote:

> Thanks for doing that, we really like testcases, so I appreciate
> the effort.

Since I always insist on tests for new functionality added to our
compiler, it's only reasonable to hold my own patches to other
projects to the same standard :)

> Overall, this looks OK to me, but Mark seemed interested in reviewing
> this patch, so please wait for his comments as well.

Ok. Note that my mail client is known to wrap text at 80 columns (and
adds a space at the end of each wrapped line for detecting this
operation). This behaviour cannot be disabled afaik, and yes, one
could certainly consider this to be a bug. At the same time, it
however also adds '"Format="flowed"; DelSp="yes"' to the Content-Type
header, so mail clients on the other side can reconstruct the original
text (if those clients support these modifiers, which I hope is the
case).

In case this fails, too, I've also placed the new patch for download
at http://users.elis.ugent.be/~jmaebe/gdb/gdb_borland_fastcall7.patch.txt

> Again, I think
> that dwarf2.h needs to be approved by binutils - it's probably going
> to be routine, but you never know.

Given that it was later confirmed that the file does belong to gcc,
should I resend my patch for dwarf2.h to the gcc patches list? I've
also added a description of the Borland fastcall calling convention to
dwarf2.h in the attached patch, as requested by Tom. Note that this
calling convention is different from GCC's fastcall.

>> * gdb.dwarf2/dw2-borland_fastcall.S: New.
>
> The .S file needs a copyright header.

Added.

> Would you be able to re-generate
> the file with -dA, by any chance. It makes the DWARF data more
> readable.
> Otherwise, no problem, it's already fine as it is.

The assembler file was generated by the Free Pascal Compiler, which is
not gcc-based. It does not have an option to produce DWARF any
prettier than this...

> We do not use gdb_suppress_tests anymore. runto_main already logs
> a FAIL if it does not work, so you can simply return -1 for instance.
> I don't think the return value makes any difference in our context.

Done.

Thanks for the feedback,

Jonas

2009-10-01 Jonas Maebe <jonas.maebe <at> elis.ugent.be>

Add support for the "Borland fastcall" calling convention.

* dwarf2.h: Add DW_CC_GNU_borland_fastcall_i386 constant.
* i386-tdep.c: #include dwarf2.h
(i386_borland_fastcall_push_dummy_call): New.
(i386_push_dummy_generic_call): Renamed i386_push_dummy_call.
(i386_push_dummy_call): New dispatch function that calls
i386_generic_push_dummy_call or i386_push_dummy_borland_fast_call
depending on the calling convention.
* gdb.dwarf2/dw2-borland_fastcall.exp: New.
* gdb.dwarf2/dw2-borland_fastcall.S: New.

diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index b79bcd2..dbfcf31 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -53,6 +53,8 @@
#include "record.h"
#include <stdint.h>

+#include "dwarf2.h"
+
/* Register names. */

static char *i386_register_names[] =
@@ -1426,7 +1428,7 @@ i386_frame_this_id (struct frame_info
*this_frame, void **this_cache,
if (cache->base == 0)
return;

- /* See the end of i386_push_dummy_call. */
+ /* See the end of i386_generic_push_dummy_call. */
(*this_id) = frame_id_build (cache->base + 8, cache->pc);
}

@@ -1620,7 +1622,7 @@ i386_sigtramp_frame_this_id (struct frame_info
*this_frame, void **this_cache,
struct i386_frame_cache *cache =
i386_sigtramp_frame_cache (this_frame, this_cache);

- /* See the end of i386_push_dummy_call. */
+ /* See the end of i386_generic_push_dummy_call. */
(*this_id) = frame_id_build (cache->base + 8, get_frame_pc
(this_frame));
}

@@ -1697,7 +1699,7 @@ i386_dummy_id (struct gdbarch *gdbarch, struct
frame_info *this_frame)

fp = get_frame_register_unsigned (this_frame, I386_EBP_REGNUM);

- /* See the end of i386_push_dummy_call. */
+ /* See the end of i386_generic_push_dummy_call. */
return frame_id_build (fp + 8, get_frame_pc (this_frame));
}
\f
@@ -1765,10 +1767,10 @@ i386_16_byte_align_p (struct type *type)
}

static CORE_ADDR
-i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
- struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
- struct value **args, CORE_ADDR sp, int struct_return,
- CORE_ADDR struct_addr)
+i386_generic_push_dummy_call (struct gdbarch *gdbarch, struct value
*function,
+ struct regcache *regcache, CORE_ADDR bp_addr,
+ int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[4];
@@ -1861,6 +1863,144 @@ i386_push_dummy_call (struct gdbarch *gdbarch,
struct value *function,
return sp + 8;
}

+/* Borland fastcall: register parameters are passed from left to
right, then
+ stack parameters also from left to right. The first three
unstructured
+ parameters <= 32 bits are passed in %eax, %edx and %ecx. The
others are
+ passed on the stack. Furthermore, in case of a struct return by
reference,
+ the address of this struct is passed as the first (register)
parameter. */
+static CORE_ADDR
+i386_borland_fastcall_push_dummy_call (struct gdbarch *gdbarch,
+ struct value *function,
+ struct regcache *regcache,
+ CORE_ADDR bp_addr, int nargs,
+ struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
+{
+ static const int para_regs[3] = { I386_EAX_REGNUM, I386_EDX_REGNUM,
+ I386_ECX_REGNUM };
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[4];
+ int reg_paras[3] = { -1, -1, -1 };
+ int i, j;
+ int write_pass;
+ int para_regnum = 0;
+
+ /* First assign the register parameters (left to right). */
+ if (struct_return)
+ {
+ store_unsigned_integer (buf, 4, byte_order, struct_addr);
+ regcache_cooked_write (regcache, para_regs[para_regnum],
+ buf);
+ /* Use the otherwise invalid "nargs" argument index to denote the
+ function result. */
+ reg_paras[para_regnum] = nargs;
+ para_regnum++;
+ }
+
+ for (i = 0; i < nargs && para_regnum < 3; i++)
+ {
+ struct type *type = check_typedef (value_enclosing_type
(args[i]));
+ int len = TYPE_LENGTH (type);
+
+ if (len <= 4
+ && TYPE_CODE (type) != TYPE_CODE_ARRAY
+ && TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_FLT)
+ {
+ regcache_cooked_write (regcache, para_regs[para_regnum],
+ value_contents_all (args[i]));
+ reg_paras[para_regnum] = i;
+ para_regnum++;
+ }
+ }
+
+ /* Now process the stack parameters from left to right. */
+ for (write_pass = 0; write_pass < 2; write_pass++)
+ {
+ int args_space = 0;
+ int have_16_byte_aligned_arg = 0;
+
+ for (i = nargs - 1; i >= 0; i--)
+ {
+ struct type *type = check_typedef (value_enclosing_type (args[i]));
+ int len = TYPE_LENGTH (type);
+ int processed = 0;
+
+ /* Skip parameters already assigned to registers. */
+ for (j = 0; j < para_regnum; j++)
+ if (reg_paras[j] == i)
+ {
+ processed = 1;
+ break;
+ }
+ if (processed)
+ continue;
+
+ if (i386_16_byte_align_p (value_enclosing_type (args[i])))
+ {
+ args_space = align_up (args_space, 16);
+ have_16_byte_aligned_arg = 1;
+ }
+ if (write_pass)
+ {
+ write_memory (sp + args_space,
+ value_contents_all (args[i]), len);
+ }
+ args_space += align_up (len, 4);
+ }
+
+ if (!write_pass)
+ {
+ /* Early exit if nothing to do. */
+ if (!args_space)
+ break;
+ if (have_16_byte_aligned_arg)
+ args_space = align_up (args_space, 16);
+ sp -= args_space;
+ }
+ }
+
+ /* Store return address. */
+ sp -= 4;
+ store_unsigned_integer (buf, 4, byte_order, bp_addr);
+ write_memory (sp, buf, 4);
+
+ /* Finally, update the stack pointer... */
+ store_unsigned_integer (buf, 4, byte_order, sp);
+ regcache_cooked_write (regcache, I386_ESP_REGNUM, buf);
+
+ /* ...and fake a frame pointer. */
+ regcache_cooked_write (regcache, I386_EBP_REGNUM, buf);
+
+ /* See the end of i386_generic_push_dummy_call. */
+ return sp + 8;
+}
+
+static CORE_ADDR
+i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
+ struct value **args, CORE_ADDR sp, int struct_return,
+ CORE_ADDR struct_addr)
+{
+ struct type *type = check_typedef (value_type (function));
+
+ /* Look up the target type in case of a function/method pointer. */
+ while (type && can_dereference (type))
+ type = TYPE_TARGET_TYPE (type);
+
+ /* Check calling convention. */
+ if (type
+ && TYPE_CALLING_CONVENTION (type) ==
DW_CC_GNU_borland_fastcall_i386)
+ return i386_borland_fastcall_push_dummy_call (gdbarch, function,
regcache,
+ bp_addr, nargs, args, sp,
+ struct_return, struct_addr);
+ else
+ return i386_generic_push_dummy_call (gdbarch, function, regcache,
bp_addr,
+ nargs, args, sp, struct_return,
+ struct_addr);
+}
+
/* These registers are used for returning integers (and on some
targets also for returning `struct' and `union' values when their
size and alignment match an integer type). */
diff --git a/include/dwarf2.h b/include/dwarf2.h
index 385ab22..7209a99 100644
--- a/include/dwarf2.h
+++ b/include/dwarf2.h
@@ -721,7 +721,14 @@ enum dwarf_calling_convention
DW_CC_lo_user = 0x40,
DW_CC_hi_user = 0xff,

- DW_CC_GNU_renesas_sh = 0x40
+ DW_CC_GNU_renesas_sh = 0x40,
+ /* Borland fastcall: register parameters are passed from left to
right,
+ then stack parameters also from left to right. The first three
+ unstructured parameters <= 32 bits are passed in %eax, %edx
and %ecx.
+ The others are passed on the stack. Furthermore, in case of a
struct
+ return by reference, the address of this struct is passed as
the first
+ (register) parameter. */
+ DW_CC_GNU_borland_fastcall_i386 = 0x41
};

/* Inline attribute. */
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.S b/gdb/
testsuite/gdb.dwarf2/dw2-borland_fastcall.S
new file mode 100644
index 0000000..ba88d14
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.S
@@ -0,0 +1,962 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2009 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 Borland fastcall calling convention. */
+
+ .file "tgdbcc.pp"
+# Begin asmlist al_begin
+
+.section .debug_line
+ .type .Ldebug_linesection0,@object
+.Ldebug_linesection0:
+ .type .Ldebug_line0,@object
+.Ldebug_line0:
+
+.section .debug_abbrev
+ .type .Ldebug_abbrevsection0,@object
+.Ldebug_abbrevsection0:
+ .type .Ldebug_abbrev0,@object
+.Ldebug_abbrev0:
+
+.section .text
+.globl DEBUGSTART_P$PROGRAM
+ .type DEBUGSTART_P$PROGRAM,@object
+DEBUGSTART_P$PROGRAM:
+# End asmlist al_begin
+# Begin asmlist al_stabs
+# End asmlist al_stabs
+# Begin asmlist al_procedures
+
+.section .text
+ .balign 16,0x90
+.globl P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+ .type P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR,@function
+P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR:
+.Lc1:
+# Temps allocated between ebp-12 and ebp-12
+.Ll1:
+# [tgdbcc.pp]
+# [10] begin
+ pushl %ebp
+.Lc3:
+.Lc4:
+ movl %esp,%ebp
+.Lc5:
+ subl $12,%esp
+# Var a located at ebp-4
+# Var b located at ebp-8
+# Var c located at ebp+20
+# Var d located at ebp+16
+# Var e located at ebp+12
+# Var f located at ebp+8
+# Var $result located at ebp-12
+ movl %eax,-12(%ebp)
+ movb %dl,-4(%ebp)
+ movb %cl,-8(%ebp)
+.Ll2:
+# [11] fillchar(result.g,sizeof(result.g),0);
+ pushl %edi
+ movl -12(%ebp),%edi
+ leal 6(%edi),%edi
+ xorl %eax,%eax
+ movl $250,%ecx
+ rep stosl
+ popl %edi
+.Ll3:
+# [12] result.a:=a;
+ movl -12(%ebp),%eax
+ movb -4(%ebp),%dl
+ movb %dl,(%eax)
+.Ll4:
+# [13] result.b:=b;
+ movl -12(%ebp),%eax
+ movb -8(%ebp),%dl
+ movb %dl,1(%eax)
+.Ll5:
+# [14] result.c:=c;
+ movl -12(%ebp),%eax
+ movb 20(%ebp),%dl
+ movb %dl,2(%eax)
+.Ll6:
+# [15] result.d:=d;
+ movl -12(%ebp),%eax
+ movb 16(%ebp),%dl
+ movb %dl,3(%eax)
+.Ll7:
+# [16] result.e:=e;
+ movl -12(%ebp),%eax
+ movb 12(%ebp),%dl
+ movb %dl,4(%eax)
+.Ll8:
+# [17] result.f:=f;
+ movl -12(%ebp),%eax
+ movb 8(%ebp),%dl
+ movb %dl,5(%eax)
+.Ll9:
+# [18] end;
+ leave
+ ret $16
+.Lc2:
+.Lt2:
+.Le0:
+ .size P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR, .Le0 - P
$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+.Ll10:
+
+.section .text
+ .balign 16,0x90
+.globl PASCALMAIN
+ .type PASCALMAIN,@function
+PASCALMAIN:
+.globl main
+ .type main,@function
+main:
+.Lc6:
+# Temps allocated between ebp-1008 and ebp+0
+.Ll11:
+# [20] begin
+ pushl %ebp
+.Lc8:
+.Lc9:
+ movl %esp,%ebp
+.Lc10:
+ subl $1008,%esp
+.Ll12:
+# [21] func(255,254,253,252,251,250);
+ pushl $253
+ pushl $252
+ pushl $251
+ pushl $250
+ leal -1008(%ebp),%eax
+ movb $254,%cl
+ movb $255,%dl
+ call P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+.Ll13:
+# [22] end.
+ xorl %eax, %eax
+ leave
+ ret
+.Lc7:
+.Lt1:
+.Le1:
+ .size main, .Le1 - main
+.Ll14:
+
+.section .fpc
+ .balign 8
+ .ascii "FPC 2.5.1 [2009/09/12] for i386 - Linux"
+
+.section .debug_frame
+.Lc11:
+ .long .Lc13-.Lc12
+.Lc12:
+ .long -1
+ .byte 1
+ .byte 0
+ .uleb128 1
+ .sleb128 -4
+ .byte 8
+ .byte 12
+ .uleb128 4
+ .uleb128 4
+ .byte 5
+ .uleb128 8
+ .uleb128 1
+ .balign 4,0
+.Lc13:
+ .long .Lc15-.Lc14
+.Lc14:
+ .long .Lc11
+ .long .Lc1
+ .long .Lc2-.Lc1
+ .byte 4
+ .long .Lc3-.Lc1
+ .byte 14
+ .uleb128 8
+ .byte 4
+ .long .Lc4-.Lc3
+ .byte 5
+ .uleb128 5
+ .uleb128 2
+ .byte 4
+ .long .Lc5-.Lc4
+ .byte 13
+ .uleb128 5
+ .balign 4,0
+.Lc15:
+ .long .Lc17-.Lc16
+.Lc16:
+ .long .Lc11
+ .long .Lc6
+ .long .Lc7-.Lc6
+ .byte 4
+ .long .Lc8-.Lc6
+ .byte 14
+ .uleb128 8
+ .byte 4
+ .long .Lc9-.Lc8
+ .byte 5
+ .uleb128 5
+ .uleb128 2
+ .byte 4
+ .long .Lc10-.Lc9
+ .byte 13
+ .uleb128 5
+ .balign 4,0
+.Lc17:
+# End asmlist al_dwarf_frame
+# Begin asmlist al_dwarf_info
+
+.section .debug_info
+ .type .Ldebug_info0,@object
+.Ldebug_info0:
+ .long .Ledebug_info0-.Lf1
+.Lf1:
+ .short 2
+ .long .Ldebug_abbrev0
+ .byte 4
+ .uleb128 1
+ .ascii "tgdbcc.pp\000"
+ .ascii "Free Pascal 2.5.1 2009/09/12\000"
+ .ascii "/home/jmaebe/private/nobackup/fpc/test/\000"
+ .byte 9
+ .byte 3
+ .long .Ldebug_line0
+ .long DEBUGSTART_P$PROGRAM
+ .long DEBUGEND_P$PROGRAM
+# Syms - Begin Staticsymtable
+# Symbol SYSTEM
+# Symbol FPINTRES
+# Symbol OBJPAS
+# Symbol PROGRAM
+# Symbol main
+# Symbol TR
+# Symbol FUNC
+# Symbol SI_PRC
+# Syms - End Staticsymtable
+# Procdef $main; Register;
+ .uleb128 2
+ .ascii "main\000"
+ .byte 65
+ .byte 1
+ .long main
+ .long .Lt1
+ .byte 0
+# Procdef func(,Byte,Byte,Byte,Byte,Byte,Byte):<record type>;
+ .uleb128 3
+ .ascii "FUNC\000"
+ .byte 65
+ .byte 1
+ .long _$PROGRAM$_Ld1
+ .long P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+ .long .Lt2
+# Symbol A
+ .uleb128 4
+ .ascii "A\000"
+ .byte 2
+ .byte 117
+ .sleb128 -4
+ .long _$PROGRAM$_Ld3
+# Symbol B
+ .uleb128 5
+ .ascii "B\000"
+ .byte 2
+ .byte 117
+ .sleb128 -8
+ .long _$PROGRAM$_Ld3
+# Symbol C
+ .uleb128 6
+ .ascii "C\000"
+ .byte 2
+ .byte 117
+ .sleb128 20
+ .long _$PROGRAM$_Ld3
+# Symbol D
+ .uleb128 7
+ .ascii "D\000"
+ .byte 2
+ .byte 117
+ .sleb128 16
+ .long _$PROGRAM$_Ld3
+# Symbol E
+ .uleb128 8
+ .ascii "E\000"
+ .byte 2
+ .byte 117
+ .sleb128 12
+ .long _$PROGRAM$_Ld3
+# Symbol F
+ .uleb128 9
+ .ascii "F\000"
+ .byte 2
+ .byte 117
+ .sleb128 8
+ .long _$PROGRAM$_Ld3
+# Symbol result
+ .uleb128 10
+ .ascii "result\000"
+ .byte 2
+ .byte 117
+ .sleb128 -12
+ .long _$PROGRAM$_Ld2
+# Symbol FUNC
+ .uleb128 11
+ .ascii "FUNC\000"
+ .byte 2
+ .byte 117
+ .sleb128 -12
+ .long _$PROGRAM$_Ld2
+# Symbol RESULT
+ .uleb128 12
+ .ascii "RESULT\000"
+ .byte 2
+ .byte 117
+ .sleb128 -12
+ .long _$PROGRAM$_Ld2
+ .byte 0
+# Defs - Begin unit SYSTEM has index 1
+# Definition Byte
+ .type _$PROGRAM$_Ld3,@object
+_$PROGRAM$_Ld3:
+ .uleb128 13
+ .ascii "BYTE\000"
+ .long .La1
+ .type .La1,@object
+.La1:
+ .uleb128 14
+ .ascii "BYTE\000"
+ .byte 7
+ .byte 1
+ .type _$PROGRAM$_Ld4,@object
+_$PROGRAM$_Ld4:
+ .uleb128 15
+ .long _$PROGRAM$_Ld3
+# Defs - End unit SYSTEM has index 1
+# Defs - Begin unit FPINTRES has index 2
+# Defs - End unit FPINTRES has index 2
+# Defs - Begin unit OBJPAS has index 3
+# Defs - End unit OBJPAS has index 3
+# Defs - Begin unit SI_PRC has index 3
+# Defs - End unit SI_PRC has index 3
+# Defs - Begin Staticsymtable
+# Definition tr
+ .type _$PROGRAM$_Ld1,@object
+_$PROGRAM$_Ld1:
+ .uleb128 16
+ .ascii "TR\000"
+ .long .La2
+ .type .La2,@object
+.La2:
+ .uleb128 17
+ .ascii "TR\000"
+ .uleb128 1006
+ .uleb128 18
+ .ascii "A\000"
+ .byte 2
+ .byte 35
+ .uleb128 0
+ .long _$PROGRAM$_Ld3
+ .uleb128 19
+ .ascii "B\000"
+ .byte 2
+ .byte 35
+ .uleb128 1
+ .long _$PROGRAM$_Ld3
+ .uleb128 20
+ .ascii "C\000"
+ .byte 2
+ .byte 35
+ .uleb128 2
+ .long _$PROGRAM$_Ld3
+ .uleb128 21
+ .ascii "D\000"
+ .byte 2
+ .byte 35
+ .uleb128 3
+ .long _$PROGRAM$_Ld3
+ .uleb128 22
+ .ascii "E\000"
+ .byte 2
+ .byte 35
+ .uleb128 4
+ .long _$PROGRAM$_Ld3
+ .uleb128 23
+ .ascii "F\000"
+ .byte 2
+ .byte 35
+ .uleb128 5
+ .long _$PROGRAM$_Ld3
+ .uleb128 24
+ .ascii "G\000"
+ .byte 2
+ .byte 35
+ .uleb128 6
+ .long _$PROGRAM$_Ld5
+ .byte 0
+ .type _$PROGRAM$_Ld2,@object
+_$PROGRAM$_Ld2:
+ .uleb128 25
+ .long _$PROGRAM$_Ld1
+# Definition Array[0..999] Of Byte
+ .type _$PROGRAM$_Ld5,@object
+_$PROGRAM$_Ld5:
+ .uleb128 26
+ .uleb128 1000
+ .long _$PROGRAM$_Ld3
+ .uleb128 27
+ .sleb128 0
+ .sleb128 999
+ .uleb128 1
+ .long _$PROGRAM$_Ld7
+ .byte 0
+ .type _$PROGRAM$_Ld6,@object
+_$PROGRAM$_Ld6:
+ .uleb128 28
+ .long _$PROGRAM$_Ld5
+# Defs - End Staticsymtable
+# Definition SmallInt
+ .type _$PROGRAM$_Ld7,@object
+_$PROGRAM$_Ld7:
+ .uleb128 29
+ .ascii "SMALLINT\000"
+ .long .La3
+ .type .La3,@object
+.La3:
+ .uleb128 30
+ .ascii "SMALLINT\000"
+ .byte 5
+ .byte 2
+ .type _$PROGRAM$_Ld8,@object
+_$PROGRAM$_Ld8:
+ .uleb128 31
+ .long _$PROGRAM$_Ld7
+ .byte 0
+ .type .Ledebug_info0,@object
+.Ledebug_info0:
+# End asmlist al_dwarf_info
+# Begin asmlist al_dwarf_abbrev
+
+.section .debug_abbrev
+# Abbrev 1
+ .uleb128 1
+ .uleb128 17
+ .byte 1
+ .uleb128 3
+ .uleb128 8
+ .uleb128 37
+ .uleb128 8
+ .uleb128 27
+ .uleb128 8
+ .uleb128 19
+ .uleb128 11
+ .uleb128 66
+ .uleb128 11
+ .uleb128 16
+ .uleb128 6
+ .uleb128 17
+ .uleb128 1
+ .uleb128 18
+ .uleb128 1
+ .byte 0
+ .byte 0
+# Abbrev 2
+ .uleb128 2
+ .uleb128 46
+ .byte 1
+ .uleb128 3
+ .uleb128 8
+ .uleb128 54
+ .uleb128 11
+ .uleb128 63
+ .uleb128 12
+ .uleb128 17
+ .uleb128 1
+ .uleb128 18
+ .uleb128 1
+ .byte 0
+ .byte 0
+# Abbrev 3
+ .uleb128 3
+ .uleb128 46
+ .byte 1
+ .uleb128 3
+ .uleb128 8
+ .uleb128 54
+ .uleb128 11
+ .uleb128 63
+ .uleb128 12
+ .uleb128 73
+ .uleb128 16
+ .uleb128 17
+ .uleb128 1
+ .uleb128 18
+ .uleb128 1
+ .byte 0
+ .byte 0
+# Abbrev 4
+ .uleb128 4
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 5
+ .uleb128 5
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 6
+ .uleb128 6
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 7
+ .uleb128 7
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 8
+ .uleb128 8
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 9
+ .uleb128 9
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 10
+ .uleb128 10
+ .uleb128 52
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 11
+ .uleb128 11
+ .uleb128 52
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 12
+ .uleb128 12
+ .uleb128 52
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 13
+ .uleb128 13
+ .uleb128 22
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 14
+ .uleb128 14
+ .uleb128 36
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 62
+ .uleb128 11
+ .uleb128 11
+ .uleb128 11
+ .byte 0
+ .byte 0
+# Abbrev 15
+ .uleb128 15
+ .uleb128 16
+ .byte 0
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 16
+ .uleb128 16
+ .uleb128 22
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 17
+ .uleb128 17
+ .uleb128 19
+ .byte 1
+ .uleb128 3
+ .uleb128 8
+ .uleb128 11
+ .uleb128 15
+ .byte 0
+ .byte 0
+# Abbrev 18
+ .uleb128 18
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 19
+ .uleb128 19
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 20
+ .uleb128 20
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 21
+ .uleb128 21
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 22
+ .uleb128 22
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 23
+ .uleb128 23
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 24
+ .uleb128 24
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 25
+ .uleb128 25
+ .uleb128 16
+ .byte 0
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 26
+ .uleb128 26
+ .uleb128 1
+ .byte 1
+ .uleb128 11
+ .uleb128 15
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 27
+ .uleb128 27
+ .uleb128 33
+ .byte 0
+ .uleb128 34
+ .uleb128 13
+ .uleb128 47
+ .uleb128 13
+ .uleb128 81
+ .uleb128 15
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 28
+ .uleb128 28
+ .uleb128 16
+ .byte 0
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 29
+ .uleb128 29
+ .uleb128 22
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 30
+ .uleb128 30
+ .uleb128 36
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 62
+ .uleb128 11
+ .uleb128 11
+ .uleb128 11
+ .byte 0
+ .byte 0
+# Abbrev 31
+ .uleb128 31
+ .uleb128 16
+ .byte 0
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+ .byte 0
+# End asmlist al_dwarf_abbrev
+# Begin asmlist al_dwarf_line
+
+.section .debug_line
+# === header start ===
+ .long .Ledebug_line0-.Lf2
+.Lf2:
+ .short 2
+ .long .Lehdebug_line0-.Lf3
+.Lf3:
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 255
+ .byte 13
+ .byte 0
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 1
+ .byte 0
+ .byte 0
+ .byte 1
+# include_directories
+ .byte 0
+# file_names
+ .ascii "tgdbcc.pp\000"
+ .uleb128 0
+ .uleb128 0
+ .uleb128 0
+ .byte 0
+ .type .Lehdebug_line0,@object
+.Lehdebug_line0:
+# === header end ===
+# function: P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+# [10:1]
+ .byte 0
+ .uleb128 5
+ .byte 2
+ .long .Ll1
+ .byte 5
+ .uleb128 1
+ .byte 21
+# [11:18]
+ .byte 2
+ .uleb128 .Ll2-.Ll1
+ .byte 5
+ .uleb128 18
+ .byte 13
+# [12:9]
+ .byte 2
+ .uleb128 .Ll3-.Ll2
+ .byte 5
+ .uleb128 9
+ .byte 13
+# [13:9]
+ .byte 2
+ .uleb128 .Ll4-.Ll3
+ .byte 13
+# [14:9]
+ .byte 2
+ .uleb128 .Ll5-.Ll4
+ .byte 13
+# [15:9]
+ .byte 2
+ .uleb128 .Ll6-.Ll5
+ .byte 13
+# [16:9]
+ .byte 2
+ .uleb128 .Ll7-.Ll6
+ .byte 13
+# [17:9]
+ .byte 2
+ .uleb128 .Ll8-.Ll7
+ .byte 13
+# [18:1]
+ .byte 2
+ .uleb128 .Ll9-.Ll8
+ .byte 5
+ .uleb128 1
+ .byte 13
+ .byte 0
+ .uleb128 5
+ .byte 2
+ .long .Ll10
+ .byte 0
+ .byte 1
+ .byte 1
+# ###################
+# function: PASCALMAIN
+# function: main
+# [20:1]
+ .byte 0
+ .uleb128 5
+ .byte 2
+ .long .Ll11
+ .byte 5
+ .uleb128 1
+ .byte 31
+# [21:3]
+ .byte 2
+ .uleb128 .Ll12-.Ll11
+ .byte 5
+ .uleb128 3
+ .byte 13
+# [22:1]
+ .byte 2
+ .uleb128 .Ll13-.Ll12
+ .byte 5
+ .uleb128 1
+ .byte 13
+ .byte 0
+ .uleb128 5
+ .byte 2
+ .long .Ll14
+ .byte 0
+ .byte 1
+ .byte 1
+# ###################
+ .type .Ledebug_line0,@object
+.Ledebug_line0:
+# End asmlist al_dwarf_line
+# Begin asmlist al_picdata
+# End asmlist al_picdata
+# Begin asmlist al_resourcestrings
+# End asmlist al_resourcestrings
+# Begin asmlist al_objc_data
+# End asmlist al_objc_data
+# Begin asmlist al_end
+
+.section .text
+.globl DEBUGEND_P$PROGRAM
+ .type DEBUGEND_P$PROGRAM,@object
+DEBUGEND_P$PROGRAM:
+# End asmlist al_end
+.section .note.GNU-stack,"",%progbits
+
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.exp b/gdb/
testsuite/gdb.dwarf2/dw2-borland_fastcall.exp
new file mode 100644
index 0000000..bd30a20
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.exp
@@ -0,0 +1,52 @@
+# Copyright 2009 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 Borland fastcall calling convention
+
+# This test can only be run on targets which support DWARF-2 and use
gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+ && ![istarget *-*-gnu*]
+ && ![istarget *-*-elf*]
+ && ![istarget *-*-openbsd*]} {
+ return 0;
+ }
+
+# This test can only be run on x86 targets.
+if {![istarget i?86-*]} {
+ return 0
+}
+
+set testfile "dw2-borland_fastcall"
+set srcfile ${testfile}.S
+set binfile ${objdir}/${subdir}/${testfile}.x
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}"
executable {nodebug}] != "" } {
+ return -1
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if { ![runto_main] } {
+ return -1
+}
+
+
+gdb_test "p FUNC(1,2,3,4,5,6)" \
+ "= {A = 1, B = 2, C = 3, D = 4, E = 5, F = 6, G = #0 <repeats 999
times>}"