The following short c example uses the standard c library and therefore requires the wasi sdk:
#include <stdio.h>
int main(void)
{
puts("Hello");
return 0;
}
When compiling the code directly with clang to wasm it works without problem:
clang --target=wasm32-unknown-wasi -s -o example.wasm example.c
My understanding of the LLVM tool chain is that I could achieve the same result with either
clang -> LLVM IR (.ll) -> LLVM native object files (.o) -> convert to wasm
clang -> LLVM native object files (.o) -> convert to wasm
I am able to use the second approach with a simple C program which does not use standard lib calls, when trying with the example above I receive a undefined symbol error:
clang --target=wasm32-unknown-wasi -c example.c
wasm-ld example.o -o example.wasm --no-entry --export-all
wasm-ld: error: example.o: undefined symbol: puts
I do not know if my problem is that I use the wrong clang parameters and therefore not export enough information or that the error is in the wasm-ld command.
Would be happy if someone could give me more insight into tool chain, thanks
I am trying to compile two *.c files to LLVM bitcode via clang, link them together using llvm-link, and make a single *.wasm file out of it. I built LLVM on my machine via the Makefile provided by https://github.com/yurydelendik/wasmception
This works fine until I use memcpy in the C code. Then llvm-link stops with error:
Intrinsic has incorrect argument type!
void (i8*, i8*, i32, i1)* #llvm.memcpy.p0i8.p0i8.i32
The following is a minimal example to reproduce the issue:
one.c
#define EXPORT __attribute__((visibility("default")))
#include <string.h>
char* some_str();
EXPORT void do_something() {
char* cpy_src = some_str();
char other_str[15];
memcpy(other_str, cpy_src, strlen(cpy_src));
}
two.c
char* some_str() {
return "Hello World";
}
Execute the following commands:
$ clang --target=wasm32-unknown-unknown-wasm --sysroot=../wasmception/sysroot -S -emit-llvm -nostartfiles -fvisibility=hidden one.c -o one.bc
[...]
$ clang --target=wasm32-unknown-unknown-wasm --sysroot=../wasmception/sysroot -S -emit-llvm -nostartfiles -fvisibility=hidden two.c -o two.bc
[...]
Note that no optimization is done because that would eliminate the unnecessary memcpy call here. As I said, this is a minimal example out of context to show the error.
$ llvm-link one.bc two.bc -o res.bc -v
Loading 'one.bc'
Linking in 'one.bc'
Loading 'two.bc'
Linking in 'two.bc'
Intrinsic has incorrect argument type!
void (i8*, i8*, i32, i1)* #llvm.memcpy.p0i8.p0i8.i32
llvm-link: error: linked module is broken!
When I comment out the memcpy call in the example file, the error is gone. Of course this is not an option in the real project I am working at.
Am I doing something wrong? Is it a bad idea in general to use memcpy in a WebAssembly context? Can this be a bug in LLVM/Clang?
Reading through these github issues, it seems the memcpy intrinsic is not currently supported by the WASM backend:
https://github.com/WebAssembly/design/issues/236
https://github.com/WebAssembly/design/issues/1003
As a workaround, you could instruct clang to disable intrinsic expansion using -fno-builtin, so that the generated code will call the actual memcpy function.
I was trying to compile hello.cob to hello.c:
$ ls
hello.cob
$ cobc -x -C hello.cob
$ ls
hello.c hello.c.h hello.c.l.h hello.cob
But clang failed to compile hello.c to executable file:
$ clang hello.c
/tmp/hello-479acf.o: In function `main':
hello.c:(.text+0x1e): undefined reference to `cob_init'
hello.c:(.text+0x2a): undefined reference to `cob_stop_run'
/tmp/hello-479acf.o: In function `sampleCOBOL_':
hello.c:(.text+0x98): undefined reference to `cob_module_global_enter'
hello.c:(.text+0x133): undefined reference to `cob_display'
hello.c:(.text+0x13f): undefined reference to `cob_stop_run'
hello.c:(.text+0x15a): undefined reference to `cob_check_version'
hello.c:(.text+0x33d): undefined reference to `cob_set_cancel'
hello.c:(.text+0x38e): undefined reference to `cob_fatal_error'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Here is hello.cob (can be compiled by cobc -x hello.cob):
IDENTIFICATION DIVISION.
PROGRAM-ID. sampleCOBOL.
PROCEDURE DIVISION.
DISPLAY "Hello World!".
STOP RUN.
I'm quite sure clang doesn't fail to compile the C source as you don't ave any C compiler warnings or errors.
It cannot link the generated object file because you didn't told clang to link against libcob and there is no "magic" for clang to know where to find its symbols. Adding -lcob to your clang invocation may be enough already.
If you want to know how cobc invokes the compiler/linker add -v to your cobc invocation.
Note: if this version of cobc was built with gcc it defaults to use gcc, too. You can see this with cobc --info which also shows if any of the built-in commands is override by environment variables.
Additional note: cobc does not only call a C compiler/linker, it also generates C code specific for the compiler it was built with. The most important part concerning the C generation is -f[no-]computed-goto, just in case the C compiler complains (which it doesn't in your case).
I'm trying to build a C library (GMP 6.0.0) for arm64 for use on iOS. I'm running the configure script with the invocation below (compiler is as found using xcrun --find).
./configure \
CC="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" \
CPP="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -E" \
CPPFLAGS="-target arm64-apple-darwin -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/ -miphoneos-version-min=7.0" \
--host=aarch64-apple-darwin
However this fails at the following line ("long long reliability test 1"):
checking compiler /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -O2 -pedantic -target arm64-apple-darwin -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/ -miphoneos-version-min=7.0... no, long long reliability test 1
configure: error: could not find a working compiler, see config.log for details
Full config.log available here. It shows multiple warning and errors for the long long reliability test compile, including the following:
conftest.c:9:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
f(){static const struct{t1 n;t1 src[9];t1 want[9];}d[]={{1,{0},{1}},};t1 got[9];int i;
^
conftest.c:10:44: error: implicit declaration of function 'h' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
for(i=0;i<1;i++){if(e(got,got,9,d[i].n)==0)h();g(i,d[i].src,d[i].n,got,d[i].want,9);if(d[i].n)h();}}
^
conftest.c:10:48: error: implicit declaration of function 'g' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
for(i=0;i<1;i++){if(e(got,got,9,d[i].n)==0)h();g(i,d[i].src,d[i].n,got,d[i].want,9);if(d[i].n)h();}}
^
conftest.c:10:100: warning: control reaches end of non-void function [-Wreturn-type]
for(i=0;i<1;i++){if(e(got,got,9,d[i].n)==0)h();g(i,d[i].src,d[i].n,got,d[i].want,9);if(d[i].n)h();}}
^
Using --host=none it works fine, but I'd really like to figure out how to build it with assembly optimized for arm64.
My system is x86_64-apple-darwin13.1.0 (or coreisbr-apple-darwin13.1.0 according to config.guess), an early '11 Core i7 MBP running OS X v10.9.2. I'm using Xcode 5.1 (5B130a).
Any help appreciated.
EDIT 1
Compiling for ARMv7 passes configure, but fails on make (full configure/make output here), apparently while compiling some assembly:
tmp-dive_1.s:165:18: error: unexpected token in '.section' directive
.section .rodata
^
EDIT 2
#MarcGlisse: By forcing clang to ignore the errors as suggested (-Wno-...) arm64 passes configure, but then fails on make (full output here):
tmp-mul_1.s:59:2: error: unrecognized instruction mnemonic
bcc Lfi1
^
tmp-mul_1.s:60:2: error: unrecognized instruction mnemonic
beq Lfi2
^
As a side note: these commits, I assume intended to remove the need for suppressing the error, don't seem to work i.e. I get the same error when removing the supression.
For armv7, using these commits as suggested fixes the .section error, but make fails later on with the following (full output here):
tmp-mode1o.s:64:2: error: unknown directive
.protected ___gmp_binvert_limb_table
^
EDIT 3
Using the suggested edits, armv7, armv7s, i386 and x86_64 now all compile with assembly!
For arm64 the edits get it past the previous error, but now gives several errors about an invalid input constraint 'rZ', all in the same file (full output here):
divrem_1.c:237:5: error: invalid input constraint 'rZ' in asm
udiv_qrnnd_preinv (*qp, r, r, nshift, d, dinv);
^
../gmp-impl.h:3062:2: note: expanded from macro 'udiv_qrnnd_preinv'
add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl)); \
^
../longlong.h:551:7: note: expanded from macro 'add_ssaaaa'
: "rZ" (ah), "rZ" (bh), "%r" (al), "rI" (bl) __CLOBBER_CC)
EDIT 4
After commenting out add_ssaaaa and sub_ddmmss in longlong.h and editing some more assembly instructions in gcd_1.asm (blo to b.lo etc.), it now fails with several of the following errors (full output here):
tmp-invert_limb.s:75:22: error: immediate value expected for shifter operand
add x1, x1, x2, lsr 1
^
tmp-invert_limb.s:75:22: error: invalid operand for instruction
add x1, x1, x2, lsr 1
^
I'll post a total diff later.
EDIT 5
Ok, that gets us another step further, but it now hits into (full output here):
tmp-invert_limb.s:52:2: error: ADR/ADRP relocations must be GOT relative
adrp x1, approx_tab
^
If this keeps going it might be better to continue this via email.
"Support for ARM64 alias Aarch64 alias ARMv8"
https://gmplib.org/gmp6.0
Copyright issues aside...
GMP may not be compatible with Apple's proprietary CPU, and may not be compatible with Clang/LLVM. Being a GNU project it is probably more thoroughly tested with GCC on non-proprietary chipsets.
A quick search shows historically at least there have been issues compiling GMP with clang.
You really should email the GMP community and ask for help on this one.
Is it possible to compile C "Hello world" program to have final executable entirely static?
#include <stdio.h>
int main() {
printf("hello world!\n");
return 0;
}
I've tried the following:
clang -static main.c
But it gives:
ld: library not found for -lcrt0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've seen staticly linked libc? but I want to get additional information on this topic.
P.S. I am asking this for education purposes rather than for real practice.