diff mbox

[Xen-devel,19/34] xen/arm: Provide eabi wrapper for __aeabi_mem* functions

Message ID 1395766541-23979-20-git-send-email-julien.grall@linaro.org
State Deferred, archived
Headers show

Commit Message

Julien Grall March 25, 2014, 4:55 p.m. UTC
Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
for mem* function provided by Xen.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Stefano Stabellini <stefano.stabellini@citrix.com>
Cc: Tim Deegan <tim@xen.org>
---
 xen/arch/arm/Makefile |    1 +
 xen/arch/arm/eabi.c   |   29 +++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 xen/arch/arm/eabi.c

Comments

Ian Campbell March 25, 2014, 5:25 p.m. UTC | #1
On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
> for mem* function provided by Xen.

Where are the references to these functions coming from if not from the
compiler?

Are you sure this isn't something usually provided by some clang
equivalent of libgcc?

Ian.
Julien Grall March 25, 2014, 6:12 p.m. UTC | #2
Hi Ian,

On 03/25/2014 05:25 PM, Ian Campbell wrote:
> On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
>> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
>> for mem* function provided by Xen.
> 
> Where are the references to these functions coming from if not from the
> compiler?

Theses functions are called by the code generated by the compiler.
Removing this file will result to the following errors:

/local/home/julien/works/arndale/xen/xen/common/symbols-dummy.o -o /local/home/julien/works/arndale/xen/xen/.xen-syms.0
prelink.o: In function `dump_node':
/local/home/julien/works/arndale/xen/xen/common/device_tree.c:259: undefined reference to `__aeabi_memset'
prelink.o: In function `get_cpu_idle_time':
/local/home/julien/works/arndale/xen/xen/common/schedule.c:178: undefined reference to `__aeabi_memset'
prelink.o: In function `construct_dom0':
/local/home/julien/works/arndale/xen/xen/arch/arm/domain_build.c:1055: undefined reference to `__aeabi_memset'
prelink.o: In function `wallclock_time':
/local/home/julien/works/arndale/xen/xen/arch/arm/time.c:267: undefined reference to `__aeabi_memset'
prelink.o: In function `scheduler_init':
/local/home/julien/works/arndale/xen/xen/common/schedule.c:1368: undefined reference to `__aeabi_memcpy'
/local/home/julien/works/arndale/xen/xen/common/schedule.c:1377: undefined reference to `__aeabi_memcpy'

 
> Are you sure this isn't something usually provided by some clang
> equivalent of libgcc?

Yes. Linux on LLVM has the same issue. See page 22:
https://events.linuxfoundation.org/images/stories/pdf/lcjp2012_charlebois.pdf?a

Regards,
Ian Campbell March 26, 2014, 10:39 a.m. UTC | #3
On Tue, 2014-03-25 at 18:12 +0000, Julien Grall wrote:
> Hi Ian,
> 
> On 03/25/2014 05:25 PM, Ian Campbell wrote:
> > On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
> >> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
> >> for mem* function provided by Xen.
> > 
> > Where are the references to these functions coming from if not from the
> > compiler?
> 
> Theses functions are called by the code generated by the compiler.

And who normally provides them when building with clang? Some sort of
libclang I guess?

> Removing this file will result to the following errors:
> 
> /local/home/julien/works/arndale/xen/xen/common/symbols-dummy.o -o /local/home/julien/works/arndale/xen/xen/.xen-syms.0
> prelink.o: In function `dump_node':
> /local/home/julien/works/arndale/xen/xen/common/device_tree.c:259: undefined reference to `__aeabi_memset'
> prelink.o: In function `get_cpu_idle_time':
> /local/home/julien/works/arndale/xen/xen/common/schedule.c:178: undefined reference to `__aeabi_memset'
> prelink.o: In function `construct_dom0':
> /local/home/julien/works/arndale/xen/xen/arch/arm/domain_build.c:1055: undefined reference to `__aeabi_memset'
> prelink.o: In function `wallclock_time':
> /local/home/julien/works/arndale/xen/xen/arch/arm/time.c:267: undefined reference to `__aeabi_memset'
> prelink.o: In function `scheduler_init':
> /local/home/julien/works/arndale/xen/xen/common/schedule.c:1368: undefined reference to `__aeabi_memcpy'
> /local/home/julien/works/arndale/xen/xen/common/schedule.c:1377: undefined reference to `__aeabi_memcpy'
> 
>  
> > Are you sure this isn't something usually provided by some clang
> > equivalent of libgcc?
> 
> Yes. Linux on LLVM has the same issue.

Kernels often use -nostdlib and other options which intentionally
disable the default linkage of libgcc/libclang type libraries.

>  See page 22:
> https://events.linuxfoundation.org/images/stories/pdf/lcjp2012_charlebois.pdf?a
> 
> Regards,
>
Julien Grall March 26, 2014, 3:38 p.m. UTC | #4
On 03/26/2014 10:39 AM, Ian Campbell wrote:
> On Tue, 2014-03-25 at 18:12 +0000, Julien Grall wrote:
>> Hi Ian,
>>
>> On 03/25/2014 05:25 PM, Ian Campbell wrote:
>>> On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
>>>> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
>>>> for mem* function provided by Xen.
>>>
>>> Where are the references to these functions coming from if not from the
>>> compiler?
>>
>> Theses functions are called by the code generated by the compiler.
> 
> And who normally provides them when building with clang? Some sort of
> libclang I guess?

I've tried to compile a same compilation unit with gcc and clang. gcc is
inlining the call to __aebi_*. See below:

Clang assembly:
000002b8 <wallclock_time>:
 2b8:   e92d4800        push    {fp, lr}
 2bc:   e1a0b00d        mov     fp, sp
 2c0:   e3a01024        mov     r1, #36 ; 0x24
 2c4:   e3a02000        mov     r2, #0
 2c8:   ebfffffe        bl      0 <__aeabi_memset>
 2cc:   e8bd8800        pop     {fp, pc}

GCC assembly:

00000378 <wallclock_time>:
 378:   e52db004        push    {fp}            ; (str fp, [sp, #-4]!)
 37c:   e28db000        add     fp, sp, #0
 380:   e3a02000        mov     r2, #0
 384:   e1a03000        mov     r3, r0
 388:   e4832004        str     r2, [r3], #4
 38c:   e5802004        str     r2, [r0, #4]
 390:   e2833004        add     r3, r3, #4
 394:   e4832004        str     r2, [r3], #4
 398:   e4832004        str     r2, [r3], #4
 39c:   e4832004        str     r2, [r3], #4
 3a0:   e4832004        str     r2, [r3], #4
 3a4:   e4832004        str     r2, [r3], #4
 3a8:   e4832004        str     r2, [r3], #4
 3ac:   e5832000        str     r2, [r3]
 3b0:   e24bd000        sub     sp, fp, #0
 3b4:   e49db004        pop     {fp}            ; (ldr fp, [sp], #4)
 3b8:   e12fff1e        bx      lr

Regards,
Julien Grall March 26, 2014, 3:46 p.m. UTC | #5
On 03/26/2014 03:38 PM, Julien Grall wrote:
> On 03/26/2014 10:39 AM, Ian Campbell wrote:
>> On Tue, 2014-03-25 at 18:12 +0000, Julien Grall wrote:
>>> Hi Ian,
>>>
>>> On 03/25/2014 05:25 PM, Ian Campbell wrote:
>>>> On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
>>>>> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
>>>>> for mem* function provided by Xen.
>>>>
>>>> Where are the references to these functions coming from if not from the
>>>> compiler?
>>>
>>> Theses functions are called by the code generated by the compiler.
>>
>> And who normally provides them when building with clang? Some sort of
>> libclang I guess?
> 
> I've tried to compile a same compilation unit with gcc and clang. gcc is
> inlining the call to __aebi_*. See below:

I've just noticed it also calls memset/memcpy directly without the
prefix __aebi_.

> Clang assembly:
> 000002b8 <wallclock_time>:
>  2b8:   e92d4800        push    {fp, lr}
>  2bc:   e1a0b00d        mov     fp, sp
>  2c0:   e3a01024        mov     r1, #36 ; 0x24
>  2c4:   e3a02000        mov     r2, #0
>  2c8:   ebfffffe        bl      0 <__aeabi_memset>
>  2cc:   e8bd8800        pop     {fp, pc}
> 
> GCC assembly:
> 
> 00000378 <wallclock_time>:
>  378:   e52db004        push    {fp}            ; (str fp, [sp, #-4]!)
>  37c:   e28db000        add     fp, sp, #0
>  380:   e3a02000        mov     r2, #0
>  384:   e1a03000        mov     r3, r0
>  388:   e4832004        str     r2, [r3], #4
>  38c:   e5802004        str     r2, [r0, #4]
>  390:   e2833004        add     r3, r3, #4
>  394:   e4832004        str     r2, [r3], #4
>  398:   e4832004        str     r2, [r3], #4
>  39c:   e4832004        str     r2, [r3], #4
>  3a0:   e4832004        str     r2, [r3], #4
>  3a4:   e4832004        str     r2, [r3], #4
>  3a8:   e4832004        str     r2, [r3], #4
>  3ac:   e5832000        str     r2, [r3]
>  3b0:   e24bd000        sub     sp, fp, #0
>  3b4:   e49db004        pop     {fp}            ; (ldr fp, [sp], #4)
>  3b8:   e12fff1e        bx      lr
> 
> Regards,
>
Ian Campbell March 26, 2014, 3:47 p.m. UTC | #6
On Wed, 2014-03-26 at 15:38 +0000, Julien Grall wrote:
> On 03/26/2014 10:39 AM, Ian Campbell wrote:
> > On Tue, 2014-03-25 at 18:12 +0000, Julien Grall wrote:
> >> Hi Ian,
> >>
> >> On 03/25/2014 05:25 PM, Ian Campbell wrote:
> >>> On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
> >>>> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
> >>>> for mem* function provided by Xen.
> >>>
> >>> Where are the references to these functions coming from if not from the
> >>> compiler?
> >>
> >> Theses functions are called by the code generated by the compiler.
> > 
> > And who normally provides them when building with clang? Some sort of
> > libclang I guess?
> 
> I've tried to compile a same compilation unit with gcc and clang. gcc is
> inlining the call to __aebi_*.

That is orthogonal to the question I asked.

What in a clang based system normally provides __aeabi_*?

Your choices are "a libclang thing", "the libc", "something else".

Ian.
Julien Grall March 26, 2014, 4:01 p.m. UTC | #7
On 03/26/2014 03:47 PM, Ian Campbell wrote:
> On Wed, 2014-03-26 at 15:38 +0000, Julien Grall wrote:
>> On 03/26/2014 10:39 AM, Ian Campbell wrote:
>>> On Tue, 2014-03-25 at 18:12 +0000, Julien Grall wrote:
>>>> Hi Ian,
>>>>
>>>> On 03/25/2014 05:25 PM, Ian Campbell wrote:
>>>>> On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
>>>>>> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
>>>>>> for mem* function provided by Xen.
>>>>>
>>>>> Where are the references to these functions coming from if not from the
>>>>> compiler?
>>>>
>>>> Theses functions are called by the code generated by the compiler.
>>>
>>> And who normally provides them when building with clang? Some sort of
>>> libclang I guess?
>>
>> I've tried to compile a same compilation unit with gcc and clang. gcc is
>> inlining the call to __aebi_*.
> 
> That is orthogonal to the question I asked.
> 
> What in a clang based system normally provides __aeabi_*?
> 
> Your choices are "a libclang thing", "the libc", "something else".

Sorry I spent the last couple of hours to try to find who is providing
the __aebi_* functions.

For userspace binary it's providing by the glibc.

Regards,
Ian Campbell March 26, 2014, 4:11 p.m. UTC | #8
On Wed, 2014-03-26 at 16:01 +0000, Julien Grall wrote:
> On 03/26/2014 03:47 PM, Ian Campbell wrote:
> > On Wed, 2014-03-26 at 15:38 +0000, Julien Grall wrote:
> >> On 03/26/2014 10:39 AM, Ian Campbell wrote:
> >>> On Tue, 2014-03-25 at 18:12 +0000, Julien Grall wrote:
> >>>> Hi Ian,
> >>>>
> >>>> On 03/25/2014 05:25 PM, Ian Campbell wrote:
> >>>>> On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
> >>>>>> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
> >>>>>> for mem* function provided by Xen.
> >>>>>
> >>>>> Where are the references to these functions coming from if not from the
> >>>>> compiler?
> >>>>
> >>>> Theses functions are called by the code generated by the compiler.
> >>>
> >>> And who normally provides them when building with clang? Some sort of
> >>> libclang I guess?
> >>
> >> I've tried to compile a same compilation unit with gcc and clang. gcc is
> >> inlining the call to __aebi_*.
> > 
> > That is orthogonal to the question I asked.
> > 
> > What in a clang based system normally provides __aeabi_*?
> > 
> > Your choices are "a libclang thing", "the libc", "something else".
> 
> Sorry I spent the last couple of hours to try to find who is providing
> the __aebi_* functions.
> 
> For userspace binary it's providing by the glibc.

Are we not telling clang not to use with libc (via --nostdlib or
similar)? I thought we did for gcc too but I can't actually see the
code. Actually maybe I wouldn't expect it to suppress this sort of
thing.

I see __eabi_memset even in a gcc based glibc, so I think this isn't
clang specific, just differences in the optmisers/inliners etc.

Anyhow, it looks like this is actually part of the ABI spec:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0043d/index.html

The correct wording for the commit message would therefore be something
like "Provide __aeabi_memset et al which are required by EABI and which
compilers expect to be provided by the libc implementation", or
something like that.

Ian.
Julien Grall March 26, 2014, 4:16 p.m. UTC | #9
On 03/26/2014 04:11 PM, Ian Campbell wrote:
> On Wed, 2014-03-26 at 16:01 +0000, Julien Grall wrote:
>> On 03/26/2014 03:47 PM, Ian Campbell wrote:
>>> On Wed, 2014-03-26 at 15:38 +0000, Julien Grall wrote:
>>>> On 03/26/2014 10:39 AM, Ian Campbell wrote:
>>>>> On Tue, 2014-03-25 at 18:12 +0000, Julien Grall wrote:
>>>>>> Hi Ian,
>>>>>>
>>>>>> On 03/25/2014 05:25 PM, Ian Campbell wrote:
>>>>>>> On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
>>>>>>>> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
>>>>>>>> for mem* function provided by Xen.
>>>>>>>
>>>>>>> Where are the references to these functions coming from if not from the
>>>>>>> compiler?
>>>>>>
>>>>>> Theses functions are called by the code generated by the compiler.
>>>>>
>>>>> And who normally provides them when building with clang? Some sort of
>>>>> libclang I guess?
>>>>
>>>> I've tried to compile a same compilation unit with gcc and clang. gcc is
>>>> inlining the call to __aebi_*.
>>>
>>> That is orthogonal to the question I asked.
>>>
>>> What in a clang based system normally provides __aeabi_*?
>>>
>>> Your choices are "a libclang thing", "the libc", "something else".
>>
>> Sorry I spent the last couple of hours to try to find who is providing
>> the __aebi_* functions.
>>
>> For userspace binary it's providing by the glibc.
> 
> Are we not telling clang not to use with libc (via --nostdlib or
> similar)? I thought we did for gcc too but I can't actually see the
> code. Actually maybe I wouldn't expect it to suppress this sort of
> thing.

We directly use ld to link the binary. So no need of --nosdtlib
--nolibgcc (see arch/arm/Makefile $(TARGET)-syms).

> I see __eabi_memset even in a gcc based glibc, so I think this isn't
> clang specific, just differences in the optmisers/inliners etc.
> 
> Anyhow, it looks like this is actually part of the ABI spec:
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0043d/index.html
> 
> The correct wording for the commit message would therefore be something
> like "Provide __aeabi_memset et al which are required by EABI and which
> compilers expect to be provided by the libc implementation", or
> something like that.

Thanks I will rework the commit message.
Tim Deegan March 26, 2014, 4:22 p.m. UTC | #10
At 16:11 +0000 on 26 Mar (1395846677), Ian Campbell wrote:
> On Wed, 2014-03-26 at 16:01 +0000, Julien Grall wrote:
> > On 03/26/2014 03:47 PM, Ian Campbell wrote:
> > > On Wed, 2014-03-26 at 15:38 +0000, Julien Grall wrote:
> > >> On 03/26/2014 10:39 AM, Ian Campbell wrote:
> > >>> On Tue, 2014-03-25 at 18:12 +0000, Julien Grall wrote:
> > >>>> Hi Ian,
> > >>>>
> > >>>> On 03/25/2014 05:25 PM, Ian Campbell wrote:
> > >>>>> On Tue, 2014-03-25 at 16:55 +0000, Julien Grall wrote:
> > >>>>>> Clang doesn't provide function __aebai_mem*, implement generically as a wrapper
> > >>>>>> for mem* function provided by Xen.
> > >>>>>
> > >>>>> Where are the references to these functions coming from if not from the
> > >>>>> compiler?
> > >>>>
> > >>>> Theses functions are called by the code generated by the compiler.
> > >>>
> > >>> And who normally provides them when building with clang? Some sort of
> > >>> libclang I guess?
> > >>
> > >> I've tried to compile a same compilation unit with gcc and clang. gcc is
> > >> inlining the call to __aebi_*.
> > > 
> > > That is orthogonal to the question I asked.
> > > 
> > > What in a clang based system normally provides __aeabi_*?
> > > 
> > > Your choices are "a libclang thing", "the libc", "something else".
> > 
> > Sorry I spent the last couple of hours to try to find who is providing
> > the __aebi_* functions.
> > 
> > For userspace binary it's providing by the glibc.
> 
> Are we not telling clang not to use with libc (via --nostdlib or
> similar)? I thought we did for gcc too but I can't actually see the
> code. Actually maybe I wouldn't expect it to suppress this sort of
> thing.
> 
> I see __eabi_memset even in a gcc based glibc, so I think this isn't
> clang specific, just differences in the optmisers/inliners etc.
> 
> Anyhow, it looks like this is actually part of the ABI spec:
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0043d/index.html
> 
> The correct wording for the commit message would therefore be something
> like "Provide __aeabi_memset et al which are required by EABI and which
> compilers expect to be provided by the libc implementation", or
> something like that.

+1.  AFAICT these are in the same class as functions like
__aeabi_idiv(), (which we already supply in /arm/arm32/lib/*.S), and
should be handled the same way.

Tim.
Julien Grall March 26, 2014, 4:39 p.m. UTC | #11
On 03/26/2014 04:22 PM, Tim Deegan wrote:
> At 16:11 +0000 on 26 Mar (1395846677), Ian Campbell wrote:

>> The correct wording for the commit message would therefore be something
>> like "Provide __aeabi_memset et al which are required by EABI and which
>> compilers expect to be provided by the libc implementation", or
>> something like that.
> 
> +1.  AFAICT these are in the same class as functions like
> __aeabi_idiv(), (which we already supply in /arm/arm32/lib/*.S), and
> should be handled the same way.

I didn't see any issues with an __aebi_*div* function. Shall we wait
until a failure?

Regards,
Ian Campbell March 26, 2014, 4:42 p.m. UTC | #12
On Wed, 2014-03-26 at 16:39 +0000, Julien Grall wrote:
> On 03/26/2014 04:22 PM, Tim Deegan wrote:
> > At 16:11 +0000 on 26 Mar (1395846677), Ian Campbell wrote:
> 
> >> The correct wording for the commit message would therefore be something
> >> like "Provide __aeabi_memset et al which are required by EABI and which
> >> compilers expect to be provided by the libc implementation", or
> >> something like that.
> > 
> > +1.  AFAICT these are in the same class as functions like
> > __aeabi_idiv(), (which we already supply in /arm/arm32/lib/*.S), and
> > should be handled the same way.
> 
> I didn't see any issues with an __aebi_*div* function. Shall we wait
> until a failure?

We already have the ones which get generated in practice.

Ian.
Tim Deegan March 26, 2014, 4:46 p.m. UTC | #13
At 16:39 +0000 on 26 Mar (1395848341), Julien Grall wrote:
> On 03/26/2014 04:22 PM, Tim Deegan wrote:
> > At 16:11 +0000 on 26 Mar (1395846677), Ian Campbell wrote:
> 
> >> The correct wording for the commit message would therefore be something
> >> like "Provide __aeabi_memset et al which are required by EABI and which
> >> compilers expect to be provided by the libc implementation", or
> >> something like that.
> > 
> > +1.  AFAICT these are in the same class as functions like
> > __aeabi_idiv(), (which we already supply in /arm/arm32/lib/*.S), and
> > should be handled the same way.
> 
> I didn't see any issues with an __aebi_*div* function. Shall we wait
> until a failure?

What I was trying to say is: we already supply the __aebi_*div*
functions, so adding the __aeabi_memset ones is correct.

Cheers,

Tim.
Julien Grall March 26, 2014, 4:52 p.m. UTC | #14
On 03/26/2014 04:46 PM, Tim Deegan wrote:
> At 16:39 +0000 on 26 Mar (1395848341), Julien Grall wrote:
>> On 03/26/2014 04:22 PM, Tim Deegan wrote:
>>> At 16:11 +0000 on 26 Mar (1395846677), Ian Campbell wrote:
>>
>>>> The correct wording for the commit message would therefore be something
>>>> like "Provide __aeabi_memset et al which are required by EABI and which
>>>> compilers expect to be provided by the libc implementation", or
>>>> something like that.
>>>
>>> +1.  AFAICT these are in the same class as functions like
>>> __aeabi_idiv(), (which we already supply in /arm/arm32/lib/*.S), and
>>> should be handled the same way.
>>
>> I didn't see any issues with an __aebi_*div* function. Shall we wait
>> until a failure?
> 
> What I was trying to say is: we already supply the __aebi_*div*
> functions, so adding the __aeabi_memset ones is correct.

Sorry I misunderstood your previous comment.
diff mbox

Patch

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 63e0460..43344c0 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -33,6 +33,7 @@  obj-y += hvm.o
 obj-y += device.o
 obj-y += decode.o
 obj-y += processor.o
+obj-$(clang) += eabi.o
 
 #obj-bin-y += ....o
 
diff --git a/xen/arch/arm/eabi.c b/xen/arch/arm/eabi.c
new file mode 100644
index 0000000..f01618c
--- /dev/null
+++ b/xen/arch/arm/eabi.c
@@ -0,0 +1,29 @@ 
+/*
+ * EABI routines
+ */
+
+#include <xen/types.h>
+#include <xen/lib.h>
+
+void __aeabi_memcpy(void *dest, const void *src, size_t n)
+{
+	(void)memcpy(dest, src, n);
+}
+
+void __aeabi_memmove(void *dest, const void *src, size_t n)
+{
+	(void)memmove(dest, src, n);
+}
+
+void __aeabi_memset(void *s, size_t n, int c)
+{
+	(void)memset(s, c, n);
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */