├── Makefile ├── README ├── TODO ├── block.c ├── ccg.c ├── ccg.h ├── commandline.c ├── constant.c ├── expression.c ├── function.c ├── integer.c ├── label.c ├── operand.c ├── pointer.c ├── reported_bugs ├── statement.c ├── types.h ├── utils.c └── variable.c /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CC=gcc 3 | 4 | CFLAGS=-c -g -pipe -Wall -Wextra -std=c11 5 | LDLIBS=-lm 6 | 7 | SOURCES=$(wildcard *.c) 8 | OBJECTS=$(SOURCES:.c=.o) 9 | EXECUTABLE=ccg 10 | 11 | all: $(SOURCES) $(EXECUTABLE) 12 | 13 | $(EXECUTABLE): $(OBJECTS) 14 | $(CC) $(OBJECTS) $(LDLIBS) -o $@ 15 | 16 | .c.o: 17 | $(CC) $(CFLAGS) $< -o $@ 18 | 19 | clean: 20 | rm -rf *.o $(EXECUTABLE) 21 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | CCG is the C Code Generator. It aims to produce chaotic and random C89 code in order to stress a bit compilers (just as csmith does). 2 | The generated code is not meant to be run (yet), so CCG can only be used to search for crashes, not miscompilations. 3 | 4 | UPDATE: compilers have now caught up with ccg (since it's been pretty hard to spot crashes last time I tried) so I may come up with a more robust approach in the future to generate more evil structures :-) 5 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * Generate structures, pointers, arrays. 2 | * Bitwise operators. 3 | * Optimize it a bit. -------------------------------------------------------------------------------- /block.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | /* `nesting' is the nesting level of the block. func(){0 {1} {1 {2}}} */ 27 | Block *makeBlock(Context *context, unsigned nesting) 28 | { 29 | size_t i, numlocalvars, numstatements; 30 | Block *ret = xmalloc(sizeof(*ret)); 31 | Context *bcontext = xmalloc(sizeof(*bcontext)); 32 | 33 | bcontext->currfunc = context->currfunc; 34 | bcontext->nvars = context->nvars; 35 | bcontext->nintegers = context->nintegers; 36 | bcontext->scope = NULL; 37 | 38 | copyVariableList(context->scope, &bcontext->scope); 39 | 40 | ret->localvars = NULL, ret->statementlist = NULL; 41 | 42 | numlocalvars = rand() % cmdline.max_localvars + !nesting; 43 | 44 | for(i = 0; i < numlocalvars; ++i) 45 | { 46 | Variable *tmp = makeVariable(bcontext, _randomvartype); 47 | bcontext->nvars++; 48 | 49 | if(tmp->type == _integer) 50 | bcontext->nintegers++; 51 | 52 | addVariableToList(tmp, &(ret->localvars)); 53 | addVariableToList(tmp, &bcontext->scope); 54 | } 55 | 56 | if(nesting < cmdline.max_block_nesting) 57 | { 58 | numstatements = cmdline.min_statements_per_block + 59 | (rand() % (cmdline.max_statements_per_block - cmdline.min_statements_per_block)); 60 | 61 | for(i = 0; i < numstatements; ++i) 62 | { 63 | Statement *tmp = makeStatement(bcontext, nesting, !(numstatements - 1 - i)); 64 | addStatementToList(tmp, &ret->statementlist); 65 | } 66 | } 67 | 68 | freeVariableList(bcontext->scope); 69 | free(bcontext); 70 | 71 | return ret; 72 | } 73 | 74 | 75 | void printBlock(Block *block) 76 | { 77 | VariableList *v; 78 | StatementList *s; 79 | 80 | puts("{"); 81 | 82 | foreach(v, block->localvars) 83 | printVariableDecl(v->variable); 84 | 85 | foreach(s, block->statementlist) 86 | printStatement(s->statement); 87 | 88 | puts("}"); 89 | } 90 | -------------------------------------------------------------------------------- /ccg.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | Program program; 27 | 28 | #ifdef DEBUG_MEMORY 29 | extern unsigned long long int allocated_bytes; 30 | #endif 31 | 32 | static unsigned getseed(void) 33 | { 34 | unsigned seed; 35 | int urandom = open("/dev/urandom", O_RDONLY); 36 | 37 | if(urandom == -1) 38 | die("couldn't open /dev/urandom for reading."); 39 | 40 | read(urandom, &seed, sizeof(unsigned)); 41 | close(urandom); 42 | 43 | return seed; 44 | } 45 | 46 | static void init(void) 47 | { 48 | program.globalvars = NULL, program.functions = NULL; 49 | program.numfunctions = program.numglobalvars = 0; 50 | 51 | /* Default settings */ 52 | cmdline.max_functions = 6; 53 | cmdline.max_localvars = 5; 54 | cmdline.max_function_parameters = 5; 55 | cmdline.min_statements_per_block = 2; 56 | cmdline.max_statements_per_block = 8; 57 | cmdline.max_expression_nesting = 8; 58 | cmdline.max_block_nesting = 7; 59 | cmdline.max_pointer_depth = 2; 60 | cmdline.seed = getseed(); 61 | cmdline.nojumps = false; 62 | } 63 | 64 | static void printProgram(void) 65 | { 66 | FunctionList *f; 67 | VariableList *v; 68 | 69 | printf("/* Seed: %d */\n", cmdline.seed); 70 | 71 | puts("#include "); 72 | puts("#include \n\n/* Global variables */"); 73 | 74 | foreach(v, program.globalvars) 75 | printVariableDecl(v->variable); 76 | 77 | puts("\n/* Function prototypes */"); 78 | 79 | foreach(f, program.functions) 80 | { 81 | printFunctionPrototype(f->function); 82 | puts(";"); 83 | } 84 | 85 | putchar('\n'); 86 | 87 | foreach(f, program.functions) 88 | printFunction(f->function); 89 | 90 | puts("\nint main(void)\n{\n" 91 | "func_0();\n" 92 | "return 0;\n}"); 93 | } 94 | 95 | int main(int argc, char **argv) 96 | { 97 | init(); 98 | processCommandline(argc, argv); 99 | srand(cmdline.seed); 100 | makeGlobalVariables(); 101 | makeFunction(false); 102 | printProgram(); 103 | 104 | #ifdef DEBUG_MEMORY 105 | fprintf(stderr, "Allocated bytes : %llu.\n", allocated_bytes); 106 | #endif 107 | 108 | return EXIT_SUCCESS; 109 | } 110 | -------------------------------------------------------------------------------- /ccg.h: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2012, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef CCG_INCLUDED 25 | #define CCG_INCLUDED 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #if defined __clang__ 39 | #if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 1) 40 | # error Clang 3.1 or newer is needed for C11 anonymous structs and unions 41 | #endif 42 | #elif defined __GNUC__ 43 | #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 +__GNUC_PATCHLEVEL__) 44 | #if GCC_VERSION < 40400 45 | # error GCC 4.4 or newer is needed for C11 anonymous structs and unions 46 | #endif 47 | #else 48 | #warning Your compiler might not support C11 anonymous structs and unions 49 | #endif 50 | 51 | #include "types.h" 52 | 53 | #define foreach(v, t) for((v = (t)); (v); (v = v->next)) 54 | 55 | #define INTEGERTYPE_SIZE(type) ((type == _i8 || type == _u8 ? 8 : (type == _i16 || type == _u16 ? 16 : (type == _i32 || type == _u32 ? 32 : 64)))) 56 | 57 | #define IS_UNSIGNED_INTEGERTYPE(type) (type == _u8 || type == _u16 || type == _u32 || type == _u64) 58 | 59 | #define RANDOM_BITNESS (8 * pow(2, rand() % 3)) 60 | 61 | #define USABLE_ID(var) (var->type == _pointer ? maxDerefdPointer(var) : var->name) 62 | 63 | 64 | #define CCG_VERSION "0.3" 65 | 66 | extern CommandlineOpt cmdline; 67 | extern Program program; 68 | extern char const * const inttype2str[_inttypemax]; 69 | extern char const * const testop2str[_testopmax]; 70 | extern char const * const arithop2str[_arithopmax]; 71 | extern char const * const assignop2str[_assignopmax]; 72 | 73 | /* Commandline processing */ 74 | void processCommandline(int, char**); 75 | 76 | /* Utils */ 77 | void die(const char*, ...); 78 | void info(const char*, ...); 79 | void *xmalloc(size_t); 80 | void *xcalloc(size_t, size_t); 81 | char *genStars(size_t n); 82 | 83 | /* Constant */ 84 | char *makeHexadecimalValue(unsigned); 85 | Constant *makeIntegerConstant(unsigned); 86 | void printConstant(Constant*); 87 | 88 | /* Variable */ 89 | Variable *makeVariable(Context*, VariableType); 90 | void addVariableToList(Variable*, VariableList**); 91 | void freeVariableList(VariableList*); 92 | void printVariableDecl(Variable*); 93 | void printVariableType(Variable*); 94 | void copyVariableList(VariableList*, VariableList**); 95 | Variable *selectVariable(Context*, VariableType); 96 | void makeGlobalVariables(void); 97 | IntegerType ultimateType(Variable*); 98 | 99 | /* Pointer */ 100 | void makePointer(Variable*, Context*); 101 | /* Variable *pickPointableVariable(Context*); */ 102 | size_t pointerDepth(Variable*); 103 | char *maxDerefdPointer(Variable*); 104 | void printPointerDecl(Variable*); 105 | 106 | /* Integer */ 107 | void makeInteger(Variable*, Context*); 108 | bool writeableIntegersExist(Context*); 109 | void printIntegerDecl(Variable*); 110 | 111 | /* Function */ 112 | Function *makeFunction(bool); 113 | void printFunction(Function*); 114 | void printFunctionPrototype(Function*); 115 | 116 | /* Block */ 117 | Block *makeBlock(Context*, unsigned); 118 | void printBlock(Block*); 119 | 120 | /* Statement */ 121 | void addStatementToList(Statement*, StatementList**); 122 | Statement *makeStatement(Context*, unsigned, bool); 123 | void printStatement(Statement*); 124 | 125 | /* Operand */ 126 | Operand *selectOperand(Context*); 127 | 128 | /* Expression */ 129 | void addExpressionToList(Expression*, ExpressionList**); 130 | Expression *makeExpression(Context*, unsigned); 131 | void printExpression(Expression*); 132 | 133 | /* Label */ 134 | Label *makeLabel(Context*); 135 | Label *selectLabel(Context*); 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /commandline.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | extern char *optarg; 27 | 28 | CommandlineOpt cmdline; 29 | 30 | static void printHelp(void) 31 | { 32 | puts(" -h, --help\t\t\tShow this help"); 33 | puts(" -v, --version\t\t\tPrint the version of CCG"); 34 | puts(" --seed\t\t\tUse a custom seed (instead of a random one)"); 35 | puts(" --max-functions\t\tMax number of functions to be generated (default 12)"); 36 | puts(" --max-localvars\t\tMax number of variables in a block (default 4)"); 37 | puts(" --max-function-parameters\tMax number of parameters for a function (default 4)"); 38 | puts(" --min-statements-per-block\tMin number of statements in each block (default 2)"); 39 | puts(" --max-statements-per-block\tMax number of statements in each block (default 7)"); 40 | puts(" --max-expression-nesting\tControl the complexity of the expressions (default 8)"); 41 | puts(" --max-block-nesting\t\tControl the nesting of the blocks (default 7)"); 42 | puts(" --max-pointer-depth\t\tMaximum depth of a pointer (default 2)"); 43 | puts(" --no-jumps\t\t\tDisables jumps (enabled by default)"); 44 | puts(" --no-omitted-operand-conditional\tDisable x ? : z conditionals without second operand"); 45 | exit(EXIT_SUCCESS); 46 | } 47 | 48 | static void printVersion(void) 49 | { 50 | puts("This is ccg version " CCG_VERSION); 51 | exit(EXIT_SUCCESS); 52 | } 53 | 54 | static void setopt(int index) 55 | { 56 | unsigned * const index2member[] = 57 | { 58 | &cmdline.seed, 59 | &cmdline.max_functions, 60 | &cmdline.max_localvars, 61 | &cmdline.max_function_parameters, 62 | &cmdline.min_statements_per_block, 63 | 64 | &cmdline.max_statements_per_block, 65 | &cmdline.max_expression_nesting, 66 | &cmdline.max_block_nesting, 67 | &cmdline.max_pointer_depth 68 | }; 69 | 70 | if(index >= 0 && index < 9) 71 | *(index2member[index]) = strtol(optarg, NULL, 10); 72 | else if (index == 9) 73 | cmdline.no_omitted_operand_conditional = true; 74 | else if(index == 10) 75 | cmdline.nojumps = true; 76 | else if(index == 11) 77 | printHelp(); 78 | else if(index == 12) 79 | printVersion(); 80 | 81 | /* Sanity check */ 82 | if(cmdline.max_pointer_depth == 0) 83 | die("the maximum pointer depth can't be 0 !"); 84 | } 85 | 86 | void processCommandline(int argc, char **argv) 87 | { 88 | int c, index = 0; 89 | 90 | const struct option longopt[] = 91 | { 92 | {"seed", required_argument, NULL, 0}, 93 | {"max-functions", required_argument, NULL, 0}, 94 | {"max-localvars", required_argument, NULL, 0}, 95 | {"max-function-parameters", required_argument, NULL, 0}, 96 | {"min-statements-per-block", required_argument, NULL, 0}, 97 | {"max-statements-per-block", required_argument, NULL, 0}, 98 | {"max-expression-nesting", required_argument, NULL, 0}, 99 | {"max-block-nesting", required_argument, NULL, 0}, 100 | {"max-pointer-depth", required_argument, NULL, 0}, 101 | {"no-omitted-operand-conditional", no_argument, NULL, 0}, 102 | {"no-jumps", no_argument, NULL, 0}, 103 | {"help", no_argument, NULL, 0}, 104 | {"version", no_argument, NULL, 0}, 105 | {NULL, 0, NULL, 0} 106 | }; 107 | 108 | while((c = getopt_long(argc, argv, "hv", longopt, &index)) != -1) 109 | { 110 | switch(c) 111 | { 112 | case 0: 113 | setopt(index); 114 | break; 115 | 116 | case 'h': 117 | printHelp(); 118 | break; 119 | 120 | case 'v': 121 | printVersion(); 122 | break; 123 | 124 | default: 125 | break; 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /constant.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | static const char *hexdigits = "0123456789ABCDEF"; 27 | 28 | char *makeHexadecimalValue(unsigned digitNumber) 29 | { 30 | size_t i; 31 | char *ret = xcalloc(digitNumber + 1, 1); 32 | 33 | for(i = 0; i < digitNumber; ++i) 34 | ret[i] = hexdigits[rand() % 16]; 35 | 36 | return ret; 37 | } 38 | 39 | /* For now, the generated integers are strictly positive */ 40 | Constant *makeIntegerConstant(unsigned bits) 41 | { 42 | Constant *ret = xmalloc(sizeof(*ret)); 43 | char *hexvalue = ((rand() % 4) ? makeHexadecimalValue(bits / 4) : "0"); /* 25 % of the time, a zero is generated */ 44 | 45 | ret->value = xcalloc(4 + strlen(hexvalue), 1); 46 | ret->bitness = bits; 47 | 48 | sprintf(ret->value, "0x%s", hexvalue); 49 | 50 | if(strlen(hexvalue) > 1) 51 | free(hexvalue); 52 | 53 | return ret; 54 | } 55 | 56 | void printConstant(Constant *constant) 57 | { 58 | fputs(constant->value, stdout); 59 | /* And... we are done. */ 60 | } 61 | -------------------------------------------------------------------------------- /expression.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | static const ExpressionType exprarray[10] = {_ternaryexpr, _functioncallexpr, _functioncallexpr, _operationexpr, _operationexpr, _operationexpr, _testexpr, _testexpr, _assignmentexpr, _assignmentexpr}; 27 | 28 | char const * const testop2str[_testopmax] = {"==", "<=", ">=", "<", ">", "!="}; 29 | char const * const arithop2str[_arithopmax] = {"+", "-", "/", "%", "*"}; 30 | char const * const bitwiseop2str[_bitwiseopmax] = {"&", "|", "^", "<<", ">>"}; 31 | char const * const logicalop2str[_logicalopmax] = {"&&", "||"}; 32 | char const * const assignop2str[_assignopmax] = {"+=", "-=", "/=", "%=", "*=", "&=", "|=", "^=", "=", "<<=", ">>="}; 33 | 34 | static void buildOperand(Expression*, Context*, unsigned); 35 | static void buildTernary(Expression *expr, Context*, unsigned); 36 | static void buildOperation(Expression*, Context*, unsigned); 37 | static void buildTest(Expression*, Context*, unsigned); 38 | static void buildAssignment(Expression*, Context*, unsigned); 39 | static void buildFunctionCall(Expression*, Context*, unsigned); 40 | 41 | static void (*buildfunctions[_expressiontypemax])(Expression*, Context*, unsigned) = 42 | { 43 | [_operandexpr] = buildOperand, 44 | [_ternaryexpr] = buildTernary, 45 | [_operationexpr] = buildOperation, 46 | [_testexpr] = buildTest, 47 | [_assignmentexpr] = buildAssignment, 48 | [_functioncallexpr] = buildFunctionCall 49 | }; 50 | 51 | void addExpressionToList(Expression *expression, ExpressionList **list) 52 | { 53 | if(!*list) 54 | { 55 | *list = xmalloc(sizeof(**list)); 56 | (*list)->expression = expression; 57 | (*list)->next = NULL; 58 | } 59 | 60 | else 61 | { 62 | ExpressionList *e; 63 | 64 | for(e = *list; e->next; e = e->next); 65 | e->next = xmalloc(sizeof(*e->next)); 66 | e->next->expression = expression; 67 | e->next->next = NULL; 68 | } 69 | } 70 | 71 | #define EXPRESSION_IS_INVALID(t) (((t) == _functioncallexpr && program.numfunctions >= cmdline.max_functions)) 72 | 73 | Expression *makeExpression(Context *context, unsigned nesting) 74 | { 75 | Expression *expression = xmalloc(sizeof(*expression)); 76 | 77 | if(nesting >= cmdline.max_expression_nesting) 78 | expression->type = _operandexpr; 79 | else 80 | { 81 | do 82 | expression->type = exprarray[rand() % (sizeof(exprarray) / sizeof(*exprarray))]; 83 | while(EXPRESSION_IS_INVALID(expression->type)); 84 | } 85 | 86 | (buildfunctions[expression->type])(expression, context, nesting + 1); 87 | 88 | return expression; 89 | } 90 | 91 | static void buildOperand(Expression *expression, Context *context, unsigned nesting) 92 | { 93 | expression->expr.operand = selectOperand(context); 94 | } 95 | 96 | static void buildTest(Expression *expression, Context *context, unsigned nesting) 97 | { 98 | struct TestExpression *te = xmalloc(sizeof(*te)); 99 | 100 | te->op = rand() % _testopmax; 101 | te->lefthand = makeExpression(context, nesting + 1); 102 | te->righthand = makeExpression(context, nesting + 1); 103 | 104 | expression->expr.testexpr = te; 105 | } 106 | 107 | static void buildTernary(Expression *expression, Context *context, unsigned nesting) 108 | { 109 | struct TernaryExpression *te = xmalloc(sizeof(*te)); 110 | 111 | te->test = makeExpression(context, nesting + 1); 112 | te->truepath = (cmdline.no_omitted_operand_conditional || rand() % 5) ? makeExpression(context, nesting + 1) : NULL; 113 | te->falsepath = makeExpression(context, nesting + 1); 114 | expression->expr.ternexpr = te; 115 | } 116 | 117 | static void buildOperation(Expression *expression, Context *context, unsigned nesting) 118 | { 119 | struct OperationExpression *oe = xmalloc(sizeof(*oe)); 120 | 121 | oe->lefthand = makeExpression(context, nesting + 1); 122 | oe->righthand = makeExpression(context, nesting + 1); 123 | oe->type = rand() % _operationtypemax; 124 | 125 | if(oe->type == _arithmetic) 126 | oe->operator.arithop = rand() % _arithopmax; 127 | else if(oe->type == _bitwise) 128 | oe->operator.bitwiseop = rand() % _bitwiseopmax; 129 | else 130 | oe->operator.logicalop = rand() % _logicalopmax; 131 | 132 | expression->expr.opexpr = oe; 133 | } 134 | 135 | #define ASSIGNMENT_OP_IS_INVALID(oprtr, left, right) ((((left->type == _double || left->type == _float) || (IS_FLOATING_POINT_VARIABLE(right))) && (oprtr == _assignmod))) 136 | 137 | static void buildAssignment(Expression *expression, Context *context, unsigned nesting) 138 | { 139 | struct AssignmentExpression *ae = xmalloc(sizeof(*ae)); 140 | 141 | ae->lvalue = selectVariable(context, _randomvartype); 142 | ae->rvalue = makeExpression(context, nesting + 1); 143 | ae->op = rand() % _assignopmax; 144 | 145 | expression->expr.assignexpr= ae; 146 | } 147 | 148 | static void buildFunctionCall(Expression *expression, Context *context, unsigned nesting) 149 | { 150 | struct FunctionCallExpression *fce = xmalloc(sizeof(*fce)); 151 | VariableList *v; 152 | 153 | fce->paramlist = NULL; 154 | fce->function = makeFunction(true); 155 | 156 | foreach(v, fce->function->paramlist) 157 | addExpressionToList(makeExpression(context, nesting + 1), (ExpressionList**) &fce->paramlist); 158 | 159 | expression->expr.funccallexpr = fce; 160 | } 161 | 162 | static void printOperand(Operand *op) 163 | { 164 | if(op->type == _variable) 165 | fputs(USABLE_ID(op->op.variable), stdout); 166 | else 167 | printConstant(op->op.constant); 168 | } 169 | 170 | static void printTest(struct TestExpression *te) 171 | { 172 | putchar('('); 173 | printExpression(te->lefthand); 174 | printf(" %s ", testop2str[te->op]); 175 | printExpression(te->righthand); 176 | putchar(')'); 177 | } 178 | 179 | static void printTernary(struct TernaryExpression *te) 180 | { 181 | putchar('('); 182 | printExpression(te->test); 183 | fputs(" ? ", stdout); 184 | 185 | if(te->truepath) 186 | printExpression(te->truepath); 187 | 188 | fputs(" : ", stdout); 189 | printExpression(te->falsepath); 190 | putchar(')'); 191 | } 192 | 193 | static void printOperation(struct OperationExpression *oe) 194 | { 195 | putchar('('); 196 | printExpression(oe->lefthand); 197 | 198 | switch (oe->type) 199 | { 200 | case _arithmetic: printf( " %s ", arithop2str[oe->operator.arithop]); break; 201 | case _bitwise: printf( " %s ", bitwiseop2str[oe->operator.bitwiseop]); break; 202 | case _logical: printf( " %s ", logicalop2str[oe->operator.logicalop]); break; 203 | default: die("bad oe->type"); 204 | } 205 | 206 | printExpression(oe->righthand); 207 | putchar(')'); 208 | } 209 | 210 | static void printAssignment(struct AssignmentExpression *ae) 211 | { 212 | putchar('('); 213 | printf("%s %s ", USABLE_ID(ae->lvalue), assignop2str[ae->op]); 214 | printExpression(ae->rvalue); 215 | putchar(')'); 216 | } 217 | 218 | static void printFunctionCall(struct FunctionCallExpression *fce) 219 | { 220 | ExpressionList *e; 221 | 222 | printf("%s(", fce->function->name); 223 | 224 | foreach(e, fce->paramlist) 225 | { 226 | printExpression(e->expression); 227 | 228 | if(e->next) 229 | fputs(", ", stdout); 230 | } 231 | 232 | putchar(')'); 233 | } 234 | 235 | void printExpression(Expression *expression) 236 | { 237 | switch(expression->type) 238 | { 239 | case _operandexpr: printOperand(expression->expr.operand); break; 240 | case _ternaryexpr: printTernary(expression->expr.ternexpr); break; 241 | case _operationexpr: printOperation(expression->expr.opexpr); break; 242 | case _testexpr: printTest(expression->expr.testexpr); break; 243 | case _assignmentexpr: printAssignment(expression->expr.assignexpr); break; 244 | case _functioncallexpr: printFunctionCall(expression->expr.funccallexpr); break; 245 | default: die("are you... mad ?"); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /function.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | Context context; 27 | 28 | static void addFunctionToList(Function *function, FunctionList **list) 29 | { 30 | if(!*list) 31 | { 32 | *list = xmalloc(sizeof(**list)); 33 | (*list)->function = function; 34 | (*list)->next = NULL; 35 | } 36 | 37 | else 38 | { 39 | FunctionList *v; 40 | 41 | for(v = *list; v->next; v = v->next); 42 | v->next = xmalloc(sizeof(*v->next)); 43 | v->next->function = function; 44 | v->next->next = NULL; 45 | } 46 | } 47 | 48 | static char *makeFunctionName(void) 49 | { 50 | char *name; 51 | char buff[8]; 52 | 53 | sprintf(buff, "%zu", program.numfunctions); 54 | name = malloc(strlen(buff) + 6); 55 | sprintf(name, "func_%zu", program.numfunctions); 56 | 57 | return name; 58 | } 59 | 60 | /* At this point, only global variables are available */ 61 | Function *makeFunction(bool params) 62 | { 63 | short i, numparams = 0; 64 | Function *ret = xmalloc(sizeof(*ret)); 65 | 66 | Context *context = xmalloc(sizeof(*context)); 67 | context->scope = params ? NULL : program.globalvars; 68 | context->currfunc = ret; 69 | 70 | ret->paramlist = NULL; 71 | ret->returntype = rand() % _inttypemax; 72 | ret->name = makeFunctionName(); 73 | ret->isStatic = (rand() % 10) == 0; 74 | ret->numlabels = 0; 75 | ret->labels = NULL; 76 | 77 | context->nvars = context->nintegers = program.numglobalvars; 78 | numparams = (params ? rand() % (cmdline.max_function_parameters + 1) : 0); 79 | 80 | program.numfunctions++; 81 | 82 | if(params) 83 | { 84 | copyVariableList(program.globalvars, &context->scope); 85 | 86 | for(i = 0; i < numparams; ++i) 87 | { 88 | Variable *v = makeVariable(context, _integer); 89 | context->nvars++; 90 | 91 | if(v->type == _integer) 92 | context->nintegers++; 93 | 94 | addVariableToList(v, &ret->paramlist); 95 | addVariableToList(v, &context->scope); 96 | } 97 | } 98 | 99 | ret->body = makeBlock(context, 0); 100 | 101 | addFunctionToList(ret, &program.functions); 102 | 103 | if(params) 104 | freeVariableList(context->scope); 105 | 106 | free(context); 107 | 108 | return ret; 109 | } 110 | 111 | void printFunctionPrototype(Function *function) 112 | { 113 | VariableList *v; 114 | 115 | if (function->isStatic) 116 | { 117 | printf( "static "); 118 | } 119 | printf("%s %s(", inttype2str[function->returntype], function->name); 120 | 121 | foreach(v, function->paramlist) 122 | { 123 | printf(v == function->paramlist ? "" : ", "); 124 | printVariableType(v->variable); 125 | printf(" %s", v->variable->name); 126 | } 127 | 128 | printf(")"); 129 | } 130 | 131 | void printFunction(Function *function) 132 | { 133 | printFunctionPrototype(function); 134 | putchar('\n'); 135 | printBlock(function->body); 136 | } 137 | -------------------------------------------------------------------------------- /integer.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | static char const * const inttype2varid[_inttypemax] = {"c", "uc", "s", "us", "i", "ui", "li", "uli"}; 27 | char const * const inttype2str[_inttypemax] = {"int8_t", "uint8_t", "int16_t", "uint16_t", "int32_t", "uint32_t", "int64_t", "uint64_t"}; 28 | 29 | static char *makeIntegerName(IntegerType type, Context *context) 30 | { 31 | char buffer[32] = {0}, *ret; 32 | 33 | sprintf(buffer, "%s_%u", inttype2varid[type], context->nvars); 34 | ret = xmalloc(strlen(buffer) + 1); 35 | strcpy(ret, buffer); 36 | 37 | return ret; 38 | } 39 | 40 | void makeInteger(Variable *var, Context *context) 41 | { 42 | var->intvar.type = rand() % _inttypemax; 43 | var->intvar.initializer = makeIntegerConstant(INTEGERTYPE_SIZE(var->intvar.type)); 44 | var->name = makeIntegerName(var->intvar.type, context); 45 | } 46 | 47 | void printIntegerDecl(Variable *var) 48 | { 49 | printf("%s %s = %s;\n", inttype2str[var->intvar.type], var->name, var->intvar.initializer->value); 50 | } 51 | -------------------------------------------------------------------------------- /label.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | static void addLabelToList(Label *label, LabelList **list) 27 | { 28 | if(!*list) 29 | { 30 | *list = xmalloc(sizeof(**list)); 31 | (*list)->label = label; 32 | (*list)->next = NULL; 33 | } 34 | 35 | else 36 | { 37 | LabelList *v; 38 | 39 | for(v = *list; v->next; v = v->next); 40 | v->next = xmalloc(sizeof(*v->next)); 41 | v->next->label = label; 42 | v->next->next = NULL; 43 | } 44 | } 45 | 46 | Label *makeLabel(Context *context) 47 | { 48 | Label *ret = xmalloc(sizeof(*ret)); 49 | 50 | ret->name = xmalloc(12); 51 | sprintf(ret->name, "lbl%s", makeHexadecimalValue(8)); 52 | context->currfunc->numlabels++; 53 | 54 | addLabelToList(ret, &context->currfunc->labels); 55 | 56 | return ret; 57 | } 58 | 59 | Label *selectLabel(Context *context) 60 | { 61 | unsigned n = rand() % context->currfunc->numlabels, c = 0; 62 | LabelList *l; 63 | 64 | foreach(l, context->currfunc->labels) 65 | { 66 | if(l->label && c++ == n) 67 | return l->label; 68 | } 69 | 70 | die("unreachable !"); 71 | return NULL; 72 | } 73 | -------------------------------------------------------------------------------- /operand.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | Operand *selectOperand(Context *context) 27 | { 28 | Operand *operand = xmalloc(sizeof(*operand)); 29 | 30 | operand->type = (rand() % 3 == 0) ? _constant : _variable; 31 | 32 | if(operand->type == _variable) 33 | operand->op.variable = selectVariable(context, _randomvartype); 34 | else 35 | operand->op.constant = makeIntegerConstant(RANDOM_BITNESS); 36 | 37 | return operand; 38 | } 39 | -------------------------------------------------------------------------------- /pointer.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | #define VARIABLE_IS_NOT_POINTABLE(var) (pointerDepth(var) >= cmdline.max_pointer_depth) 27 | 28 | static char *makePointerName(Context *context) 29 | { 30 | char *ret, buff[16]; 31 | 32 | sprintf(buff, "ptr_%u", context->nvars); 33 | ret = xmalloc(strlen(buff) + 1); 34 | strcpy(ret, buff); 35 | 36 | return ret; 37 | } 38 | 39 | static Variable *pickPointableVariable(Context *context) 40 | { 41 | VariableList *v; 42 | Variable *ret = NULL; 43 | 44 | do 45 | { 46 | size_t t = rand() % context->nvars, i = 0; 47 | 48 | foreach(v, context->scope) 49 | { 50 | if(i++ == t) 51 | ret = v->variable; 52 | } 53 | 54 | } while(VARIABLE_IS_NOT_POINTABLE(ret)); 55 | 56 | return ret; 57 | } 58 | 59 | void makePointer(Variable *var, Context *context) 60 | { 61 | var->pointer.pointed = pickPointableVariable(context); 62 | var->name = makePointerName(context); 63 | } 64 | 65 | 66 | inline size_t pointerDepth(Variable *var) 67 | { 68 | size_t n = 0; 69 | 70 | while(var->type == _pointer) 71 | { 72 | ++n; 73 | var = var->pointer.pointed; 74 | } 75 | 76 | return n; 77 | } 78 | 79 | /* This function goes through all the pointers to find the type of the ultimately pointed integer ! */ 80 | IntegerType ultimateType(Variable *var) 81 | { 82 | while(var->type == _pointer) 83 | var = var->pointer.pointed; 84 | 85 | return var->intvar.type; 86 | } 87 | 88 | char *maxDerefdPointer(Variable *var) 89 | { 90 | static char buffer[32]; 91 | size_t depth = pointerDepth(var); 92 | 93 | memset(buffer, '*', depth); 94 | buffer[depth] = 0; 95 | 96 | strcat(buffer, var->name); 97 | 98 | return buffer; 99 | } 100 | 101 | void printPointerDecl(Variable *var) 102 | { 103 | size_t i, depth = pointerDepth(var); 104 | 105 | printf("%s ", inttype2str[ultimateType(var)]); 106 | 107 | for(i = 0; i < depth; ++i) 108 | putchar('*'); 109 | 110 | printf("%s = &%s;\n", var->name, var->pointer.pointed->name); 111 | } 112 | -------------------------------------------------------------------------------- /reported_bugs: -------------------------------------------------------------------------------- 1 | LLVM/Clang 2 | 3 | * (05/18/12) http://llvm.org/bugs/show_bug.cgi?id=12868 (fixed) 4 | * (05/19/12) http://llvm.org/bugs/show_bug.cgi?id=12886 (fixed) 5 | * (05/19/12) http://llvm.org/bugs/show_bug.cgi?id=12887 (fixed) 6 | * (05/20/12) http://llvm.org/bugs/show_bug.cgi?id=12889 (fixed) 7 | * (05/20/12) http://llvm.org/bugs/show_bug.cgi?id=12897 (fixed) 8 | * (05/23/12) http://llvm.org/bugs/show_bug.cgi?id=12927 (fixed) 9 | * (05/23/12) http://llvm.org/bugs/show_bug.cgi?id=12929 (fixed) 10 | * (05/27/12) http://llvm.org/bugs/show_bug.cgi?id=12963 (fixed) 11 | * (06/04/12) http://llvm.org/bugs/show_bug.cgi?id=13021 12 | * (06/22/12) http://llvm.org/bugs/show_bug.cgi?id=13180 (fixed) 13 | * (06/23/12) http://llvm.org/bugs/show_bug.cgi?id=13185 (fixed) 14 | * (06/28/12) http://llvm.org/bugs/show_bug.cgi?id=13228 (fixed) 15 | * (06/30/12) http://llvm.org/bugs/show_bug.cgi?id=13244 (fixed) 16 | * (07/18/12) http://llvm.org/bugs/show_bug.cgi?id=13390 (fixed) 17 | * (07/19/12) http://llvm.org/bugs/show_bug.cgi?id=13402 (fixed) 18 | * (10/19/12) http://llvm.org/bugs/show_bug.cgi?id=14131 (fixed) 19 | * (10/19/12) http://llvm.org/bugs/show_bug.cgi?id=14132 (fixed) 20 | * (10/20/12) http://llvm.org/bugs/show_bug.cgi?id=14133 (fixed) 21 | * (10/27/12) http://llvm.org/bugs/show_bug.cgi?id=14197 (fixed) 22 | * (11/03/12) http://llvm.org/bugs/show_bug.cgi?id=14248 (fixed) 23 | * (11/06/12) http://llvm.org/bugs/show_bug.cgi?id=14271 (fixed) 24 | * (12/08/12) http://llvm.org/bugs/show_bug.cgi?id=14544 (fixed) 25 | * (12/08/12) http://llvm.org/bugs/show_bug.cgi?id=14546 (fixed) 26 | * (12/08/12) http://llvm.org/bugs/show_bug.cgi?id=14547 (fixed) 27 | * (12/28/12) http://llvm.org/bugs/show_bug.cgi?id=14729 (fixed) 28 | * (12/28/12) http://llvm.org/bugs/show_bug.cgi?id=14732 (fixed) 29 | * (12/28/12) http://llvm.org/bugs/show_bug.cgi?id=14735 (fixed) 30 | * (12/29/12) http://llvm.org/bugs/show_bug.cgi?id=14742 (fixed) 31 | * (12/29/12) http://llvm.org/bugs/show_bug.cgi?id=14749 (fixed) 32 | * (01/20/13) http://llvm.org/bugs/show_bug.cgi?id=15008 (fixed) 33 | * (04/21/13) http://llvm.org/bugs/show_bug.cgi?id=15805 (fixed) 34 | * (04/26/13) http://llvm.org/bugs/show_bug.cgi?id=15851 (fixed) 35 | * (05/19/13) http://llvm.org/bugs/show_bug.cgi?id=16067 (fixed) 36 | * (07/15/13) http://llvm.org/bugs/show_bug.cgi?id=16628 (fixed) 37 | 38 | GCC 39 | 40 | * (05/20/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53418 (fixed) 41 | * (10/21/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55008 (fixed) 42 | * (10/21/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55010 (fixed) 43 | * (10/21/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55011 (fixed) 44 | * (10/28/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55107 (fixed) 45 | * (10/28/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55110 (fixed) 46 | * (10/28/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55111 (fixed) 47 | * (10/29/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55122 (fixed) 48 | * (10/29/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55124 (fixed) 49 | * (11/03/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55191 (fixed) 50 | * (11/11/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55270 (fixed) 51 | * (11/24/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55277 (fixed) 52 | * (12/31/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55831 (fixed) 53 | * (12/31/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55832 (fixed) 54 | * (12/31/12) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55833 (fixed) 55 | * (01/01/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55838 (fixed) 56 | * (01/03/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55862 (fixed) 57 | * (01/12/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55955 (fixed) 58 | * (01/13/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55964 (fixed) 59 | * (01/18/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56034 (fixed) 60 | * (01/18/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56035 (fixed) 61 | * (02/02/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56181 (fixed) 62 | * (02/03/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56195 (fixed) 63 | * (02/09/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56264 (fixed) 64 | * (02/15/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56349 (fixed) 65 | * (02/15/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56350 (fixed) 66 | * (02/17/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56366 (fixed) 67 | * (02/18/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56384 (fixed) 68 | * (02/22/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56426 (fixed) 69 | * (02/26/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56466 (fixed) 70 | * (03/01/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56494 (fixed) 71 | * (03/08/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56571 (fixed) 72 | * (03/23/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56695 (fixed) 73 | * (03/27/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56756 (fixed) 74 | * (04/26/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57081 (fixed) 75 | * (04/30/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57122 (fixed) 76 | * (05/06/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57185 (fixed) 77 | * (05/11/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57251 (fixed) 78 | * (05/18/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57322 (fixed) 79 | * (05/24/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57400 (fixed) 80 | * (05/28/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57442 (fixed) 81 | * (06/01/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57497 (fixed) 82 | * (06/22/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57676 (fixed) 83 | * (06/23/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57685 (fixed) 84 | * (07/26/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57993 (fixed) 85 | * (07/28/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58008 (fixed) 86 | * (07/28/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58010 (fixed) 87 | * (07/28/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58011 (fixed) 88 | * (12/07/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59417 (fixed) 89 | * (12/24/13) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59592 (fixed) 90 | * (07/20/15) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=66945 (fixed) 91 | * (07/21/15) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=66958 (fixed) 92 | * (07/25/15) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=67005 (fixed) 93 | * (08/12/15) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=67191 (fixed) 94 | * (08/12/17) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=81832 (fixed) 95 | -------------------------------------------------------------------------------- /statement.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | 27 | static const StatementType statarray[20] = {_if, _if, _if, _if, _for, _for, _for, _for, _assignment, _assignment, _assignment, _assignment, _ptrassignment, _ptrassignment, _ptrassignment, _functioncall, _functioncall, _functioncall, _goto, _return}; 28 | 29 | static void buildIf(Statement*, Context*, unsigned); 30 | static void buildFor(Statement*, Context*, unsigned); 31 | static void buildAssignment(Statement*, Context*, unsigned); 32 | static void buildPtrAssignment(Statement*, Context*, unsigned); 33 | static void buildFunctionCall(Statement*, Context*, unsigned); 34 | static void buildReturn(Statement*, Context*, unsigned); 35 | static void buildGoto(Statement*, Context*, unsigned); 36 | 37 | static void (*buildfunctions[_statementtypemax])(Statement*, Context*, unsigned) = 38 | { 39 | [_if] = buildIf, 40 | [_for] = buildFor, 41 | [_assignment] = buildAssignment, 42 | [_ptrassignment] = buildPtrAssignment, 43 | [_functioncall] = buildFunctionCall, 44 | [_return] = buildReturn, 45 | [_goto] = buildGoto 46 | }; 47 | 48 | void addStatementToList(Statement *statement, StatementList **list) 49 | { 50 | if(!*list) 51 | { 52 | *list = xmalloc(sizeof(**list)); 53 | (*list)->statement = statement; 54 | (*list)->next = NULL; 55 | } 56 | 57 | else 58 | { 59 | StatementList *s; 60 | 61 | for(s = *list; s->next; s = s->next); 62 | s->next = xmalloc(sizeof(*s->next)); 63 | s->next->statement = statement; 64 | s->next->next = NULL; 65 | } 66 | } 67 | 68 | #define IS_INVALID ((type == _ptrassignment && (context->nvars == context->nintegers))\ 69 | || (type == _functioncall && program.numfunctions >= cmdline.max_functions)\ 70 | || (type == _return && (!nesting || !lastofblock))\ 71 | || (type == _goto && (cmdline.nojumps || (context->currfunc->numlabels == 0)))) 72 | 73 | Statement *makeStatement(Context *context, unsigned nesting, bool lastofblock) 74 | { 75 | Statement *ret = xmalloc(sizeof(*ret)); 76 | StatementType type; 77 | 78 | do 79 | type = statarray[rand() % (sizeof(statarray) / sizeof(*statarray))]; 80 | while(IS_INVALID); 81 | 82 | /* 2% of chance to put a label */ 83 | if(!cmdline.nojumps && type != _goto && !(rand() % 50)) 84 | ret->label = makeLabel(context); 85 | else 86 | ret->label = NULL; 87 | 88 | (buildfunctions[(ret->type = type)])(ret, context, nesting); 89 | 90 | return ret; 91 | } 92 | 93 | 94 | /***** Build functions *****/ 95 | 96 | static void buildIf(Statement *statement, Context *context, unsigned nesting) 97 | { 98 | IfStatement *ifstatement = xmalloc(sizeof(*ifstatement)); 99 | 100 | ifstatement->condition = makeExpression(context, 0); 101 | ifstatement->truepath = makeBlock(context, nesting + 1); 102 | 103 | /* An else branch is generated 30% of the time */ 104 | ifstatement->falsepath = !(rand() % 3) ? makeBlock(context, nesting + 1) : NULL; 105 | 106 | statement->stmnt.ifstatement = ifstatement; 107 | } 108 | 109 | static void buildFor(Statement *statement, Context *context, unsigned nesting) 110 | { 111 | ForStatement *forstatement = xmalloc(sizeof(*forstatement)); 112 | 113 | forstatement->iterator = selectVariable(context, _randomvartype); 114 | 115 | /* The init var is in [-30;0[ u ]0;30] and the test val is in [30;89] */ 116 | /* forstatement->init = (rand() % 30 + 1) * ((forstatement->iterator->type == _integer ? IS_UNSIGNED_INTEGERTYPE(forstatement->iterator->intvar.type) : IS_UNSIGNED_INTEGERTYPE(ultimateType(forstatement->iterator))) ? 1 : ((rand() % 2) ? -1 : 1)); */ 117 | forstatement->init = rand() % 100; 118 | forstatement->testval = (rand() % 100) + 100; 119 | 120 | forstatement->testop = _lowerorequal; 121 | forstatement->incval = (rand() % 5) + 1; 122 | forstatement->assignop = _assigninc; 123 | 124 | forstatement->body = makeBlock(context, nesting + 1); 125 | 126 | statement->stmnt.forstatement = forstatement; 127 | } 128 | 129 | static void buildFunctionCall(Statement *statement, Context *context, unsigned nesting) 130 | { 131 | FunctionCallStatement *funccallstatement = xmalloc(sizeof(*funccallstatement)); 132 | funccallstatement->paramlist = NULL; 133 | VariableList *v; 134 | 135 | funccallstatement->function = makeFunction(true); 136 | 137 | foreach(v, funccallstatement->function->paramlist) 138 | addExpressionToList(makeExpression(context, nesting + 1), (ExpressionList**) &funccallstatement->paramlist); 139 | 140 | statement->stmnt.funccallstatement = funccallstatement; 141 | } 142 | 143 | static void buildAssignment(Statement *statement, Context *context, unsigned nesting) 144 | { 145 | AssignmentStatement *as = xmalloc(sizeof(*as)); 146 | 147 | as->var = selectVariable(context, _randomvartype); 148 | as->op = rand() % _assignopmax /*_assign*/; 149 | as->expr = makeExpression(context, 0); 150 | 151 | statement->stmnt.assignmentstatement = as; 152 | } 153 | 154 | #define PTRASSIGNMENT_IS_CONSISTENT(lhs, rhs) (INTEGERTYPE_SIZE(ultimateType(lhs)) <= INTEGERTYPE_SIZE(ultimateType(rhs))) 155 | 156 | static void buildPtrAssignment(Statement *statement, Context *context, unsigned nesting) 157 | { 158 | Variable *v; 159 | PtrAssignmentStatement *pas = xmalloc(sizeof(*pas)); 160 | 161 | pas->lhs = selectVariable(context, _pointer); 162 | 163 | do 164 | v = selectVariable(context, _randomvartype); 165 | while(!PTRASSIGNMENT_IS_CONSISTENT(pas->lhs, v)); 166 | 167 | pas->rhs = v; 168 | 169 | statement->stmnt.ptrassignmentstatement = pas; 170 | } 171 | 172 | static void buildReturn(Statement *statement, Context *context, unsigned nesting) 173 | { 174 | ReturnStatement *rs = xmalloc(sizeof(*rs)); 175 | 176 | rs->retval = selectOperand(context); 177 | 178 | statement->stmnt.returnstatement = rs; 179 | } 180 | 181 | static void buildGoto(Statement *statement, Context *context, unsigned nesting) 182 | { 183 | GotoStatement *gs = xmalloc(sizeof(*gs)); 184 | 185 | gs->label = selectLabel(context); 186 | 187 | statement->stmnt.gotostatement = gs; 188 | } 189 | 190 | 191 | static void printIfStatement(Statement *statement) 192 | { 193 | IfStatement *ifstatement = statement->stmnt.ifstatement; 194 | 195 | fputs("if(", stdout); 196 | printExpression(ifstatement->condition); 197 | puts(")"); 198 | printBlock(ifstatement->truepath); 199 | 200 | if(ifstatement->falsepath) 201 | { 202 | puts("else"); 203 | printBlock(ifstatement->falsepath); 204 | } 205 | } 206 | 207 | static void printForStatement(Statement *statement) 208 | { 209 | ForStatement *forstatement = statement->stmnt.forstatement; 210 | char *id = USABLE_ID(forstatement->iterator); 211 | 212 | printf("for(%s = %d; %s %s %d; %s %s %d)\n", id, forstatement->init, 213 | id, testop2str[forstatement->testop], forstatement->testval, 214 | id, assignop2str[forstatement->assignop], forstatement->incval); 215 | 216 | printBlock(forstatement->body); 217 | } 218 | 219 | static void printAssignmentStatement(Statement *statement) 220 | { 221 | AssignmentStatement *assignstatement = statement->stmnt.assignmentstatement; 222 | 223 | printf("%s %s ", USABLE_ID(assignstatement->var), assignop2str[assignstatement->op]); 224 | printExpression(assignstatement->expr); 225 | puts(";"); 226 | } 227 | 228 | static void printPtrAssignmentStatement(Statement *statement) 229 | { 230 | PtrAssignmentStatement *pas = statement->stmnt.ptrassignmentstatement; 231 | size_t lhsdepth = pointerDepth(pas->lhs), rhsdepth = pointerDepth(pas->rhs); 232 | 233 | if(pas->rhs->type == _pointer) 234 | { 235 | if(lhsdepth == rhsdepth) 236 | printf("%s = %s;\n", pas->lhs->name, pas->rhs->name); 237 | else if(lhsdepth < rhsdepth) 238 | printf("%s = %s%s;\n", pas->lhs->name, genStars(rhsdepth - lhsdepth), pas->rhs->name); 239 | else 240 | printf("%s%s = %s;\n", genStars(lhsdepth - rhsdepth), pas->lhs->name, pas->rhs->name); 241 | } 242 | 243 | else 244 | { 245 | printf("%s%s = &%s;\n", genStars(lhsdepth - rhsdepth - 1), pas->lhs->name, pas->rhs->name); 246 | } 247 | } 248 | 249 | static void printFunctionCallStatement(Statement *statement) 250 | { 251 | ExpressionList *e; 252 | FunctionCallStatement *funccallstatement = statement->stmnt.funccallstatement; 253 | 254 | printf("\n%s(", funccallstatement->function->name); 255 | 256 | foreach(e, funccallstatement->paramlist) 257 | { 258 | printExpression(e->expression); 259 | 260 | if(e->next) 261 | fputs(", ", stdout); 262 | } 263 | 264 | puts(");"); 265 | } 266 | 267 | static void printReturnStatement(Statement *statement) 268 | { 269 | Operand *retval = statement->stmnt.returnstatement->retval; 270 | 271 | printf("return %s;\n", retval->type == _variable ? USABLE_ID(retval->op.variable) : retval->op.constant->value); 272 | } 273 | 274 | static void printGotoStatement(Statement *statement) 275 | { 276 | printf("goto %s;\n", statement->stmnt.gotostatement->label->name); 277 | } 278 | 279 | void printStatement(Statement *statement) 280 | { 281 | static void (*printfunctions[_statementtypemax])(Statement*) = 282 | { 283 | [_if] = printIfStatement, 284 | [_for] = printForStatement, 285 | [_return] = printReturnStatement, 286 | [_assignment] = printAssignmentStatement, 287 | [_ptrassignment] = printPtrAssignmentStatement, 288 | [_functioncall] = printFunctionCallStatement, 289 | [_goto] = printGotoStatement 290 | }; 291 | 292 | if(statement->label) 293 | printf("%s:\n", statement->label->name); 294 | 295 | (printfunctions[statement->type])(statement); 296 | } 297 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2012, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #define P_WRITEABLE (1 << 0) 25 | 26 | typedef int bool; 27 | 28 | #define true 1 29 | #define false 0 30 | 31 | typedef enum {_i8, _u8, _i16, _u16, _i32, _u32, _i64, _u64, _inttypemax} IntegerType; 32 | typedef enum {_if, _for, _functioncall, _return, _assignment, _ptrassignment, _goto, _statementtypemax} StatementType; 33 | typedef enum {_variable, _constant, _operandtypemax, _none = 42} OperandType; 34 | typedef enum {_equal, _lowerorequal, _greaterorequal, _lower, greater, _different, _testopmax} TestOp; 35 | typedef enum {_plus, _minus, _div, _mod, _mul, _arithopmax} ArithOp; 36 | typedef enum {_bwand, _bwor, _xor, _left, _right, _bitwiseopmax} BitwiseOp; 37 | typedef enum {_logand, _logor, _logicalopmax} LogicalOp; 38 | typedef enum {_arithmetic, _bitwise, _logical, _operationtypemax} OperationType; 39 | typedef enum {_operandexpr, _ternaryexpr, _operationexpr, _testexpr, _assignmentexpr, _functioncallexpr, _expressiontypemax} ExpressionType; 40 | typedef enum {_assigninc, _assigndec_, _assigndiv, _assignmod, _assignmul, _assignand, _assignor, _assignxor, _assign, _leftshiftassign, _rightshiftassign, _assignopmax} AssignmentOp; 41 | 42 | typedef enum {_integer, _pointer, _vartypemax, _randomvartype = 42} VariableType; 43 | 44 | typedef uint8_t Permissions; 45 | 46 | /* #pragma pack(4) */ 47 | 48 | typedef struct 49 | { 50 | char *value; 51 | unsigned bitness; 52 | } Constant; 53 | 54 | typedef struct Variable 55 | { 56 | char *name; 57 | 58 | union 59 | { 60 | struct IntegerVariable 61 | { 62 | Constant *initializer; 63 | IntegerType type; 64 | } intvar; 65 | 66 | struct Pointer 67 | { 68 | struct Variable *pointed; 69 | } pointer; 70 | }; 71 | 72 | VariableType type; 73 | } Variable; 74 | 75 | typedef struct VL 76 | { 77 | Variable *variable; 78 | struct VL *next; 79 | } VariableList; 80 | 81 | typedef struct 82 | { 83 | OperandType type; 84 | 85 | union 86 | { 87 | Variable *variable; 88 | Constant *constant; 89 | } op; 90 | } Operand; 91 | 92 | typedef struct 93 | { 94 | void *condition; /* Expression *condition */ 95 | 96 | struct BLCK 97 | { 98 | VariableList *localvars; 99 | 100 | struct SL 101 | { 102 | struct Stmnt *statement; 103 | struct SL *next; 104 | } *statementlist; 105 | } *truepath, *falsepath; 106 | } IfStatement; 107 | 108 | typedef struct SL StatementList; 109 | typedef struct BLCK Block; 110 | 111 | typedef struct 112 | { 113 | void *condition; 114 | Block *body; 115 | } WhileStatement; 116 | 117 | typedef struct 118 | { 119 | Variable *iterator; 120 | int init, testval, incval; 121 | TestOp testop; 122 | AssignmentOp assignop; 123 | Block *body; 124 | } ForStatement; 125 | 126 | typedef struct 127 | { 128 | Variable *var; 129 | void *expr; 130 | AssignmentOp op; 131 | } AssignmentStatement; 132 | 133 | typedef struct 134 | { 135 | Variable *lhs, *rhs; 136 | } PtrAssignmentStatement; 137 | 138 | typedef struct 139 | { 140 | Operand *retval; 141 | } ReturnStatement; 142 | 143 | typedef struct 144 | { 145 | char *name; 146 | } Label; 147 | 148 | typedef struct LL 149 | { 150 | Label *label; 151 | struct LL *next; 152 | } LabelList; 153 | 154 | typedef struct 155 | { 156 | char *name; 157 | IntegerType returntype; 158 | VariableList *paramlist; 159 | Block *body; 160 | LabelList *labels; 161 | short numlabels; 162 | bool isStatic; 163 | } Function; 164 | 165 | typedef struct 166 | { 167 | Function *function; 168 | void *paramlist; /* ExpressionList *paramlist; */ 169 | } FunctionCallStatement; 170 | 171 | typedef struct 172 | { 173 | Label *label; 174 | } GotoStatement; 175 | 176 | typedef struct Stmnt 177 | { 178 | StatementType type; 179 | Label *label; 180 | 181 | union 182 | { 183 | IfStatement *ifstatement; 184 | WhileStatement *whilestatement; 185 | ForStatement *forstatement; 186 | FunctionCallStatement *funccallstatement; 187 | AssignmentStatement *assignmentstatement; 188 | PtrAssignmentStatement *ptrassignmentstatement; 189 | ReturnStatement *returnstatement; 190 | GotoStatement *gotostatement; 191 | } stmnt; 192 | } Statement; 193 | 194 | typedef struct FL 195 | { 196 | Function *function; 197 | struct FL *next; 198 | } FunctionList; 199 | 200 | typedef struct Expr 201 | { 202 | ExpressionType type; 203 | 204 | union 205 | { 206 | struct TestExpression 207 | { 208 | struct Expr *lefthand, *righthand; 209 | TestOp op; 210 | } *testexpr; 211 | 212 | struct TernaryExpression 213 | { 214 | struct Expr *test; 215 | struct Expr *truepath, *falsepath; 216 | } *ternexpr; 217 | 218 | struct OperationExpression 219 | { 220 | struct Expr *lefthand, *righthand; 221 | OperationType type; 222 | 223 | union 224 | { 225 | ArithOp arithop; 226 | BitwiseOp bitwiseop; 227 | LogicalOp logicalop; 228 | } operator; 229 | } *opexpr; 230 | 231 | struct AssignmentExpression 232 | { 233 | Variable *lvalue; 234 | struct Expr *rvalue; 235 | AssignmentOp op; 236 | } *assignexpr; 237 | 238 | struct FunctionCallExpression 239 | { 240 | Function *function; 241 | void *paramlist; /* struct ExpressionList *paramlist */ 242 | } *funccallexpr; 243 | 244 | Operand *operand; 245 | } expr; 246 | } Expression; 247 | 248 | typedef struct EL 249 | { 250 | Expression *expression; 251 | struct EL *next; 252 | } ExpressionList; 253 | 254 | typedef struct Context 255 | { 256 | unsigned short nvars, nintegers; 257 | VariableList *scope; 258 | Function *currfunc; 259 | } Context; 260 | 261 | typedef struct 262 | { 263 | VariableList *globalvars; 264 | FunctionList *functions; 265 | size_t numfunctions, numglobalvars; 266 | } Program; 267 | 268 | typedef struct 269 | { 270 | unsigned seed, max_functions, max_localvars, max_function_parameters, min_statements_per_block, max_statements_per_block, 271 | max_expression_nesting, max_block_nesting, max_pointer_depth; 272 | bool nojumps; 273 | bool no_omitted_operand_conditional; 274 | } CommandlineOpt; 275 | -------------------------------------------------------------------------------- /utils.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | #ifdef DEBUG_MEMORY 27 | unsigned long long int allocated_bytes = 0; 28 | #endif 29 | 30 | void die(const char *format, ...) 31 | { 32 | va_list vargs; 33 | 34 | va_start(vargs, format); 35 | fprintf(stderr, "ccg: "); 36 | vfprintf(stderr, format, vargs); 37 | fprintf(stderr, "\n"); 38 | exit(EXIT_FAILURE); 39 | } 40 | 41 | void *xmalloc(size_t size) 42 | { 43 | void *ptr = malloc(size); 44 | 45 | #ifdef DEBUG_MEMORY 46 | allocated_bytes += size; 47 | #endif 48 | 49 | if(!ptr) 50 | die("cannot allocate memory !"); 51 | 52 | return ptr; 53 | } 54 | 55 | void *xcalloc(size_t nmemb, size_t size) 56 | { 57 | void *ptr = calloc(nmemb, size); 58 | 59 | #ifdef DEBUG_MEMORY 60 | allocated_bytes += nmemb * size; 61 | #endif 62 | 63 | if(!ptr) 64 | die("cannot allocate memory !"); 65 | 66 | return ptr; 67 | } 68 | 69 | /* Generate n stars */ 70 | char *genStars(size_t n) 71 | { 72 | static char stars[16]; 73 | 74 | memset(stars, '*', n); 75 | stars[n] = 0; 76 | 77 | return stars; 78 | } 79 | -------------------------------------------------------------------------------- /variable.c: -------------------------------------------------------------------------------- 1 | /* C Code Generator 2 | * 3 | * Copyright (C) 2016, Antoine Balestrat 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom 10 | * the Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "ccg.h" 25 | 26 | void addVariableToList(Variable *variable, VariableList **list) 27 | { 28 | if(!*list) 29 | { 30 | *list = xmalloc(sizeof(**list)); 31 | (*list)->variable = variable; 32 | (*list)->next = NULL; 33 | } 34 | 35 | else 36 | { 37 | VariableList *v; 38 | 39 | for(v = *list; v->next; v = v->next); 40 | v->next = xmalloc(sizeof(*v->next)); 41 | v->next->variable = variable; 42 | v->next->next = NULL; 43 | } 44 | } 45 | 46 | void freeVariableList(VariableList *list) 47 | { 48 | VariableList *v, *next; 49 | 50 | for(v = list; v; v = next) 51 | { 52 | next = v->next; 53 | free(v); 54 | } 55 | } 56 | 57 | Variable *makeVariable(Context *context, VariableType type) 58 | { 59 | Variable *ret = xmalloc(sizeof(Variable)); 60 | 61 | if(type != _randomvartype) 62 | { 63 | ret->type = type; 64 | 65 | if(type == _integer) 66 | makeInteger(ret, context); 67 | else 68 | makePointer(ret, context); 69 | } 70 | 71 | else 72 | { 73 | if((ret->type = rand() % _vartypemax) == _integer) 74 | makeInteger(ret, context); 75 | else if(ret->type == _pointer) 76 | makePointer(ret, context); 77 | } 78 | 79 | return ret; 80 | } 81 | 82 | void printVariableDecl(Variable *var) 83 | { 84 | if(var->type == _integer) 85 | printIntegerDecl(var); 86 | else 87 | printPointerDecl(var); 88 | } 89 | 90 | void printVariableType(Variable *var) 91 | { 92 | printf("%s", inttype2str[ultimateType(var)]); 93 | 94 | if(var->type == _pointer) 95 | { 96 | size_t n = pointerDepth(var); 97 | 98 | for(size_t i = 0; i < n; ++i) 99 | putchar('*'); 100 | } 101 | } 102 | 103 | void copyVariableList(VariableList *src, VariableList **dest) 104 | { 105 | VariableList *v; 106 | 107 | foreach(v, src) 108 | addVariableToList(v->variable, dest); 109 | } 110 | 111 | Variable *selectVariable(Context *context, VariableType type) 112 | { 113 | VariableList *v; 114 | size_t n, t = 0; 115 | 116 | if(type == _randomvartype) 117 | n = rand() % context->nvars; 118 | else 119 | n = rand() % (type == _integer ? context->nintegers : (context->nvars - context->nintegers)); 120 | 121 | foreach(v, context->scope) 122 | { 123 | if(v->variable->type == type || type == _randomvartype) 124 | if(t++ == n) 125 | return v->variable; 126 | } 127 | 128 | die("unreachable"); 129 | return NULL; 130 | } 131 | 132 | void makeGlobalVariables(void) 133 | { 134 | size_t i; 135 | Context *c = xmalloc(sizeof(*c)); 136 | 137 | c->scope = program.globalvars; 138 | c->nvars = 0; 139 | 140 | program.numglobalvars = rand() % 11 + 1; 141 | 142 | for(i = 0; i < program.numglobalvars; ++i) 143 | { 144 | addVariableToList(makeVariable(c, _integer), &program.globalvars); 145 | c->nvars++; 146 | } 147 | 148 | free(c); 149 | } 150 | --------------------------------------------------------------------------------