How to translate C headers contain gcc __attribute__?

General FreeBASIC programming questions.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 27, 2020 14:51

It's __attribute__((const)) and __attribute__((pure)) and __attribute__ ((__deprecated__)). fbfrog failed to translate them and marked as TODO. What could I do with them? From my own little research, I think just commented them out. But I'm not sure.

I know with __attribute__ ((__deprecated__)) it means the function is deprecated. But my code still using these functions so I can't simply commented them out. So I just don't care about it and remove __attribute__ ((__deprecated__))? Is there any equivalent to these __attribute__ on FreeBASIC so I could accurately translate the headers?
marcov
Posts: 3004
Joined: Jun 16, 2005 9:45
Location: Eindhoven, NL
Contact:

Re: How to translate C headers contain gcc __attribute__?

Postby marcov » Apr 27, 2020 15:10

(general attribute lists:

Many compiler often reduce modifiers to lists. IOW instead of having a special "stdcall" modifier, you say __attribute[stdcall]. If the procedure is also inline you go __attribute[stdcall,inline]. Etc etc.

The advantage is that other (non compiler, think documentation parsers, LINTs etc) don't have to change their grammar for each new modifier. They just copy whatever is in the attribute list, and reproduce it when necessary.

So each and every feature has to be implemented separately, unless you are a transpiler, then you can just "hope" to copy them to the output. But usually attributes are horribly compiler dependent, so it chains you to one certain compiler as backend.
)

pure probably means that functions don't have sideeffects (like reading from or writing to global variables), which makes them candidates for inlining and other very heavy optimizations. IOW the function always gives the same result for the same parameters. It can be safely left alone, since you can't inline over cross language header anyway.

Deprecated is usually just a marker for warning/hint generation that the symbol is "old". In FPC we use it to mark identifiers that are scheduled for removal in future versions. (there are also other variants like "experimental", to mark identifiers that are not part of an official interface, iow not guaranteed to exist in future versions). It doesn't change codegeneration.

I assume const (as a function/sub/procedure modifier) has something to do to assume that all parameters are not modified. On constants you expect it to mean "put them in the const segment if possible". If my first guess (unmodified parameters) is right, it could have meaning for header translators too, unlike the other two. Worse CONSTness rules vary with architecture and even target.

So I looked it up and it seems to be different:

The const attribute prohibits a function from reading objects that affect its return value between successive invocations. However, functions declared with the attribute can safely read objects that do not change their return value, such as non-volatile constants.


This sounds like it is a kind of helper for pure. Doing anything im-pure (pun intended) will cause an error. One could argue that pure is meant for the interface/header (to signal purity), and const is helping implement it and keeping it pure.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 27, 2020 15:41

marcov wrote:(general attribute lists:

Many compiler often reduce modifiers to lists. IOW instead of having a special "stdcall" modifier, you say __attribute[stdcall]. If the procedure is also inline you go __attribute[stdcall,inline]. Etc etc.

The advantage is that other (non compiler, think documentation parsers, LINTs etc) don't have to change their grammar for each new modifier. They just copy whatever is in the attribute list, and reproduce it when necessary.

So each and every feature has to be implemented separately, unless you are a transpiler, then you can just "hope" to copy them to the output. But usually attributes are horribly compiler dependent, so it chains you to one certain compiler as backend.
)

pure probably means that functions don't have sideeffects (like reading from or writing to global variables), which makes them candidates for inlining and other very heavy optimizations. IOW the function always gives the same result for the same parameters. It can be safely left alone, since you can't inline over cross language header anyway.

Deprecated is usually just a marker for warning/hint generation that the symbol is "old". In FPC we use it to mark identifiers that are scheduled for removal in future versions. (there are also other variants like "experimental", to mark identifiers that are not part of an official interface, iow not guaranteed to exist in future versions). It doesn't change codegeneration.

I assume const (as a function/sub/procedure modifier) has something to do to assume that all parameters are not modified. On constants you expect it to mean "put them in the const segment if possible". If my first guess (unmodified parameters) is right, it could have meaning for header translators too, unlike the other two. Worse CONSTness rules vary with architecture and even target.

So I looked it up and it seems to be different:

The const attribute prohibits a function from reading objects that affect its return value between successive invocations. However, functions declared with the attribute can safely read objects that do not change their return value, such as non-volatile constants.


This sounds like it is a kind of helper for pure. Doing anything im-pure (pun intended) will cause an error. One could argue that pure is meant for the interface/header (to signal purity), and const is helping implement it and keeping it pure.


Thank you. But I already search before ask. The guy here explains it more easier to understand than you: https://stackoverflow.com/questions/291 ... e-in-gnu-c

I have nothing to hide that I'm translating the GNUTLS headers. I need to use functions from GNUTLS. I found it weirded that FreeBASIC doesn't already include openssl headers. Anyway, I choose to go with GNUTLS. If you know how to translate it to FreeBASIC, please help. I think I can only remove all of these attributes but I think the performance of my app will be awful if I doing so because it can't cache the function result but instead call it again and again so caused massive slow down.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 27, 2020 16:20

Anyone could help?

I also want to ask how to deal with C header use inline. As I know, FreeBASIC doesn't support inlining. So could I just remove the inline keyword?
marcov
Posts: 3004
Joined: Jun 16, 2005 9:45
Location: Eindhoven, NL
Contact:

Re: How to translate C headers contain gcc __attribute__?

Postby marcov » Apr 27, 2020 16:43

systemctl wrote:Anyone could help?

I also want to ask how to deal with C header use inline. As I know, FreeBASIC doesn't support inlining. So could I just remove the inline keyword?


Yes. Same with pure and the rest, probably not supported by at least the GAS backends since it is a bit more advanced functionality. Maybe supported by the GCC backend, if FB just passes through such attributes, but that shoule be easily checked by seeing if FB accepts it and then checking the generated C.

if I read that SO link,than my guesswork was wrong, and is const just pure++.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 27, 2020 17:10

marcov wrote:
systemctl wrote:Anyone could help?

I also want to ask how to deal with C header use inline. As I know, FreeBASIC doesn't support inlining. So could I just remove the inline keyword?


Yes. Same with pure and the rest, probably not supported by at least the GAS backends since it is a bit more advanced functionality. Maybe supported by the GCC backend, if FB just passes through such attributes, but that shoule be easily checked by seeing if FB accepts it and then checking the generated C.

if I read that SO link,than my guesswork was wrong, and is const just pure++.


Not supported at all. My test:

Code: Select all

__attribute__((const)) __attribute__ ((__deprecated__)) function test(byval x as long, byval y as long) as long
  return x + y
end function

print test(1,2)
print


Put __attribute__((const)) __attribute__ ((__deprecated__)) behind as long also failed to compile.

I build with fbc -gen gcc test.bas, it will be clearer when you put -r in: fbc -gen gcc -r test.bas. I checked the generated C source, it does use __attribute__ inside it but ironically it doesn't support __attribute__ in the BASIC source.

My system is amd64 so gen gcc is the default, it's not really needed to specify.

Anyway, what do you think about the out come if I just removed these attributes? I guest my app will be awfully slow but at least could be compiled.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 27, 2020 18:37

I have done the translation for GNUTLS by removed all of these attributes. However the library I want to port uses too much C only features make it impossible to port to FreeBASIC. It's a Web framework for the C language. If ported to FreeBASIC we will have a lot of fun.

It's ulfius. I also tried to port kore, facil and onion. All of them failed because of the reason above. The C language is not suitable for this kind of job at all, so they have to use tricks, and these tricks are heavily depend on the C only features so it's not portable.
TeeEmCee
Posts: 298
Joined: Jul 22, 2006 0:54
Location: Auckland

Re: How to translate C headers contain gcc __attribute__?

Postby TeeEmCee » Apr 30, 2020 15:45

Actually, FB does kind of support inlining functions. Define a function as PRIVATE. This gets translated to "static" in the emitted C when using -gen gcc. This encourages GCC to inline the function. Marking a function as "inline" in C only hints to the compiler to inline, anyway (as well as visibility/linkage effects). Of course under -gen gas there's no inlining.

But based on my reading of marcov's investigation, you can drop all of those attributes you mentioned.

What were the C-only features that you couldn't translate to FB? More GCC C extensions? There aren't many features of C that don't translate to FB.
Last edited by TeeEmCee on Apr 30, 2020 15:47, edited 1 time in total.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 30, 2020 15:47

TeeEmCee wrote:Actually, FB does kind of support inlining functions. Define a function as PRIVATE. This gets translated to "static" in the emitted C when using -gen gcc. This encourages GCC to inline the function. Marking a function as "inline" in C only hints to the compiler to inline, anyway (as well as visibility/linkage effects).

But based on my reading of marcov's investigation, you can drop all of those attributes you mentioned.

What were the C-only features that you couldn't translate to FB? More GCC C extensions?


A macro to emulate foreach. I will find and post it here.
Last edited by systemctl on Apr 30, 2020 15:55, edited 1 time in total.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 30, 2020 15:51

It's here:

Code: Select all

#define json_object_foreach(object, key, value)                                          \
    for (key = json_object_iter_key(json_object_iter(object));                           \
         key && (value = json_object_iter_value(json_object_key_to_iter(key)));          \
         key = json_object_iter_key(                                                     \
             json_object_iter_next(object, json_object_key_to_iter(key))))

#define json_object_foreach_safe(object, n, key, value)                                  \
    for (key = json_object_iter_key(json_object_iter(object)),                           \
        n = json_object_iter_next(object, json_object_key_to_iter(key));                 \
         key && (value = json_object_iter_value(json_object_key_to_iter(key)));          \
         key = json_object_iter_key(n),                                                  \
        n = json_object_iter_next(object, json_object_key_to_iter(key)))

#define json_array_foreach(array, index, value)                                          \
    for (index = 0;                                                                      \
         index < json_array_size(array) && (value = json_array_get(array, index));       \
         index++)


The full file is here: https://github.com/akheron/jansson/blob ... /jansson.h
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 30, 2020 15:52

I also have trouble translate these lines, in the same file above, too:

Code: Select all

#if defined(__GNUC__) || defined(__clang__)
static JSON_INLINE void json_decrefp(json_t **json) {
    if (json) {
        json_decref(*json);
        *json = NULL;
    }
}

#define json_auto_t json_t __attribute__((cleanup(json_decrefp)))
#endif
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 30, 2020 15:54

TeeEmCee wrote:But based on my reading of marcov's investigation, you can drop all of those attributes you mentioned.


I think there are attributes that can't be simply dropped. Like the attribute cleanup I posted above.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to translate C headers contain gcc __attribute__?

Postby systemctl » Apr 30, 2020 16:01

systemctl wrote:
TeeEmCee wrote:But based on my reading of marcov's investigation, you can drop all of those attributes you mentioned.


I think there are attributes that can't be simply dropped. Like the attribute cleanup I posted above.


More information about these attributes: https://gcc.gnu.org/onlinedocs/gcc/Comm ... butes.html

It's difficult for me to understand them, though. It's nothing surprise if I interpreted them wrong.
marcov
Posts: 3004
Joined: Jun 16, 2005 9:45
Location: Eindhoven, NL
Contact:

Re: How to translate C headers contain gcc __attribute__?

Postby marcov » Apr 30, 2020 20:30

systemctl wrote:I have nothing to hide that I'm translating the GNUTLS headers. I need to use functions from GNUTLS. I found it weirded that FreeBASIC doesn't already include openssl headers. Anyway, I choose to go with GNUTLS. If you know how to translate it to FreeBASIC, please help. I think I can only remove all of these attributes but I think the performance of my app will be awful if I doing so because it can't cache the function result but instead call it again and again so caused massive slow down.


A cache is dynamic. A compiler is static. So only if you e.g. call the function twice with the same arguments (and that being verifiable compiletime!) in the same SUB (or Main()), otherwise it will not do much. Sometimes other optimizations can increase the scope somewhat beyond functions (e.g. inline, LTO for leaf functions), but in general these are not the most worthwhile optimizations for human made code, I think.

Such optimizations are often more important if you compile C code generated by a high level transpiler (and probably (much) more highlevel than fb's gcc backend), or for embedded applications that are relatively small, use a relative small language subset, and therefore can be very agressively globally optimized.

Though maybe in some case it might be able to hoist function calls out of loops.

note: added the remark about embedded applications. Worked on embedded today, so suddenly remembered that ;-)
Last edited by marcov on May 01, 2020 11:39, edited 1 time in total.
TeeEmCee
Posts: 298
Joined: Jul 22, 2006 0:54
Location: Auckland

Re: How to translate C headers contain gcc __attribute__?

Postby TeeEmCee » May 01, 2020 8:13

You could translate json_object_foreach to:

Code: Select all

#macro json_object_foreach(object, key, value)
   key = json_object_iter_key(json_object_iter(object))
   while key
      value = json_object_iter_value(json_object_key_to_iter(key))
      if value = 0 then exit while
#endmacro

#macro end_json_object_foreach(object, key, value)
      key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key)))
   wend
#endmacro


Yes, you couldn't translate the "cleanup" to FB (cool, I didn't know GCC had that). Well, unless you created a class with a destructor. But you'll just have to omit json_auto_t, it's only a convenience anyway.

Return to “General”

Who is online

Users browsing this forum: No registered users and 5 guests