I am trying to write an assembly function without using c prototypes.
For some reason it looks like the gcc doesn't allow to use extended asm in the global context.
Please consider the following code that compiles succssefully:
void *g_var;
void foo()
{
asm ("stx %%i7, [%0]"
:"=r" (g_var));
}
When I am also trying to define the prototype using asm, as follows:
asm(".global foo2\n\t"
"foo2:\n\t");
asm ("stx %%i7, [%0]"
:"=r" (g_var));
the compiler give me the following error as if extended asm cannot be used in global context.
foo.c:151:2: error: expected ')' before ':' token :"=r"
(return_addr)); ^
Please note that when I don't use extened asm as follows, the compiler approves the code:
asm(".global foo2\n\t"
"foo2:\n\t");
asm("jmpl %o7 + 8, %g0\n\t");
Thanks.
From the GCC Documentation:
Note that extended asm statements must be inside a function. Only basic asm may be outside functions (see Basic Asm). Functions declared with the naked attribute also require basic asm (see Function Attributes).
So the answer to your question is that - no it isn't possible to use extended assembler templates outside a function in the global context. As you have found basic assembler statements are allowed.
Related
I am trying to understand the preprocessor directives (like #if , #ifdef, #ifndef) and following is the code I have tried out.
Note: The member functions are further wrapped and used in python and hence the results show the python like calls but this does not affect any of the c++ process.
Question: 1. As per my understanding the global variables have a scope of whole file from the point it is declared. Then in this case, why is the defined value not accepted inside another function?
Requirement: I want to do something like mentioned below:
void Somefunc(int val){
set variable x;
}
Based on the x value, I want to include functions. Now the condition is:
If x=1, only some functions should be compiled since others utilize headers which would throw errors with the compiler I am using.
Thanks in advance!
Preprocessing runs before compilation. It handles the source code as plain text, it doesn't care for C++ language semantics.
The reason why var is not defined is that a preprocessor definition is valid from the point of definition until the end of the file (preprocessed translation unit) or a corresponding #undef.
Is it possible to write inline assembly (Intel syntax) with GCC or Clang, without needing to understand the clobber list "stuff"?
I'm going to guess "no" because the clobber list "stuff" ensures you don't over-write the register the compiler wrote to (immediately before your inline assembly begins)?
GNU C Basic inline asm statements (no operand/clobber lists) are not recommended for basically anything except maybe the body of an __attribute__((naked)) function. Why can't local variable be used in GNU C basic inline asm statements? (globals can't safely be used either.)
https://gcc.gnu.org/wiki/DontUseInlineAsm says to see ConvertBasicAsmToExtended for reasons not to use Basic asm statements. You can't really do anything safely in Basic asm; even asm("cli"); can get reordered with any memory accesses that aren't volatile.
If you're going to use inline asm at all (instead of writing a stand-alone function in asm, or C with intrinsics), you need to describe your string of asm instruction in exact detail to the compiler, in terms of a black box with input and/or output operands, and/or clobbers. See https://stackoverflow.com/tags/inline-assembly/info for links to guides, including some SO answers about using input / output constraints.
Think hard before deciding it's really worth using GNU C inline asm for anything. If you can get the compiler to emit the same instructions another way, that's almost always better. Intrinsics or pure C allow constant-propagation optimization; inline asm doesn't (unless you do stuff like if(_builtin_constant_p(x)) { pure C version } else { inline asm version }).
Intel syntax: in GCC, compile with -masm=intel so your asm template will be part of an Intel-syntax .s, and the compiler will substitute in operands in Intel syntax. (Like dword ptr [rsp] instead of (%rsp) for "m"(my_int)).
In clang I'm not sure there's any convenient way to use Intel-syntax in normal asm statements.
There is one other option though, if you don't care about efficient code (but then why are you using asm?): clang supports -fasm-blocks to allow syntax like MSVC's inefficient style of inline asm. And yes, this uses Intel syntax.
Is there any way to complie a microsoft style inline-assembly code on a linux platform? shows how inefficient the resulting code is: full of compiler-generated instructions to store input variables to memory for the asm{} block to read them. Because MSVC-style asm blocks can't do inputs or outputs in registers. (Clang doesn't support the leave-a-value-in-EAX method for getting a single value out so the output has to be stored/reloaded as well.)
You don't get to specify clobbers for this, so I assume an asm block implies a "memory" clobber, along with clobbers on all registers you write. (Or maybe even just mention.)
I would not recommend this; it's basically not possible to wrap a single instruction or handful of instructions efficiently this way. Only if you're writing a whole loop can you amortize the overhead of getting inputs into an asm{} block.
I'm using CodeBlocks and GCC compiler. I'd like to use "string safe functions" e.g strlen_s, strcpy_s, but compiler shows an error:
Undefined reference to strlen_s.
I then add a line to the code:
#define __STDC_WANT_LIB_EXT1__ 1
As well as writing the following in the Compiler Options (settings -> compiler -> global compiler settings -> other compiler options):
-std=c11
In the book that I'm reading there's a code to checking whether my compiler supports these functions. The code is as follows:
#include <stdio.h>
int main()
{
#if defined __STDC_WANT_LIB_EXT1__
printf("optional functions are defined");
#else
printf("optional functions are not defined");
#endif
return 0;
}
When I run this code I see "optional functions are defined". I've also reinstalled CodeBlocks but I still get these errors.
Should I install another compiler? If I should, which one will be the best?
#define __STDC_WANT_LIB_EXT1__ 1 is expected to be defined by your application - you have to define it yourself to enable the use of the bounds-checking interface functions.
In order to see if the bounds-checking interface is at all available, you need to check if __STDC_LIB_EXT1__ is defined by the compiler.
Note that no function called strlen_s exists.
This test is not sufficient, you should also test whether the implementation defines the macro __STDC_LIB_EXT1__.
These functions are from a part of the C standard that is called "Annex K" and that is optional. With this macro you test if your C library provides that feature, with the WANT macro defined before any includes you tell the compiler that you want to use these features from Annex K.
Annex K is much controversial, and not many public domain C libraries implement it. Many people think that its interfaces don't provide the security that it claims.
And for the book that you are reading this doesn't seem to be too reliable. But then, I may be biased on that point.
I've got an application written in pure C, mixed with some functions that contain pure ASM. Naked attribute isn't available for x86 (why? why?!) and my asm functions don't like when prologue and epilogue is messing with the stack. Is it somehow possible to create a pure assembler function that can be referenced from C code parts? I simply need the address of such ASM function.
Just use asm() outside a function block. The argument of asm() is simply ignored by the compiler and passed directly on to the assembler. For complex functions a separate assembly source file is the better option to avoid the awkward syntax.
Example:
#include <stdio.h>
asm("_one: \n\
movl $1,%eax \n\
ret \n\
");
int one();
int main() {
printf("result: %d\n", one());
return 0;
}
PS: Make sure you understand the calling conventions of your platform. Many times you can not just copy/past assembly code.
PPS: If you care about performance, use extended asm instead. Extended asm essentially inlines the assembly code into your C/C++ code and is much faster, especially for short assembly functions. For larger assembly functions a seperate assembly source file is preferable, so this answer is really a hack for the rare case that you need a function pointer to a small assembly function.
Good news everyone. GCC developers finally implemented attribute((naked)) for x86. The feature will be available in GCC 8.
Certainly, just create a .s file (assembly source), which is run through gas (the assembler) to create a normal object file.
I am trying to compile some legacy code with more modern toolchains. I have tracked down one of my issues to the switch from gcc 4.6 to gcc 4.7:
Some of the functions are annotated with the inline keyword. Gcc fails on these with the error message:
error: inlining failed in call to always_inline 'get_value_global': function body not available
What is the correct way of dealing with this issue? How could the function body not be available? Should the compiler not make sure that it is available in all situations that require it?
Edit
As requested (in a deleted comment), an example of a signature of a function resulting in the error:
inline struct a_value_fmt const *find_a_value_format(struct base_fmt *base)
{
/* the code */
}
That error is typical to inline functions declared in source files, rather than in header files, in which case the compiler is not able to inline them (as the code of the function to be inlined must be visible to the compiler in the same source file being compiled). So, first thing I would check is that all functions declared inline are indeed defined in header files.
It may be that a change in GCC diagnostics in 4.7 caused the error to surface, and that it went silent in GCC 4.6 (but that's just a speculation).
The quoted error indicates that the function is declared with __attribute__((always_inline)). Note that GCC may fail to inline and report a different (and quite obscure) error if function is declared always_inline, but not with the inline keyword - so make sure that any function declared as always_inline is also declared as inline.
Few more tips:
General advice, which may not be applicable: since this is a legacy codebase, you may want to re-evaluate which functions should be inlined, being on the critical path, and which aren't, based on updated profiling results. Sometimes, inline is used generously, even when it is not required, or redundant. In some cases, the fix may be to remove the inline keyword in places where it is not needed.
When functions are declared in header files, the compiler considers them for inlining automatically (given they are small enough, and the compiler thinks that inlining them will improve performance, based on its heuristics) - even when the inline keyword is not used. inline is sort of a "recommendation" to the compiler, and it doesn't have to obey (unless it is given along with the always_inline attribute).
Modern compilers make relatively smart inlining decisions, so it's usually best to let the compiler do it's thing, and declare functions as inline (and moving their implementations to header files) in the appliation hot spots, based on profiling results.