GCC Vector Extensions: AVX2 builtin shuffle crashes when m64 is used - c

I have the following program in Mingw, gcc 4.9.2:
#include <stdio.h>
#include <stdint.h>
#define VECSIZE 32
typedef char byteVec __attribute__ ((vector_size (VECSIZE)));
#define PERMLEFT_BVEC (byteVec){63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}
byteVec permute(byteVec x, byteVec y) {
return __builtin_shuffle(x,y,PERMLEFT_BVEC);
}
void print_vec32b(byteVec a) {
printf("[ ");
int i; for (i = 0; i < 32; ++i) printf("%d ", a[i]);
puts("]");
}
int main() {
byteVec x = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
byteVec y = {11,12,13,14,15,16,17,18,19,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,88,89,90,91,92};
byteVec z = permute(x,y);
print_vec32b(x);
return 0;
}
When I compile this program with -m64, it crashes. With -m32 it works fine. Optimization level doesn't matter. I don't understand what's going on. I've also tried TDM with GCC 5.1.0. Same thing. Anybody have any advice? Is it something screwy with GCC in Windows?
Here is the assembly produced by the compiler (note how the shuffle is turned into a permutation automatically, with vperm2i128 and vpalignr, which is the desired behavior:
GCC Explorer
Minimal program: above.
Desired behavior: print permuted byte vector (which it does in 32-bit mode).
Expected output (works in 32-bit mode):
$ gcc nvec.c -m32 -mavx2 -o a.exe && a.exe
[ 92 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ]
Actual result: crash.
Description of crash: immediate crash, windows error reporting bug shows up. No errors or warnings.

Related

How to install and include a library to my C compiler?

I am using Debian 11
I am trying to reproduce strlcpy.
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4
5 unsigned int ft_strlcpy(char *dest, char *src, unsigned int size)
6 {
7 unsigned int i;
8
9 i = 0;
10 while (src[i] && i < size)
11 {
12 dest[i] = src[i];
13 i++;
14 }
15 dest[i] = '\0';
16 while (src[i])
17 i++;
18 return (i);
19 }
20
21 int main()
22 {
23 unsigned int i;
24 char *dest1 = malloc(sizeof(char) * 50);
25 char *dest2 = malloc(sizeof(char) * 50);
26
27 i = 0;
28 while (i < 26)
29 {
30 printf("%d ", ft_strlcpy(dest1, "hello my name is marcel", i));
31 printf("%s\n", dest1);
32 printf("%ld ", strlcpy(dest2, "hello my name is marcel", i));
33 printf("%s\n", dest2);
34 i++;
35 }
36 free(dest1);
37 free(dest2);
38 return (0);
39 }
However, I get this message when I compile my code:
ft_strlcpy.c: In function ‘main’:
ft_strlcpy.c:32:18: warning: implicit declaration of function ‘strlcpy’; did you mean ‘strncpy’? [-Wimplicit-function-declaration]
32 | printf("%ld ", strlcpy(dest2, "hello my name is marcel", i));
| ^~~~~~~
| strncpy
/usr/bin/ld: /tmp/ccukR8g6.o: in function `main':
ft_strlcpy.c:(.text+0xf0): undefined reference to `strlcpy'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: ft_strlcpy] Error 1
I have no idea how to include libbsd or use pkgconf.
I have tried for a couple of hours, but I couldn't find the solution.
If someone could redirect me to a manual or explain the concepts, that would be great.
Thank you for your help!
The strlcpy function is included in the BSD libc, a superset (extended version) of the POSIX standard library for BSD operating systems. For it to be recognized by the compiler you have to first install the library through your package manager, the name of which will be either libbsd, libbsd-dev or libbsd-devel depending on whether your distribution uses seperate development libraries or not, and than include it as <bsd/string.h>. You can then compile it with (assuming you use GCC) gcc <your-filename>.c -lbsd, specifying the library to be linked. I wouldn't recommended using BSD functions outside of BSD specific software due to portability issues (POSIX incompliences).

using Makefiles in c, declaring variables multiple definitions

i am using makefiles in c, i have three files and each of the three have all the declarations of each variable. so it looks like this when i compile.
/usr/bin/ld: comp_disc.o:(.bss+0x8): multiple definition of `Cost_of_purchase'; main.o:(.bss+0x8): first defined here
/usr/bin/ld: comp_disc.o:(.bss+0x10): multiple definition of `DiscTot'; main.o:(.bss+0x10): first defined here
/usr/bin/ld: comp_disc.o:(.bss+0x18): multiple definition of `Sales_tax'; main.o:(.bss+0x18): first defined here
/usr/bin/ld: comp_disc.o:(.bss+0x20): multiple definition of `Total_price'; main.o:(.bss+0x20): first defined here
/usr/bin/ld: comp_disc.o:(.bss+0x28): multiple definition of `military'; main.o:(.bss+0x28): first defined here
but when i only keep those declarations on main.c i get this.
comp_disc.c:10:12: error: ‘Cost_of_purchase’ undeclared (first use in this function)
10 | if(Cost_of_purchase > 150) {
| ^~~~~~~~~~~~~~~~
comp_disc.c:11:13: error: ‘Mdisc’ undeclared (first use in this function)
11 | Mdisc = .15 * Cost_of_purchase;
so I'm wondering what i need to do so that my variables are declared correctly using make
here is my makefile
# target : dependencies
2 cwork7 : main.o comp_disc.o print_res.o
3 gcc main.o comp_disc.o print_res.o -Wall -o cwork7
4
5 main.o : main.c
6 gcc -c main.c -Wall
7
8 comp_disc : comp_disc.c
9 gcc -c comp_disc.c -Wall
10
11 print_res.o : print_res.c
12 gcc -c print_res.c -Wall
my main.c
5 #include <stdio.h>
6 //functions prototypes
7 void compute_discount(void);
8 int print_results(void);
9
10
11 //defined Gloabal var
12 double Mdisc;
13 double Cost_of_purchase;
14 double DiscTot;
15 double Sales_tax;
16 double Total_price;
17 char military;
18
19 int main (void) {
20 //declare variables
21
22 //Cost of purchase
23 printf("Cost of purchase?\t\t$");
24 scanf ("%lf",&Cost_of_purchase);
25
26 //Military?
27 printf("In military (y or n)?\t\t");
28 scanf(" %c" ,&military);
29
30 //calling for functions
31 compute_discount();
32 print_results();
33
34 }
35
36
my print_res.c
1 #include <stdio.h>
2
3 //function to print results
4 int print_results(void){
5
6 //if input is y Y then use below, this is not dependant on if military only if the letter is accepted
7 switch(military){
8 case 'y':
9 case 'Y':
10 printf("Military discount (15%%): \t$%.2f\n", Mdisc);
11 printf("Discounted total: \t\t$%.2f\n", DiscTot);
12 printf("Sales tax (5%%): \t\t$%.2f\n", Sales_tax);
13 printf("Total: \t\t\t\t$%.2f\n", Total_price);
14 break;
15 //less information is given when n or N is used
16 case 'n':
17 case 'N':
18 printf("Sales tax (5%%): \t\t$%.2f\n", Sales_tax);
19 printf("Total: \t\t\t\t$%.2f\n", Total_price);
20 break;
21 }
22 return(0);
23 }
and my comp_disc.c
1 #include <stdio.h>
2
3 //function to compute discount
4 void compute_discount(void){
5
6 //compute military discount
7 switch(military){
8 case 'y':
9 case 'Y':
10 if(Cost_of_purchase > 150) {
11 Mdisc = .15 * Cost_of_purchase;
12 } else if (Cost_of_purchase < 150) {
13 Mdisc = .10 * Cost_of_purchase;
14 }
15 break;
16 case 'n':
17 case 'N':
18 Mdisc = 0;
19 break;
20 default:
21 printf("Error: bad input\n");
22 }
23
24 //cost minus military discount
25 DiscTot = Cost_of_purchase - Mdisc;
26 //sales tax
27 Sales_tax = .05 * DiscTot;
28 //Total Calculated
29 Total_price = DiscTot + Sales_tax;
30
31 }
Please let me know what you think is the issue.
This has nothing to do with the Makefile.
If you define the variables in all source file you get exactly what the linker says, multiple definitions of the same name. And if you drop them from the file you obviously get a compile error as you are using variables the compiler does not know about.
The simple solution is to keep the variables in main as-is, but to define them as extern in all other files, like extern double Cost_of_purchase; That tells the compiler the variable exists, but is already defined elsewhere, which solves the problem.
However, just don't use global variables. Pass your data to the functions.
struct acc_data {
double Mdisc;
double Cost_of_purchase;
double DiscTot;
double Sales_tax;
double Total_price;
char military;
}
int main(void)
{
struct acc_data acc = { 0 };
// init code skipped
compute_discount(&acc);
print_results(&acc);
}
void compute_discount(struct acc_data *acc)
{
//same as before but prefix variables with acc->
// example:
acc->Total_price = 5000.0;
}
That gets rid of your original problem and improves your code somewhat.
Put the definition of the struct in a header file you include in all C files that use it.

call c function from matlab

I got lots of trouble to call c function from matlab.
My c function is simple
test.c
#include "mex.h"
int addOne(int a)
{
return a+1;
}
I typed mex test.c in matlab command window, I got this error message
Undefined symbols for architecture x86_64:
"_mexFunction", referenced from:
-exported_symbol[s_list] command line option
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
mex: link of ' "test.mexmaci64"' failed.
My Matlab is 2013a, osx 10.9, xcode 5.02
Does anybody have an idea about this? Thanks.
Here is a quick example to get you started:
addOne.cpp
#include "mex.h"
double addOne(double a)
{
return a+1;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nrhs!=1 || nlhs>1) mexErrMsgIdAndTxt("mex:error", "Wrong num of args");
if (!mxIsDouble(prhs[0])) mexErrMsgIdAndTxt("mex:error", "Not double");
plhs[0] = mxDuplicateArray(prhs[0]);
double *x = mxGetPr(plhs[0]);
size_t len = mxGetNumberOfElements(plhs[0]);
for (size_t i=0; i<len; ++i) {
x[i] = addOne(x[i]);
}
}
MATLAB:
>> mex -largeArrayDims addOne.cpp
>> x = magic(4)
x =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
>> addOne(x)
ans =
17 3 4 14
6 12 11 9
10 8 7 13
5 15 16 2

Why does gdb show my code with macros even after I manually run the preprocessor?

Sorry if this question is poorly phrased, but it's a weird problem and I'm not sure entirely how to explain it. I wrote some stupid code involving macros that had a stupid error, but even though I solved the problem, gdb didn't help very much. I thought the problem might be in how I wrote the macros (it wasn't), so I used the -E flag so I could inspect the code and debug it without the macros. Then this happened:
/media/sf_Mint-Shared/C $ clang switch.c -E > switch_e.c
/media/sf_Mint-Shared/C $ clang switch_e.c -g -O0 -o switch
/media/sf_Mint-Shared/C $ gdb switch
[snip]
(gdb) run
Starting program: /media/sf_Mint-Shared/C/switch
Enter your favorite fruit: apple
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b6f2f2 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) l
6 #define SWITCH(t) strcpy(switch_str, t);
7 #define CASE(c, d) if (!strcmp(switch_str, (c))) {d} else
8 #define ELSE(d) {d}
9 #define ENDSWITCH() switch_str = NULL;
10
11 int main()
12 {
13 char fruit[20];
14
15 printf("Enter your favorite fruit: ");
(gdb) l 26
21 scanf("%s", fruit);
22 to_lower(fruit);
23
24 SWITCH(0, fruit)
25 CASE(0, "apple", puts("Apples are delicious!");)
26 CASE(0, "pear", puts("Pears are alright");)
27 CASE(0, "banana", puts("Ew, bananas are gross");)
28 ELSE(puts("Sorry, I don't know that fruit.");)
29 ENDSWITCH(0)
30
In case it isn't obvious, the macros are still present, despite the fact that I compiled the executable from the fully preprocessed source. Here's the (truncated) code that went into the processor:
// Includes truncated
static char *switch_str;
int main()
{
char fruit[20];
printf("Enter your favorite fruit: ");
scanf("%s", fruit);
strcpy(switch_str, fruit);
if (!strcmp(switch_str, ("apple"))) {puts("Apples are delicious!");} else
if (!strcmp(switch_str, ("pear"))) {puts("Pears are alright");} else
if (!strcmp(switch_str, ("banana"))) {puts("Ew, bananas are gross");} else
{puts("Sorry, I don't know that fruit.");}
switch_str = ((void *)0);
return 0;
}
How are the original macros persisting even after preprocessing and how can I debug with them expanded?
The gcc preprocessor inserts #line directives to be able to correlate preprocessed lines to the original line. The gcc compiler uses these directives, both to produce error messages and for debugging information. Consequently, gdb is instructed to look at the original file for source information, even if you run the preprocessor manually.
You can use the -P option to cpp in order to suppress #line directives.

How to force a C program to print an unexpected result?

The source code of square.c is:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int square(int *ptr)
{
int a;
a = *ptr;
return a * a;
}
int main(int argc, char **argv)
{
int a, aa;
srandom(time(NULL));
a = random() % 10 + 1;
aa = square(&a);
printf("%d\n", aa);
return 0;
}
The command-line to compile the source code is:
gcc square.c -o square
Is it possible to run the square executable in Linux so that the printed value will not be a square of any integer number?
Any method of running the program is allowed.
Yes. We can override printf.
Write the code in your post into square.c and compile it with gcc square.c
Make this file, fakesquare.c
int printf(char *str,int i)
{
return puts("7");
}
Compile fakesquare.c as a shared library:
gcc -fPIC -o libfakesquare.so -shared fakesquare.c
Run the square program with libfakesquare.so preloaded:
[15:27:27 0 /tmp] $ LD_PRELOAD=./libfakesqare.so ./a.out
7
[15:29:16 0 /tmp] $ LD_PRELOAD=./libfakesqare.so ./a.out
7
[15:29:16 0 /tmp] $ LD_PRELOAD=./libfakesqare.so ./a.out
7
Witout libfakeshared.so preloaded:
[15:29:40 0 /tmp] $ ./a.out
36
[15:29:41 0 /tmp] $ ./a.out
16
[15:29:42 0 /tmp] $ ./a.out
64
You could use this :
Fastest way to determine if an integer's square root is an integer
Their code seems optimized, but whichever is simplest should do the trick for you.
The only dependency at your code is libc. If libc stays unmodified then your code will always work.
Also your program will fail if before running it, all available memory is exhausted. You can always check if ptr!=NULL.
Assuming a standard C environment I don't see a reason why this should fail on a standard platform. The code might fail if printf is not doing what it is inteded to do, but probably this is not what you are asking for. It also might fail on a platform where int is as small as a byte and a byte is only 6 bits wide. In this case your square function might calculate 9*9=81 which will not fit in the result type int (0..63 for 6 bit-byte). But in my opinion this is a quite academic case.

Resources