larmel / lacc Goto Github PK
View Code? Open in Web Editor NEWA simple, self-hosting C compiler
License: MIT License
A simple, self-hosting C compiler
License: MIT License
Is there a plan to support windows?
I have a problem is trying to install the compiler, I have this error:
Step 5/18 : RUN make install
---> Running in 20e0b2a6a1ef
mkdir -p bin/include
cp include/stdlib/alloca.h include/stdlib/float.h include/stdlib/stdalign.h include/stdlib/stdarg.h include/stdlib/stdbool.h include/stdlib/stddef.h --target-directory=bin/include
cp: unrecognized option: target-directory=bin/include
BusyBox v1.32.1 () multi-call binary.
Usage: cp [OPTIONS] SOURCE... DEST
Copy SOURCE(s) to DEST
-a Same as -dpR
-R,-r Recurse
-d,-P Preserve symlinks (default if -R)
-L Follow all symlinks
-H Follow symlinks on command line
-p Preserve file attributes if possible
-f Overwrite
-i Prompt before overwrite
-l,-s Create (sym)links
-T Treat DEST as a normal file
-u Copy only newer files
make: *** [Makefile:93: bin/include] Error 1
The command '/bin/sh -c make install' returned a non-zero code: 2
I am under alpine linux, in docker, on linux/amd64.
If you want to see project : https://github.com/bensuperpc/docker-lacc
I'm trying to compile something what do you need __builtin_bswap32
:
dst[i] = __builtin_bswap32(src[i]);
For this, I include linux/swab.h
:
#include <linux/swab.h>
Error:
(/usr/include/asm/swab.h, 7) error: Expected ; but got __u32.
/usr/include/asm/swab.h:7
static __inline__ __u32 __arch_swab32(__u32 val)
{
__asm__("bswapl %0" : "=r" (val) : "0" (val));
return val;
}
I imagine that this appears because don't support static __inline__
I ran make test
I got this bug
[-E: Ok!] [-S: Ok!] [-c: Ok!] [-c -O1: Ok!] :: test/c99/vla-sizeof.c
[-E: Ok!] [-S: Ok!] [-c: Ok!] [-c -O1: Ok!] :: test/c99/vla-arg.c
test/c99/flexible-array.c.prep.c:866:38: error: unknown type name ‘major’
__SYSMACROS_DECL_TEMPL(unsigned int, major, (__dev_t __dev))
^~~~~
test/c99/flexible-array.c.prep.c:866:45: error: expected declaration specifiers or ‘...’ before ‘(’ token
__SYSMACROS_DECL_TEMPL(unsigned int, major, (__dev_t __dev))
^
(/usr/include/sys/sysmacros.h, 73) error: Unexpected token '__dev', expected ')'.
(/usr/include/sys/sysmacros.h, 73) error: Unexpected token '__dev', expected ')'.
(/usr/include/sys/sysmacros.h, 73) error: Unexpected token '__dev', expected ')'.
[-E: Compilation failed!] [-S: Compilation failed!] [-c: Compilation failed!] [-c -O1: Compilation failed!] :: test/c99/flexible-array.c
make: *** [Makefile:41: test-lacc] Error 4
raavi@raavi ~/Downloads/lacc-master $ make test
[-E: Ok!] [-S: Ok!] [-c: Ok!] [-c -O1: Ok!] :: test/c11/alignof.c
[-E: Ok!] [-S: Ok!] [-c: Ok!] [-c -O1: Ok!] :: test/c99/line-comment.c
this is my /usr/include/sys/sysmacros.h below
/* Definitions of macros to access `dev_t' values.
Copyright (C) 1996-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SYS_SYSMACROS_H_OUTER
#ifndef __SYSMACROS_DEPRECATED_INCLUSION
# define _SYS_SYSMACROS_H_OUTER 1
#endif
/* If <sys/sysmacros.h> is included after <sys/types.h>, these macros
will already be defined, and we need to redefine them without the
deprecation warnings. (If they are included in the opposite order,
the outer #ifndef will suppress this entire file and the macros
will be usable without warnings.) */
#undef major
#undef minor
#undef makedev
/* This is the macro that must be defined to satisfy the misuse check
in bits/sysmacros.h. */
#ifndef _SYS_SYSMACROS_H
#define _SYS_SYSMACROS_H 1
#include <features.h>
#include <bits/types.h>
#include <bits/sysmacros.h>
/* Caution: The text of this deprecation message is unquoted, so that
#symbol can be substituted. (It is converted to a string by
__SYSMACROS_DM1.) This means the message must be a sequence of
complete pp-tokens; in particular, English contractions (it's,
can't) cannot be used.
The message has been manually word-wrapped to fit in 80 columns
when output by GCC 5 and 6. The first line is shorter to leave
some room for the "foo.c:23: warning:" annotation. */
#define __SYSMACROS_DM(symbol) __SYSMACROS_DM1 \
(In the GNU C Library, #symbol is defined\n\
by <sys/sysmacros.h>. For historical compatibility, it is\n\
currently defined by <sys/types.h> as well, but we plan to\n\
remove this soon. To use #symbol, include <sys/sysmacros.h>\n\
directly. If you did not intend to use a system-defined macro\n\
#symbol, you should undefine it after including <sys/types.h>.)
/* This macro is variadic because the deprecation message above
contains commas. */
#define __SYSMACROS_DM1(...) __glibc_macro_warning (#__VA_ARGS__)
#define __SYSMACROS_DECL_TEMPL(rtype, name, proto) \
extern rtype gnu_dev_##name proto __THROW __attribute_const__;
#define __SYSMACROS_IMPL_TEMPL(rtype, name, proto) \
__extension__ __extern_inline __attribute_const__ rtype \
__NTH (gnu_dev_##name proto)
__BEGIN_DECLS
__SYSMACROS_DECLARE_MAJOR (__SYSMACROS_DECL_TEMPL)
__SYSMACROS_DECLARE_MINOR (__SYSMACROS_DECL_TEMPL)
__SYSMACROS_DECLARE_MAKEDEV (__SYSMACROS_DECL_TEMPL)
#ifdef __USE_EXTERN_INLINES
__SYSMACROS_DEFINE_MAJOR (__SYSMACROS_IMPL_TEMPL)
__SYSMACROS_DEFINE_MINOR (__SYSMACROS_IMPL_TEMPL)
__SYSMACROS_DEFINE_MAKEDEV (__SYSMACROS_IMPL_TEMPL)
#endif
__END_DECLS
#endif /* _SYS_SYSMACROS_H */
#ifndef __SYSMACROS_NEED_IMPLEMENTATION
# undef __SYSMACROS_DECL_TEMPL
# undef __SYSMACROS_IMPL_TEMPL
# undef __SYSMACROS_DECLARE_MAJOR
# undef __SYSMACROS_DECLARE_MINOR
# undef __SYSMACROS_DECLARE_MAKEDEV
# undef __SYSMACROS_DEFINE_MAJOR
# undef __SYSMACROS_DEFINE_MINOR
# undef __SYSMACROS_DEFINE_MAKEDEV
#endif
#ifdef __SYSMACROS_DEPRECATED_INCLUSION
# define major(dev) __SYSMACROS_DM (major) gnu_dev_major (dev)
# define minor(dev) __SYSMACROS_DM (minor) gnu_dev_minor (dev)
# define makedev(maj, min) __SYSMACROS_DM (makedev) gnu_dev_makedev (maj, min)
#else
# define major(dev) gnu_dev_major (dev)
# define minor(dev) gnu_dev_minor (dev)
# define makedev(maj, min) gnu_dev_makedev (maj, min)
#endif
#endif /* sys/sysmacros.h */
I solved the bug by deleting all the contents of /usr/include/sys/sysmacros.h and saving an empty file there. I have kept a backup of it. but what could be a permanent solution to this?
Test case:
int main(void) {
int a[] = {1, (int){2}};
return a[0] != 1;
}
Instead of {1, 2}
, a
gets initialized to {0, 2}
.
Test case:
int id(int x) {
return x;
}
int main(void) {
int x[] = {id(1), id(0)};
return x[1];
}
The generated assembly looks like it is setting up for a function call with two arguments (1, 0), then calling id
twice with no changes to the argument registers in between.
I see that typetree.c hardcodes the size of standard types (char, short, int, float, etc...) to those of the typical x86_64 platforms... I feel this can be a cause for issues on some platforms if for some reason the host compiler has a different size for some of these types (which I guess can happen even if it's x86_64, because I don't think it's forbidden for a compiler to take, let's say, 4 bytes for short ints if it wishes to do so).
So, I believe lacc should have its own limits.h in the include/stdlib folder, because AFAIK the sizes of these types is compiler-specific rather than OS-specific.
Also, I suggest to list the sizes of these standard types at the toplevel readme.
I think it would be great that lacc had a special backend mode that generated C89 code from the IR, and then invoked another C89 compiler for actual compilation. This would open the door of being able to compile C99 and C11 code in platforms that just have a C89 compiler, and could be even more useful in future C versions (C2x and whatever comes next).
I'm not thinking in using lacc for translating to C89, because the C89 code generated by the backend wouldn't be "comfortable to the eyes", and, besides, I guess it would be non-portable code because it comes from the IR, which in turn comes from parsing system headers (and system headers are platform-dependent, so the result would be platform-dependent C89 code).
In other words, the goal I'm thinking in is just invoking another C89 compiler, not in the usefulness of the generated C89 code apart of being adequate for being passed to another compiler running in the same system.
Another cool goal of this backend would be that it would open the door to lacc running in any platform and in any CPU (with perhaps the only requirement of defining the sizes of basic types in the same way that the target C89 compiler does: I guess that lacc should be using the same type sizes as the C89 compiler that will be invoked).
Also, I tend to believe it could be a feature useful for testing the optimizer, because the target C89 compiler could be invoked with -O0 (thus using only optimizations done by lacc) or with -O3 (checking how much room is still there for optimization).
Now the obvious question: how much work would this feature require? By looking at the code, I tend to believe it should be doable without too much effort, but I still wasn't able to understand the complete workflow and the complete IR representation, so I ask the question because you are the author and so you know in detail what this feature would require.
I'm trying to compile the test main.
int main() {
int a;
a = 42;
return a;
}
An error ld
appears to me:
lacc ./main.c -o ./bin/o
/usr/bin/ld -L/usr/local/lib -L/usr/lib main.o -o ./bin/o -lc
/usr/bin/ld: aviso: no se puede encontrar el símbolo de entrada _start; se usa por defecto 0000000000401000
/usr/bin/ld: warning: You can not find the input symbol _start; It is used by default 0000000000401000
When compiling https://musl.libc.org, I get the following:
/usr/local/bin/lacc -std=c99 -nostdinc -Wa,--noexecstack -D_XOPEN_SOURCE=700 -I./arch/x86_64 -I./arch/generic -Iobj/src/internal -I./src/include -I./src/internal -Iobj/include -I./include -O2 -pipe -Wno-pointer-to-int-cast -Werror=implicit-function-declaration -Werror=implicit-int -Werror=pointer-sign -Werror=pointer-arith -Werror=int-conversion -Werror=incompatible-pointer-types -Werror=discarded-qualifiers -Werror=discarded-array-qualifiers -Waddress -Warray-bounds -Wchar-subscripts -Wduplicate-decl-specifier -Winit-self -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wunused-function -Wunused-label -Wunused-variable -DCRT -c -o obj/crt/x86_64/crti.o crt/x86_64/crti.s
/usr/local/bin/lacc -std=c99 -nostdinc -Wa,--noexecstack -D_XOPEN_SOURCE=700 -I./arch/x86_64 -I./arch/generic -Iobj/src/internal -I./src/include -I./src/internal -Iobj/include -I./include -O2 -pipe -Wno-pointer-to-int-cast -Werror=implicit-function-declaration -Werror=implicit-int -Werror=pointer-sign -Werror=pointer-arith -Werror=int-conversion -Werror=incompatible-pointer-types -Werror=discarded-qualifiers -Werror=discarded-array-qualifiers -Waddress -Warray-bounds -Wchar-subscripts -Wduplicate-decl-specifier -Winit-self -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wunused-function -Wunused-label -Wunused-variable -DCRT -c -o obj/crt/x86_64/crtn.o crt/x86_64/crtn.s
Unrecognized input file crt/x86_64/crti.s.
Unrecognized input file crt/x86_64/crtn.s.
I tried to compile a simple hello world from C to to assembly and then from assembly to a Linux binary, lacc -S main.c -o main.s
, lacc main.s -o main
, but it shows this on the second command:
file format not recognized; treating as linker script
I'm not sure if I should report it here or at musl
If you could implement compiling from assembly, that would be appreciated, thanks
i'm evaluating a bunch of C preprocessor sources for usage as macro assembler in custom assembly files. when i try lacc on such a file (which is perfectly fine preprocessed by e.g. GCC's cpp) i get "Unrecognized input files.".
btw, would it be hard to unwire the preprocessor code from the rest ?
Some interesting examples
typedef int x;
void f1(int(x)); // same as void f(int (*)(int))
void f2(int(y)); // same as void f(int)
void f3(int((*))); // same as void f(int *)
void f4(int((*x))); // same as void f(int *)
void f5(int((x))); // same as void f(int (*)(int))
void f6(int(int)); // same as void f(int (*)(int))
It looks like lacc is handling all but f1
, f5
, and f6
.
This is a bit tricky, but I think it can be done by checking the token after the opening (
. If it is a *
, (
, or an identifier that is a typename, it is just a parenthesized declarator or abstract-declarator. Otherwise, it begins the parameter-type-list of an abstract function declarator.
I'm trying to slowly get the ioquake3 engine to compile under os x, as well as the test files and anything else that isn't compiling. Currently I'm copying over a few of the Xcode includes headers and editing them as needed to get the files to compile.
I've added a stub #warning directive but commented out a few others i needed until later.
Currently I have to add:
-I /PATH_TO_XCODE_INCLUDE/include to lacc calls
if i want my own custom edited headers, I have included
-I /PATH_TO_LACC_LIB/include/
ahead of the previous include so that the compiler picks those files up in the correct order,
as I don't know if the flag to have it appended to the include list is available. Maybe I'll add that too?
Thoughts?
When there is more than one file to compile there some invalid memory read due to use of function static variables inside compile.c::compile_neg
it's trying to reuse struct symbol *c32, *c64;
a possible fix is:
static struct symbol *compile_neg_c32, *compile_neg_c64;
void reset_compile_neg_static()
{
compile_neg_c32 = compile_neg_c64 = NULL;
}
static enum reg compile_neg(
struct var target,
struct var l)
{
enum reg xmm0, xmm1;
struct var val;
union value num = {0};
if (is_float(l.type)) {
if (!compile_neg_c32) {
num.u = 1u << 31;
compile_neg_c32 = sym_create_constant(basic_type__float, num);
}
val = var_direct(compile_neg_c32);
} else {
assert(is_double(l.type));
if (!compile_neg_c64) {
num.u = 1ul << 63;
compile_neg_c64 = sym_create_constant(basic_type__double, num);
}
val = var_direct(compile_neg_c64);
}
And then call reset_compile_neg_static
from symtab.c::symtab_clear
:
INTERNAL void symtab_clear(void)
{
int i;
struct symbol *sym;
for (i = 0; i < array_len(&ns_label.symbols); ++i) {
sym = array_get(&ns_label.symbols, i);
if (sym->symtype == SYM_TENTATIVE) {
error("Undefined label '%s'.", sym_name(sym));
}
}
clear_namespace(&ns_tag);
clear_namespace(&ns_ident);
clear_namespace(&ns_label);
array_empty(&string_types);
hash_clear(&functions, NULL);
reset_compile_neg_static(); //!!>>> here
}
Hello. Did you planning for future add object format’s for osx and win64 (intel)? With respect for tinycc: he didn’t generate macos executable. Portable c compiler also not supported this platform. But, why not? If we have robust and portable (as is) c compiler, for linux, win, and osx - it is cool, not? Without many hard things, support KISS principles, not yacc and lex, with linker maybe, and with independent libc. This compiler is a really good start point for implement this all.
Hi! Thanks a lot for developing lacc! I like its simplicity, and also the fact that you can dump the IR instead of compiling. You mention that, in addition to C89, lacc also supports features from newer standards. And, by looking at the code, I found that you actually seem to support many features from recent C versions:
On the other hand, I found no traces of _Generic(), so it seems it's not supported yet. So this leads to my question: do you keep some list somewhere saying what's still missing for lacc being C11-compliant?
Hello larmel, I'm Assyrianic and I'm looking to create a scripting language for my game engine. My intention is to use a real C compiler (LACC in this case) and modify it to produce VM bytecode rather than x86 assembler. Thus, my developers do not need to create or learn a new language just to create content. Please do not take this in the wrong way but how stable is LACC?
Hi --
lacc
is unable to build itself when the linker is lld
, the LLVM linker. When running make bin/selfhost/lacc
, the bootstrap lacc
builds and links fine. When the bootstrap lacc
tries to build lacc
, lld
gives the complaint seen in the title of this issue report.
Both GNU ld
and GNU gold
happily link the selfhosted lacc
so this seems to be something unique to lld
.
Hi!
On OpenBSD, the following tests fail:
Result differ: was 6, expected 0.
Result differ: was 6, expected 0.
Result differ: was 6, expected 0.
Result differ: was 6, expected 0.
[-E: Wrong result!] [-S: Wrong result!] [-c: Wrong result!] [-c -O1: Wrong result!] :: test/c99/va_copy.c
test/gnu/alloca.c:1:20: error: alloca.h: No such file or directory
test/gnu/alloca.c: Invalid input file!
This one is an easy fix; change the first line of test/gnu/alloca.c
from
#include <alloca.h>
to
#ifdef __OpenBSD__
#include <stdlib.h>
#else
#include <alloca.h>
#endif
Output differ:
1,2c1,2
< sizeof: (8, 2305843009213693952)
< offset: (0, 4)
---
> sizeof: (4611686018427387912, 2305843009213693952)
> offset: (4611686018427387904, 4611686018427387908)
Output differ:
1,2c1,2
< sizeof: (8, 2305843009213693952)
< offset: (0, 4)
---
> sizeof: (4611686018427387912, 2305843009213693952)
> offset: (4611686018427387904, 4611686018427387908)
Output differ:
1,2c1,2
< sizeof: (8, 2305843009213693952)
< offset: (0, 4)
---
> sizeof: (4611686018427387912, 2305843009213693952)
> offset: (4611686018427387904, 4611686018427387908)
Output differ:
1,2c1,2
< sizeof: (8, 2305843009213693952)
< offset: (0, 4)
---
> sizeof: (4611686018427387912, 2305843009213693952)
> offset: (4611686018427387904, 4611686018427387908)
[-E: Wrong result!] [-S: Wrong result!] [-c: Wrong result!] [-c -O1: Wrong result!] :: test/gnu/large-objects.c
The reference compiler is gcc-8.3.0; clang-7.0.1 has additional test failures in the test/asm
directory, but those are shortcomings of clang, not lacc.
Thanks!
gcc's documentation specifies that a comma, a paste token, and the identifier __VA_ARGS__
in that order within a macro definition invokes a special behavior where the comma will be eaten if __VA_ARGS__
is empty.
I tried my hand at implementing this myself, but I figured you would have a better idea on how to go about this so I didn't make a pull request.
here is a silly example program. the tuple implementation is inspired by libCello.
/* Expected output to stderr:
hey
hey you
whoa!
whoa: whoa! whoa!
()
(1)
(1, 2, 3)
*/
#include <stdio.h>
#include <limits.h>
#define lament(msg, ...) fprintf(stderr, msg, ##__VA_ARGS__)
#define whoa(msg, ...) fprintf(stderr, msg, ##__VA_ARGS__, ##__VA_ARGS__)
#define TUPLE_END INT_MIN
#define tuple(...) tuple_im(_, ##__VA_ARGS__, TUPLE_END)
#define tuple_im(_, ...) (int[]){__VA_ARGS__}
void print_tuple(int *tuple)
{
lament("(");
for (; *tuple != TUPLE_END; tuple++) {
lament("%i", *tuple);
if (tuple[1] != TUPLE_END) {
lament(", ");
}
}
lament(")\n");
}
int main(int argc, char **argv)
{
(void) argc;
(void) argv;
lament("hey\n");
lament("hey %s\n", "you");
whoa("whoa!\n");
whoa("whoa: %s %s\n", "whoa!");
print_tuple(tuple());
print_tuple(tuple(1));
print_tuple(tuple(1, 2, 3));
return 0;
}
Hi --
Very trivial diff, not really worth a pull request. Self-host build fails because dwarf.c is missing an #include <stdarg.h> and generates this message:
(src/backend/x86_64/dwarf.c, 108) error: Undefined symbol 'va_list'.
While here, change Makefile -std= to -std=c99, since lacc now defaults to that.
fixes.txt
Hello.
On my system I built lacc and make test and amke test-selfhost are working.
I tried lacc tcc.c
and it got me a segmentation fault..
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.