Are macro definitions compatible between MIPS and Intel C compiler? - c

I seem to be having a problem with a macro that I have defined in a C program.
I compile this software and run it sucessfully with the MIPS compiler.
It builds OK but throws the error "Segmentation fault" at runtime when using icc.
I compiled both of these on 64 bit architectures (MIPS on SGI, with -64 flag and icc on an intel platform).
Is there some magic switch I need to use to make this work correctly on both system? I turned on warnings for the intel compiler, and EVERY one of the places in my program where a macro is invoked throws a warning. Usually something along the lines of mismatched types on the macro's parameters (int to char *) or some such thing.
Here is the offending macro
#define DEBUG_ENTER(name) {tdepth++;
if(tnames[tdepth] == NULL) tnames[tdepth] = memalign(8, sizeof(char)*MAXLEN);
strcopy(tnames[tdepth],name);
FU_DEBUG("Entering \n");}
This basically is used for debugging - printing to a log file with a set number of tabs in based on how many function calls there are. (tdepth = tab depth)
I did some checking around in man pages. it seems like memalign is only supported on IRIX. This may be my problem. I am going to track it down.

This might have to do with the system's "endianness." Looking here it seems that MIPS has switchable endianness. I'm not sure if you are using the correct endianness already, but if you aren't, you will DEFINATELY have problems.

This might be a byte order issue. MIPS can be big endian but intel is little endian.

It sounds like the array tnames is an array of int. If you're assigning pointers to it, it should be an array of a pointer type - in this case probably char * is appropriate.
(Also, strcopy() isn't a standard function - are you sure you don't mean strcpy()?)

Related

Should one use Named Address Spaces where they are available?

There are some architectures which have multiple address spaces, notable examples are true Harvard ones, but for example OpenCL also has this property.
C compilers may provide some solutions to this, one of these is Named Address Spaces, supporting special pointer qualifiers to indicate the pointer's address space, but other solutions might also be present.
For GCC, the corresponding documentation is here: https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Named-Address-Spaces.html
For IAR targeting the AVR, the corresponding documentation is here: https://www.iar.com/support/tech-notes/compiler/strings-with-iccavr-2.x/ (note that this is earlier than GCC's support, which GCC likely adapted for the 8 bit AVR target).
For SDCC (Small Device C compiler): http://sdcc.sourceforge.net/doc/sdccman.pdf , starts on Page 36. Covers microcontrollers like the 8051, Z80 and 68HC08.
Some information for OpenCL: https://www.khronos.org/registry/OpenCL/sdk/1.1/docs/man/xhtml/local.html and https://software.intel.com/en-us/articles/the-generic-address-space-in-opencl-20
I didn't know about them, and on the architecture I am using (8 bit AVR), there is another solution to deal with the problem, specialized macros (pgmspace.h) to work with data in the ROM. But there are no type checks on these, and they (in my opinion) make code ugly, so it would seem to me that using Named Address Spaces are a superior, and possibly even more portable way to deal with the problem (portable in that one could easily port such a software to a target having a single address space by providing empty definitions for the address space qualifiers).
However in a previous question in which I learned from their availability, solutions suggesting the use of Named Address Spaces got severely downvoted, here: How to make two otherwise identical pointer types incompatible
Downvoters didn't provide any explanation, and I neither found any myself, for me it seems like Named Address Spaces are a good and perfectly functional way of dealing with the problem.
Could anyone provide an explanation? Why Named Address Spaces probably shouldn't be used? (favoring whatever other method available on the target having multiple distinct address spaces)
Another approach is to steal a technique used in things like the Linux kernel and tools like smatch.
Linux has defines like
#define __user
which mean the code can say things like int foo(const __user char *p). The compiler ignores the __user but tools like smatch are then used to make sure that pointers don't accidentally wander between namespaces.
The problem with these is obvious: they only work on the gcc compiler.
And in the embedded systems branch there are lots of different compilers, each offering its own unique, non-portable way to do this. Sometimes that is fine (most embedded projects never get ported to different compilers) but from a generic point-of-view, it is not.
(The very same issue also exists with extended addresses - if you would for example use a 8 or 16 bit MCU with more than 64kib addressable memory. Compilers then use various non-standard extensions such as near and far.)
One solution to these problems is to make a "wrapper" around the compiler-specific behavior, by making a hardware abstraction layer (HAL) where you specify that the type used for storing data in flash is flash_byte_t or some such, then from your HAL include a compiler-specific header-file containing the actual typedef, such as typedef const __flash uint8_t flash_byte_t;. For example, the application includes "compiler.h" and this one in turn includes "gcc.h". That way you only need to re-write one small header file when you switch compiler.
Also as it turns out, C allows const flash_byte_t just fine even though this was already typedef'd as const. There's a special odd rule in C saying that you can add the same qualifier as many times in a declaration as you like. So const const int x is equivalent to const int x. This means that if the user would put on extra const-qualification, that's fine.
Note that it's mostly AVR being a special exception here, because of its weird Harvard model.
Otherwise, there's an industry de facto standard convention used by most compilers: all const qualified variables with static storage duration should be allocated in flash. Of course the C standard makes no guarantees of this (it is out of scope of the standard), but most embedded compilers behave like that.

how to enable __far in gcc cygwin

I am having some trouble compiling my code having __far.
I have read that __far is not a c standard keyword.
furthermore, this is in relation to the use of rl78 compiler.
C Implementations for architectures with non-flat address spaces, usually had those two pointer "classes":
near pointers that store the offset within a memory segment
far pointers that additionally specify what segment
Many compilers implemented the latter using a non-standard __far specifier. The 16-bit x86 used to be such an architecture.
But Cygwin is only available for 32 bit x86 and x86_64 versions of Windows. And on those there is no concept of near and far pointer anymore.
In order to compile your code, you will need to strip away the __fars and hope that the code itself isn't too tightly coupled to your original architecture.

Calculate an arbitrary type's size without executing a program

Given any type in a C program, I would like to know it's size, such as one would when executing the following line,
printf("%d\n",sizeof(myType));
without actually executing the program. The solution must work with arbitrary types whose size can be determined at compile time, such as user-defined structs.
The rationale is that, if it can be known at compile time, there should be a way to extract that information without having to run the program. Possibly something a bit more elegant than having to parse the resulting assembler source or binary for literal contstants, but if that's the only way, I'll take what I can get.
This question doesn't quite work for me, since OP's solution relies on executing the code, and the most voted answer relies on the preprocessor info directive actually expanding macros (my toolchain doesn't apparently).
For background, I'm developing for PIC18 MCUs and using the XC8 compiler.
What I ultimately want is to verify that some structures I've defined take up their expected size in memory.
This is a classic use case for static assertions. If your compiler supports _Static_assert, you can write
_Static_assert(sizeof(mystruct) == expected_size, "Invalid struct size.");
demo 1
If you use an older compiler that does not support C-1x yet, use a common work-around that relies on declaring an array type with negative size:
#define CHECK_SIZE(x,e) if(sizeof(char[2*(sizeof(x)==e)-1])==1);
demo 2

why do we use far keyword in c? [duplicate]

const struct sockaddr FAR* name,
It's an old extension from the era of segmented memory architectures. It basically means "this is a pointer that needs to be able to point at any address, not just things in the same segment as the code using it".
See more or on the wikipedia page.
far doesn't mean anything in C. Check out the C99 standard [PDF] and see if you can find mention of far pointers. Far pointers were an extension added to compilers targeting the 8086/80286 architectures to provide support for the segmented memory model.
If does nothing unless you happen to be using a 16 bit x86 compiler.
If you look in the Win32 header WinDef.h (in Visual Studio, simply right-click the word FAR in the source and select "Go to Definition", you will see that it is a macro defined as far, which in turn is also a macro defined as nothing at all!
It is only there to allow the compilation of legacy Win16 source as Win32. In 16 bit x86 compilers, far was a compiler extension keyword to support seg::offset pointers which resolve to a 20bit address (16 bit x86 only had a 1Mb address space!). They are distinct from 16 bit near pointers which comprised only the ::offset from the current segment.

What does Far mean in c?

const struct sockaddr FAR* name,
It's an old extension from the era of segmented memory architectures. It basically means "this is a pointer that needs to be able to point at any address, not just things in the same segment as the code using it".
See more or on the wikipedia page.
far doesn't mean anything in C. Check out the C99 standard [PDF] and see if you can find mention of far pointers. Far pointers were an extension added to compilers targeting the 8086/80286 architectures to provide support for the segmented memory model.
If does nothing unless you happen to be using a 16 bit x86 compiler.
If you look in the Win32 header WinDef.h (in Visual Studio, simply right-click the word FAR in the source and select "Go to Definition", you will see that it is a macro defined as far, which in turn is also a macro defined as nothing at all!
It is only there to allow the compilation of legacy Win16 source as Win32. In 16 bit x86 compilers, far was a compiler extension keyword to support seg::offset pointers which resolve to a 20bit address (16 bit x86 only had a 1Mb address space!). They are distinct from 16 bit near pointers which comprised only the ::offset from the current segment.

Resources