Git Product home page Git Product logo

amacc's Introduction

AMaCC = Arguably Minimalist Arm C Compiler

Introduction

AMaCC is a 32-bit Arm architecture compiler built from scratch. It serves as a stripped-down version of C, designed as a pedagogical tool for learning about compilers, linkers, and loaders.

There are two execution modes AMaCC implements:

  • Just-in-Time (JIT) compiler for Arm backend.
  • Generation of valid GNU/Linux executables using the Executable and Linkable Format (ELF).

It is worth mentioning that AMaCC is designed to compile a subset of C necessary to self-host with the above execution modes. For instance, it supports global variables, particularly global arrays.

A simple stack-based Abstract Syntax Tree (AST) is generated through cooperative stmt() and expr() parsing functions, both fed by a token-generating function. The expr() function performs some literal constant optimizations. The AST is transformed into a stack-based VM Intermediate Representation (IR) using the gen() function. The IR can be examined via a command-line option. Finally, the codegen() function generates Arm32 instructions from the IR, which can be executed via either jit() or elf32() executable generation

AMaCC combines classical recursive descent and operator precedence parsing. An operator precedence parser proves to be considerably faster than a recursive descent parser (RDP) for expressions when operator precedence is defined using grammar productions that would otherwise be turned into methods.

Compatibility

AMaCC is capable of compiling C source files written in the following syntax:

  • support for all C89 statements except typedef.
  • support for all C89 expression operators.
  • data types: char, int, enum, struct, union, and multi-level pointers
    • type modifiers, qualifiers, and storage class specifiers are currently unsupported, though many keywords of this nature are not routinely used, and can be easily worked around with simple alternative constructs.
    • struct/union assignments are not supported at the language level in AMaCC, e.g. s1 = s2. This also applies to function return values and parameters. Passing and returning pointers is recommended. Use memcpy if you want to copy a full struct, e.g. memcpy(&s1, &s2, sizeof(struct xxx));
  • global/local variable initializations for supported data types
    • e.g., int i = [expr]
    • New variables are allowed to be declared within functions anywhere.
    • item-by-item array initialization is supported
    • but aggregate array declaration and initialization is yet to be supported e.g., int foo[2][2] = { { 1, 0 }, { 0, 1 } };

The architecture support targets armv7hf with Linux ABI, and it has been verified on Raspberry Pi 2/3/4 with GNU/Linux.

Prerequisites

  • Code generator in AMaCC relies on several GNU/Linux behaviors, and it is necessary to have Arm/Linux installed in your build environment.

  • Install GNU Toolchain for the A-profile Architecture

    • Select arm-linux-none-gnueabihf (AArch32 target with hard float)
  • Install QEMU for Arm user emulation

sudo apt-get install qemu-user

Running AMaCC

Run make check and you should see this:

[ C to IR translation          ] Passed
[ JIT compilation + execution  ] Passed
[ ELF generation               ] Passed
[ nested/self compilation      ] Passed
[ Compatibility with GCC/Arm   ] ........................................
----------------------------------------------------------------------
Ran 52 tests in 8.842s

OK

Check the messages generated by make help to learn more.

Benchmark

AMaCC is able to generate machine code really fast and provides 70% of the performance of gcc -O0.

Test environment:

  • Raspberry Pi 4B (SoC: bcm2711, ARMv8-A architecture)
  • Raspbian GNU/Linux, kernel 5.10.17-v7l+, gcc 8.3.0 (armv7l userland)

Input source file: amacc.c

compiler driver binary size (KiB) compile time (s)
gcc with -O0 -ldl (compile+link) 56 0.5683
gcc with -O0 -c (compile only) 56 0.4884
AMaCC 100 0.0217

Internals

Check Intermediate Representation (IR) for AMaCC Compilation.

Acknowledgements

AMaCC is based on the infrastructure of c4.

Related Materials

amacc's People

Contributors

coldnew avatar cykutw avatar dzhustin avatar hpcguy avatar johnnylchang avatar jserv avatar lecopzer avatar loganchien avatar oscarshiang avatar spacemiqote avatar splasky avatar thekk avatar timgates42 avatar vacantron avatar yodalee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

amacc's Issues

Incorrect execution result for simple program

maze.c.gz is a simple maze generator written by Joe Wingbermuehle. The modified program can be parsed and executed by AMaCC. However, the program output is NOT correct. It was assumed to be kind of maze though. Also, the functionality to solve maze was incorrect.

Implement standalone interpreter for generated IR

At present, AMaCC translates C source into internal bytecode form on which code generator depends for Arm machine code. The argument -s is to generate bytecode from parsing tree. Here is the example:

$ ./amacc -s tests/hello.c 
1: #include <stdio.h>
2: 
3: int main()
4: {
5:     printf("hello, world\n");
    ENT  0
    IMM  -568971248
    PSH 
    PRTF
    ADJ  1
6:     return 0;
    IMM  0
    LEV 
7: }

Branch interpreter provides incomplete interpreter support, which can accepts bytecode. It would be great if we can take the standalone interpreter to validate AMaCC internally.

Reference: Write a C interpreter

How left shift handles negative number?

It seems left shift on negative numbers are not handled properly.

Make check has error message as below:

- 4 << -1 = 0
?                ^
+ 4 << -1 = 2
?                 ^

I traced the source code and it seemed the negative numbers have not been taken into consideration in our semantics.

At line 618 of amacc.c

case Shl: next(); *++e = PSH; expr(Add); *++e = SHL; ty = INT; break;

So is it a bug or a feature of our compiler? Please do correct me if I missed out something.

Consider adding static storage class?

A 'static' storage class could potentially be supported by internally creating a 'hidden' global variable having the name <funcname>_<varname>. This could help prevent the use of global variables, at least in the source code. I think all the machinery is already there to support this in about ten lines of source code changes.

Reorder opcode enumeration

Recent div/mod operator support breaks the classification of opcode enumeration:

/* system call shortcuts */
OPEN,READ,WRIT,CLOS,PRTF,MALC,FREE,MSET,MCMP,MCPY,MMAP,DSYM,BSCH,STRT,DLOP,DIV,MOD,EXIT,

Both DIV and MOD should be moved to somewhere nearby SUB and MUL.

Use Dynasm to implement the test case

I can't load the PC value which is a memory location to a general purpose register r0.

It is my current implementation jit-arm.dasm
The line 16 is that instruction, ldr r0, [pc, #12]

All the instruction will translate into a unsigned integer array which contain all the machine code.
//|.actionlist actions
static const unsigned int actions[6] = {
0xe59f000c,
0xe5901000,
0xe2811009,
0xe5801000,
0xe1a0f00e,
0x00000000
};

It is as same as tests/jit.c
Hence, I don't know why it occurs the following error as it executes the instruction, ldr r0, [pc, #12]

lua ./dynasm.lua -o jit-arm.h jit-arm.dasc
arm-linux-gnueabihf-gcc -Wall -std=gnu99 -I. -o jit-arm -DJIT=\"jit-arm.h\" dynasm-driver.c
qemu-arm -L /usr/arm-linux-gnueabihf jit-arm
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
make: *** [run-jit-arm] Segmentation fault (core dumped)

Any suggestion ?
(BTW, if I change PC to SP, everything is ok)

Simple program breaks the compiler

int main() {
    int a;
    a = 0;
    if (1) {
        int b;
        printf("%d\n", a);
        int c;
        b = 1;
        a += b;
        printf("%d\n", a);
    }
}

Results in

0
0
1

Clearly it should not print 3 numbers!

Can't place other loop(s) inside another for loop

To reproduce this, try to compile:

int main(int argc, char **argv)
{
        int i, j;

        for (i = 0; i < 5; i++)
                for (j = 0; j < 5; j++)
                        printf("loop %d\n", i);

        return 0;
}

and we got an infinite loop.

This is a bug of current implementation of for loop. As we know, the order of code chunks while parsing is not what we expect in assembly form, like

// We parse it as:
// Init -> Cond -> Bz -> After -> Body -> Jmp

// But we want it to be:
// Init -> Cond -> Bz -> Body -> After -> Jmp

To solve this, I simply swap After and Body chunk, and here comes the problem. All address used in Body remain the same and causes unexpected behavior. Here are two ways in my mind:

  1. re-caculate the address of each address used in Body
    + higher performance
    - more complex works
    - increase bunch of code (I think we should keep this project small and simple)
  2. use jump command to control code flow instead of swapping code chunks
    - lower performance
    + keep everything as simple as now
    + need only lines of code to achieve

Not sure which approach would fit the spirit of this project more.

AssertionError: shift operations

The following error occurred when scripts/runtest.py was being run.

FAIL: test_shift (__main__.TestCC_SC)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "scripts/runtest.py", line 54, in test
    self.assertEqual(amacc_out.decode('utf-8'), gcc_out.decode('utf-8'))
AssertionError: '1 <<[70 chars]-1 = 2\n4 >> -1 = 8\n-1 << 1 = fffffffe\n-1 <<[210 chars]68\n' != '1 <<[70 chars]-1 = 0\n4 >> -1 = 0\n-1 << 1 = fffffffe\n-1 <<[210 chars]68\n'
  1 << 0 = 1
  1 << 2 = 4
  0 << 4 = 0
  1 << 31 = 80000000
  1 << 32 = 0
- 4 << -1 = 2
?           ^
+ 4 << -1 = 0
?           ^
- 4 >> -1 = 8
?           ^
+ 4 >> -1 = 0
?           ^
  -1 << 1 = fffffffe
  -1 << 0 = ffffffff
  4 >> 1 = 2
  4 >> 5 = 0
  0x80000000 >> 31 = ffffffff
  -1 >> 2 = ffffffff
  -1091119768 - -1091119766 = -2(fffffffe)
  a = f6d5680c, b = bef6d568, c = fff6d568
  a = 76d5680c, b = bef6d568, c = bef6d568

[ELF32]: amacc could not open ELF32 format

Although it can compile, it can not do the self-hosting via ELF32 format.

For now, it is the error message

[gapry@E130 amacc]$ make check
[ JIT      ]
hello, world
[ compiled ]
could not open(elf/hello)
Makefile:20: recipe for target 'check' failed
make: *** [check] Error 255

Is it possible to create a new branch to develop the ELF32 Loader ?

Different result with gcc in tests/char.c

In test file tests/char.c, the amacc execution result of following code:

p = malloc(128);
p[0] = -1;
v = p[0];
printf("%x %d %d %x\n", p[0], p[0], v, p[1]);

is different to gcc.
amacc generates ffffffff -1 -1 65 while gcc generates ff 255 255 65
Not sure is this an issue or not. It may related to that amacc handle char as signed char, not sure for now.

Separate parser and lexer?

May I separate the lexer and parser?
It will be more easy to generate ast tree if I can separate the lexer and parser.

Modulo (operator%) does not give correct result

I noticed in a larger program that I compiled JIT with amacc, which relies on modulo for prng, that the results were wrong. So I made a small test program, and tried a freshly cloned amacc on it - as you can see below the results are completely wrong.

(Here is a hacky fix for now, which requires the use of mod(a, b) instead of a % b - it gives the correct results for the shown small test program)

$ git clone [email protected]:jserv/amacc.git
Cloning into 'amacc'...
remote: Enumerating objects: 71, done.
remote: Counting objects: 100% (71/71), done.
remote: Compressing objects: 100% (51/51), done.
remote: Total 734 (delta 33), reused 52 (delta 19), pack-reused 663
Receiving objects: 100% (734/734), 297.06 KiB | 1.18 MiB/s, done.
Resolving deltas: 100% (411/411), done.
$ cd amacc/
$ make
  CC+LD		amacc
  CC+LD		amacc-native
amacc.c:2107:5: warning: return type of ‘main’ is not ‘int’ [-Wmain]
 int main(int argc, char **argv)
     ^~~~
amacc.c:2107:5: warning: first argument of ‘main’ should be ‘int’ [-Wmain]
$ ./amacc ~/tmp/modtest.c 
39628
1015073
3
2
$ more ~/tmp/modtest.c 
int main() {
	int a = 2131119850;
	int b = 53777;
	printf("%d\n", (a % b));

	int c = 841495917;
	int d = 829;
	printf("%d\n", (c % d));

	int e = 100;
	int f = 26;
	printf("%d\n", e % f);

	int g = 2;
	int h = 1;
	printf("%d\n", g % h);

	return 0;
}

Allow array declarations using [] operators.

Creating an issue for this so it can be tracked.

Using an array operator '[ ]' is currently supported for use with (certain) pointer variables in array expressions, but never supported for array declarations. This ticket is to specifically address declarations using '[ ]' directly.

JIT documentation

Dmytro Sirenko wrote an excellent documentation for c4-based x86 JIT compilation: JIT.md.
We expect to prepare Aarch32 specific entry to describe how JIT works in AMaCC as well.

Can't create elf file directly on ARM?

pi@anchor:~/Languages/amacc $ uname -a
Linux anchor 5.10.17-v7l+ #1403 SMP Mon Feb 22 11:33:35 GMT 2021 armv7l GNU/Linux

pi@anchor:~/Languages/amacc $ gcc amacc.c -ldl

pi@anchor:~/Languages/amacc $ cat count.c
int main()
{
int i;
for (i=0; i<10; ++i)
printf("%d\n", i) ;
return i;
}

pi@anchor:~/Languages/amacc $ ./a.out -o foo.o count.c

pi@anchor:~/Languages/amacc $ file foo.o
foo.o: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, stripped

pi@anchor:~/Languages/amacc $ objdump -d foo.o
objdump: foo.o: file format not recognized

??? --- Why doesn't this work?

pi@anchor:~/Languages/amacc $ ./a.out count.c
0
1
2
3
4
5
6
7
8
9
pi@anchor:~/Languages/amacc $

Calling convention documentation?

Hi,

Can you add a file to the doc directory describing the calling convention for amacc? The comments attached to the LEA instruction are not enough.

I have written a standalone peephole optimizer that reduces the number of assembly language instructions by half at this point (mostly because it eliminates all the push/pop instructions) and layers other optimizations on top, but I could go much further if I could wrap my head around the calling convention. It looks like a function sometimes returns an r0 register. It also seems like it is safe to 'step on' most of the registers without saving/restoring at function entry/exit, but I just want to verify. I am flying totally blind.

Finally, if you have any insight into how the (non-standard) ELF format "works", any information at all there would be helpful. Specificlly, I am interested in relocating and (most importantly) aligning functions that call each other.

Just a few lines of information in a doc file would help since I currently have utter confusion, and have miraculously not broken anything with my optimizer yet, at least nothing I know of through my five tests (including maze.c).

PS Here's what the optimizer currently does. In a month, it might beat optimizing compilers. :)

int fact(int n)
{
   int i ;
   int retVal = 1 ;
   for (i=2; i<=n; ++i)
      retVal *= i ;
   return retVal ;
}

after peephole:

  50:	e92d4800 	push	{fp, lr}
  54:	e28db000 	add	fp, sp, #0
  58:	e24dd008 	sub	sp, sp, #8
  5c:	e3a00001 	mov	r0, #1
  60:	e50b0008 	str	r0, [fp, #-8]
  64:	e3a00002 	mov	r0, #2
  68:	e50b0004 	str	r0, [fp, #-4]
  6c:	e1a00000 	nop			; (mov r0, r0)
  70:	e1a00000 	nop			; (mov r0, r0)
  74:	e1a00000 	nop			; (mov r0, r0)
  78:	e51b8004 	ldr	r8, [fp, #-4]
  7c:	e59b0008 	ldr	r0, [fp, #8]
  80:	e1580000 	cmp	r8, r0
  84:	ca000013 	bgt	0xb0
  88:	e51b7008 	ldr	r7, [fp, #-8]
  8c:	e51b0004 	ldr	r0, [fp, #-4]
  90:	e0000097 	mul	r0, r7, r0
  94:	e50b0008 	str	r0, [fp, #-8]
  98:	e51b7004 	ldr	r7, [fp, #-4]
  9c:	e3a00001 	mov	r0, #1
  a0:	e0800007 	add	r0, r0, r7
  a4:	e50b0004 	str	r0, [fp, #-4]
  a8:	eafffff2 	b	0x78
  ac:	e1a00000 	nop			; (mov r0, r0)
  b0:	e51b0008 	ldr	r0, [fp, #-8]
  b4:	e28bd000 	add	sp, fp, #0
  b8:	e8bd8800 	pop	{fp, pc}

from maze.c:

int maze_rand()
{
    return ((maze_rand_v = maze_rand_v * 214013 + 2531011) >> 16) & 0x7fff;
}

after peephole:

      50:       e92d4800        push    {fp, lr}
      54:       e28db000        add     fp, sp, #0
      58:       e59f8064        ldr     r8, [pc, #100]  ; 0xc4
      5c:       e59f005c        ldr     r0, [pc, #92]   ; 0xc0
      60:       e5907000        ldr     r7, [r0]
      64:       e59f004c        ldr     r0, [pc, #76]   ; 0xb8
      68:       e0070097        mul     r7, r7, r0
      6c:       e59f0038        ldr     r0, [pc, #56]   ; 0xac
      70:       e0807007        add     r7, r0, r7
      74:       e5887000        str     r7, [r8]
      78:       e3a00010        mov     r0, #16
      7c:       e1a08057        asr     r8, r7, r0
      80:       e59f000c        ldr     r0, [pc, #12]   ; 0x94
      84:       e0080000        and     r0, r8, r0
      88:       e28bd000        add     sp, fp, #0
      8c:       e8bd8800        pop     {fp, pc}

Support compound assignment operators

The += operator in C is one of the language’s compound assignment operators. It is essentially a shorthand notation for increamenting the variable on the left by an arbitrary value on the right.

The following two lines of C code are identical, in terms of their effect on the variable z:

z = z + y;  // increment z by y
z += y;  // increment z by y

Both of these statements do the same thing. The current value of z and the current value of y are added together, and the result of the addition is placed into variable z, replacing the value that had been stored in z.

At least +=, -=, and *= operators should be supported.

Add support for struct assignement.

Struct/union assignments are not currently allowed, since they require moving mem blocks:

struct foo s1, s2;
s1 = s2;  // not allowed

That said, the AST tracks all the type information needed to support this. Assignment/copy just needs to be converted to a SYSC to memcpy(). Also, for function return values and parameters, the C-standard ABI conventions need to be followed. I looked at the C89 standard and didn't see it spelled out. Some compilers used to convert struct parameters to pointers automatically if the struct size exceeded a certain limit, and I am not sure what the rules are now.

The undefined behavior of AMaCC is different from gcc

On my platform:

ubuntu 18.04
gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0

Left shift operator inside gcc with negative argument will become right shift,but AMaCC will set the result to 0.
Do we need to change AMaCC to keep the behavior consistent with gcc?
This is the failure message after check test:

FAIL: test_shift (__main__.TestCC_SC)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "runtest.py", line 55, in test
    self.assertEqual(amacc_out.decode('utf-8'), gcc_out.decode('utf-8'))
AssertionError: '1 <<[70 chars]-1 = 0\n-1 << 1 = fffffffe\n-1 << 0 = ffffffff[197 chars]68\n' != '1 <<[70 chars]-1 = 2\n-1 << 1 = fffffffe\n-1 << 0 = ffffffff[197 chars]68\n'
  1 << 0 = 1
  1 << 2 = 4
  0 << 4 = 0
  1 << 31 = 80000000
  1 << 32 = 0
- 4 << -1 = 0
?           ^
+ 4 << -1 = 2
?           ^
  -1 << 1 = fffffffe
  -1 << 0 = ffffffff
  4 >> 1 = 2
  4 >> 5 = 0
  0x80000000 >> 31 = ffffffff
  -1 >> 2 = ffffffff
  -1091119768 - -1091119766 = -2(fffffffe)
  a = f6d5680c, b = bef6d568, c = fff6d568
  a = 76d5680c, b = bef6d568, c = bef6d568

AMaCC license

As AMaCC contains substantial rswier/c4 code, please change your license to GPLv2.

After bsearch

7094c3f

res = bsearch(&sym, sym, 2, 1, (void*) _start); // hack to jump into a function pointer
if (((void*) 0) != res)
    return retval;
else {
    printf("Error: can't find the function pointer\n");
    exit(0);
}

If return value from _start is not equal to 0, res will be NULL

In some test: tests/ptr.c tests/shift.c tests/arginc.c ...
main() returns non-zero or have no return, and print the Error.

It's pretty weird to the error message "can't find the function pointer".
Can't find what pointer? At this state the program finishes executing jit-progrom, if pointer means _start, "can't find" is really meaningless.
Is it better message for "main function return for non-zero value: %d" or something else to let some test file (ex: tests/arginc.c only return argc + 2) make sense?

Can't create ELF executable from bootstrap amacc compiler

A recent problem has appeared:

$ gcc -o amacc-gcc amacc.c -ldl
$ ./amacc-gcc -o fib tests/fib.c
$ ./fib 20
10946
$ ./amacc-gcc -o amacc amacc.c # amacc bootstrap compile
$ ./amacc tests/fib.c 20
10946
$ ./amacc -o fib-amacc tests/fib.c
Segmentation fault
$

At first, I thought this was because of changes I made to the compiler, but I rolled back to Dec 16, 2020 before I had made any changes to the compiler, and tried again, with the same result:

$ cd /tmp
$ git clone https://github.com/jserv/amacc.git
$ cd amacc
$ git checkout -b old_state 684c54b # Dec 16 2020
$ gcc -o amacc-gcc amacc.c -ldl
$ ./amacc-gcc -o fib tests/fib.c
$ ./fib 20
10946
$ ./amacc-gcc -o amacc amacc.c
$ ./amacc tests/fib.c 20
10946
$ ./amacc -o fib-amacc tests/fib.c
Segmentation fault
$

I am thinking that this may be due to an ABI change in the linux kernel that I pulled with a recent 'sudo apt update ; sudo apt full-upgrade' .

I am not an ELF expert, so I'm not sure I can fix this, especially since I don't have a debugger that will work on the bootstrapped amacc executable produced by the compile commands above. If anyone can point me to a debugger that will work on amacc ELF files, I can try to make some progress

PS Just getting back to amacc work after a forced hiatus.

Incorrect result of left shift with negative number

In test file tests/shift.c, the execution result of following code:

printf("4 << -1 = %x\n", 4 << -1);

is 4 << -1 = 0, while gcc output 4 << -1 = 2
It is possible that left shift of negative number is handled like unsigned number, thus wipe out all bits.

Add floating point type?

I'm guessing 32bit floating point would take 150-400 lines of C source code to implement. For instance, now that dynamic library support has been expanded, AMaCC can call strtof() to parse float constants, saving many lines of compiler code. New IR symbols can be added for FP operations, probably around a dozen. It's my belief that type promotions and function call ABI would be the hardest part of the whole implementation. I think the AMaCC type system is already well positioned to handle float, although some comparison expressions in amacc.c may get longer if there are three base types to consider rather than two. The question for discussion is, just because it can be added, should it be added?

Enhance robustness of '[ ]' operator for array access.

Creating an issue for this so it can be tracked.

Using an array operator '[ ]' is currently supported for use with (certain) pointer variables in array expressions, but not always. The goal of this ticket is to be able to use the array operator '[ ]' in expressions, working as expected under every possible circumstance. Note that having '[ ]' work for declarations also needs to be improved, and is submitted as a separate issue.

incorrect difference of address

In test file tests/ptr.c, the execution result of following code is incorrect:

s = (int*)0xbebebeb0;
e = (int*)0xbebebeb4;
v = e - s;
if (v == 1)
  printf("passed\n");
else
printf("failed, e - s = %x\n", v);

Which print failed, e - s = 0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.