nibblebits / dragoncompiler Goto Github PK
View Code? Open in Web Editor NEWA C compiler written in C
License: GNU General Public License v2.0
A C compiler written in C
License: GNU General Public License v2.0
/* This file is automatically generated.
This file selects the right generated file of `__stub_FUNCTION' macros
based on the architecture being compiled for. */
#if !defined __x86_64__
# include <gnu/stubs-32.h>
#endif
#ifndef _STDC_PREDEF_H
#define _STDC_PREDEF_H 1
#ifdef __GCC_IEC_559
#if __GCC_IEC_559 > 0
#define __STDC_IEC_559__ 1
#endif
#else
#define __STDC_IEC_559__ 1
#endif
#endif
main: ./helpers/vector.c:21: vector_assert_bounds_for_pop: Assertion `vector_in_bounds_for_pop(vector, index)' failed.
#define ABC_SUM(x, y) x + y
#define ABC ABC_SUM(5, 5)
#if ABC
#endif
void* abc;
int main()
{
}
mov byte [ebp-4], eax
Cannot be computed by NASM assembler, we must use the AL register, it will not take from EAX for us. Invalid combination of operands.
struct abc d;
int main()
{
struct abc z;
z.z = 50;
z.c = 30;
}
We can see a huge problem with z.z this causes a segmentation fault but the strange thing is that it causes a seg fault with z.c but only after z.z is executed which causes a problem with the resolver for some reason.
Bug Summary:
After z.z it appears a new type of scope exists that contains three variables of type "z" one of them is a structure of abc, the other two are integers of "z" as found in the member variable in structure "abc". The bug is not present when we only have z.z however only the variable representing the "abc" structure that is named "z" is returned and not to the expected "z" member that is an integer found in the abc structure.
struct abc
{
int a;
char b;
int c;
};
struct abc d;
int main()
{
struct abc a;
a.a = 50;
a.b = 20;
a.c = 30;
return a.a + a.b;
}
main:
push ebp
mov ebp, esp
sub esp, 16
mov eax, 50
mov dword [ebp-12], eax
mov eax, 20
mov byte [ebp-8], al
mov eax, 30
mov dword [ebp-4], eax
mov eax, [ebp-8]
push eax
mov eax, [ebp-12]
pop ecx
add ecx, eax
add esp, 16
pop ebp
ret
add esp, 16
pop ebp
ret
#define BCA 10
#define ABC BCA+BCA*5
#if ABC == 20
#define ABC 1
#endif
int main()
{
int x;
x = ABC;
}
[x=[BCA+[BCA*5]
]
]
section .data
section .text
global main
; main function
main:
push ebp
mov ebp, esp
sub esp, 16
main: resolver.c:532: resolver_follow_identifier: Assertion `entity' failed.
Aborted (core dumped)
int test(char* msg)
{
int k;
k = 50 - -10;
}
Generates
[k=[50-{*10}]]
section .data
section .text
; test function
test:
push ebp
mov ebp, esp
sub esp, 16
mov eax, 50
sub eax, 10
neg eax
mov dword [ebp-4], eax
add esp, 16
pop ebp
ret
Expecting
[k=[50-{*10}]]
section .data
section .text
; test function
test:
push ebp
mov ebp, esp
sub esp, 16
mov eax, 50
push eax
mov eax, 10
neg eax
pop ecx
sub eax, ecx
mov dword [ebp-4], eax
add esp, 16
pop ebp
ret
Likely an issue with error code handling when returning from a unit test. Seems workflow may be ignoring it.
Tests pass successfully on local machine after a "make all". Unit tests run by Github may have not actually failed. Clone and call "make all" to test and see.
int main()
{
int x = \
50;
}
#define __restrict restrict
Does not work properly because "restrict" is a keyword. This should not be a determinator to weather or not the preprocessor works or not.
int* b = 0;
int main()
{
*b = 50;
}
Caused the "main" function to no longer exist in the tree.
#include <stddef.h>
int main()
{
int x = 15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t);
}
int main()
{
int x;
x = 56+87;
return x;
}
main:
push ebp
mov ebp, esp
sub esp, 16
mov eax, 56
add eax, 87
mov dword [ebp-4], eax
mov eax, [ebp-4]
pop ebp
ret
add esp, 16
pop ebp
ret
It seems structure variables declared in global scope produce a datasize but not a default value of zero as required by NASM assembler.
section .data
; AAA aa
aa: dq
Generates tree: [[k={*k}]+50]
We are expecting [k=[{*k}+50]] what we are getting sets the variable k and then adds 50 to the assignment its self.
int main()
{
int x;
x = 50+40+20+40+50+(500*2);
return x;
}
Points a;
Leads to an infinite loop
Well who would of thought, this is possible in the C standard, I guess it makes sense just didn't think of this before
#define ABC typedef
ABC int bbb
Unfortunately my implementation didn't account for this, so we will need to fix this bug.
Unexpected keyword typedef
on line 5, col 0
We expect: [40*20]+[40*60]
Structure forward declaration is used as a basis for calculating structure size and attributes. This should be ignored by checking for the flag that states this is just a forward declaration
/* Copyright (C) 1991-2020 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
<https://www.gnu.org/licenses/>. */
#ifndef __struct_FILE_defined
#define __struct_FILE_defined 1
/* Caution: The contents of this file are not part of the official
stdio.h API. However, much of it is part of the official *binary*
interface, and therefore cannot be changed. */
#if defined _IO_USE_OLD_IO_FILE && !defined _LIBC
# error "_IO_USE_OLD_IO_FILE should only be defined when building libc itself"
#endif
#if defined _IO_lock_t_defined && !defined _LIBC
# error "_IO_lock_t_defined should only be defined when building libc itself"
#endif
#include <bits/types.h>
struct _IO_FILE;
struct _IO_marker;
struct _IO_codecvt;
struct _IO_wide_data;
/* During the build of glibc itself, _IO_lock_t will already have been
defined by internal headers. */
#ifndef _IO_lock_t_defined
typedef void _IO_lock_t;
#endif
/* The tag name of this struct is _IO_FILE to preserve historic
C++ mangled names for functions taking FILE* arguments.
That name should not be used in new code. */
struct _IO_FILE
{
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
/* The following pointers correspond to the C++ streambuf protocol. */
char *_IO_read_ptr; /* Current read pointer */
char *_IO_read_end; /* End of get area. */
char *_IO_read_base; /* Start of putback+get area. */
char *_IO_write_base; /* Start of put area. */
char *_IO_write_ptr; /* Current put pointer. */
char *_IO_write_end; /* End of put area. */
char *_IO_buf_base; /* Start of reserve area. */
char *_IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
int _fileno;
int _flags2;
/* 1+column number of pbase(); 0 is unknown. */
unsigned int _cur_column;
signed char _vtable_offset;
};
// Bug with hexadecimal and binary in this particular region
#define IO_USER_LOCK 0x10
/* Many more flag bits are defined internally. */
main: ./helpers/vector.c:21: vector_assert_bounds_for_pop: Assertion `vector_in_bounds_for_pop(vector, index)' failed.
Aborted (core dumped)
int printf(const char* msg, int m)
{
}
causes a segmentation fault.
program received signal SIGSEGV, Segmentation fault.
0x0000555555558f4c in parser_scope_offset_for_stack (node=0x55555557b900, history=0x55555557b8e0) at parser.c:254
254 if (!variable_node_is_primative(node) && variable_struct_node(node)->_struct.body_n->body.padded)
(gdb) bt
#0 0x0000555555558f4c in parser_scope_offset_for_stack (node=0x55555557b900, history=0x55555557b8e0) at parser.c:254
#1 0x00005555555590cd in parser_scope_offset (node=0x55555557b900, history=0x55555557b8e0) at parser.c:299
#2 0x000055555555c5c0 in parse_variable (dtype=0x7fffffffda50, name_token=0x5555555747a0, history=0x55555557b8e0)
at parser.c:1690
#3 0x000055555555c68d in parse_variable_full (history=0x55555557b8e0) at parser.c:1710
#4 0x000055555555c708 in parse_function_arguments (history=0x55555557a0c0) at parser.c:1725
#5 0x000055555555c828 in parse_function (dtype=0x7fffffffdb70, name_token=0x555555574740, history=0x555555579f20)
at parser.c:1761
int main()
{
int x;
x = 20+30+40+50*10 ? (500*2) : (200*4);
return x;
}
The code above ends up with a parentheses whose left node is the main function its self this is an expression bug.
The parentheses is ignored
int main()
{
int x;
x = ((56) + 10);
}
main: ./helpers/vector.c:21: vector_assert_bounds_for_pop: Assertion `vector_in_bounds_for_pop(vector, index)' failed.
Aborted (core dumped)
Example: x = x ^ x + 10;
Gives us:
push ebp
mov ebp, esp
sub esp, 16
mov eax, [ebp-1]
add eax, [ebp-1]
add eax, 10
mov byte [ebp-1], eax
add esp, 16
pop ebp
ret
struct abc
{
int a;
char b;
int c;
int z;
};
struct abc d;
int main()
{
struct abc z;
z.z = 50;
z.b = 20;
z.c = 30;
}
problem is with z.z due to the stack variable sharing the same name as the member we have as segmentation fault during a pop in the resolver.
struct abc
{
int a;
char b;
int c;
};
struct abc d;
int main()
{
struct abc a;
a.a = 50;
a.b = 20;
a.c = 30;
d.a = 1;
d.b = 2;
d.c = 3;
return a.a + a.b + a.c + d.c + d.b + d.a;
}
main function
main:
push ebp
mov ebp, esp
sub esp, 16
mov eax, 50
mov dword [ebp-12], eax
mov eax, 20
mov byte [ebp-8], al
mov eax, 30
mov dword [ebp-4], eax
mov eax, 1
mov dword [d], eax
mov eax, 2
mov byte [d+4], al
mov eax, 3
mov dword [d+8], eax
mov eax, [d]
add eax, [d+4]
add eax, [d+8]
add eax, [ebp-4]
add eax, [ebp-8]
add eax, [ebp-12]
add esp, 16
pop ebp
ret
add esp, 16
pop ebp
ret
We have a huge problem with preprocessor definitions, if they do not contain literal values then they cannot be used throughout the preprocessor. This is wrong and in C your allowed to do this.
#define ABC 50+10
#if ABC >= 20
#define ABC 100
#endif
int main()
{
int x;
x = ABC;
}
Complains that ABC has more than one value.
int main()
{
int x;
x = 5;
while(x != 2)
{
x = x -1;
}
return x;
}
Compiler generates instruction
mov eax, 1
sub eax, [ebp-4]
Therefore we get invalid result in EAX when it is then saved back into [ebp-4] causing an infinite loop of undefined behaviour.
k = 5+a;
Causes a lexer error and says operator "+" is not valid. The lexer is unable to see them as separate entities.
int x;
int main()
{
x = sizeof(int);
}
#define ABC (50 && 20)
Does not work properly because of the paraentheses, it is mistaken for a macro function.
We have a bug with function prototypes, they cause a seg fault and it seems they are mistaken for variables.
int printf(const char* msg);
int main()
{
printf("hello");
}
#define BCA 10
#define ABC BCA+BCA*5
#if ABC == 20
#define ABC 1
#endif
int main()
{
int x;
x = ABC;
}
The given operator * is not supported for unary evaluation in the preprocessor on line 11, col 1
#if ((!defined __STRICT_ANSI__ || (defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 500)) && !defined _POSIX_SOURCE && !defined _POSIX_C_SOURCE)
#endif
Causes an error.
main: expressionable.c:97: expressionable_expect_sym: Assertion `0 == 1 && "Expecting the symbol %c but something else was provided"' failed.
Aborted (core dumped)
int special(char c1, int i1)
{
return c1+i1;
}
int main()
{
return special(22, 10);
}
section .data
section .text
global special
; special function
special:
push ebp
mov ebp, esp
mov eax, [ebp+5]
add eax, [ebp+12]
pop ebp
ret
pop ebp
ret
global main
; main function
main:
push ebp
mov ebp, esp
mov eax, 10
PUSH EAX
mov eax, 22
PUSH EAX
call special
add esp, 8
pop ebp
ret
pop ebp
ret
It seems the two function argument test is failing, therefore we might have a problem with how we extract characters from the stack.
int test(char* msg)
{
char* x;
char e;
char d;
int k;
k = ((d)+20);
}
#define ABC 50
#define CBA ABC
#if CBA == 50
#warning "valid"
#endif
Problem with logical operators, we are not converting result to true or false, we are allowing the numeric value stored in EAX to determine true or false which is wrong.
#define __WORDSIZE 32
#if __WORDSIZE == 32
#elif __WORDSIZE == 64
#else
# error "abc"
#endif
int main()
{
return 55;
}
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.