├── .build.yml ├── .gitignore ├── CMakeLists.txt ├── ChangeLog ├── LICENSE ├── README.md ├── kcc.1.scdoc └── src ├── KCCCleanup.cc ├── KCCCleanup.h ├── SDCC.lex ├── SDCC.y ├── SDCCBBlock.c ├── SDCCBBlock.h ├── SDCCargs.h ├── SDCCasm.c ├── SDCCasm.h ├── SDCCast.c ├── SDCCast.h ├── SDCCbitv.c ├── SDCCbitv.h ├── SDCCbtree.cc ├── SDCCbtree.h ├── SDCCcflow.c ├── SDCCcflow.h ├── SDCCcse.c ├── SDCCcse.h ├── SDCCdflow.c ├── SDCCdflow.h ├── SDCCerr.c ├── SDCCerr.h ├── SDCCgen.c ├── SDCCgen.h ├── SDCCglobl.h ├── SDCCglue.c ├── SDCCglue.h ├── SDCChasht.c ├── SDCChasht.h ├── SDCCicode.c ├── SDCCicode.h ├── SDCClabel.c ├── SDCClabel.h ├── SDCCloop.c ├── SDCCloop.h ├── SDCClospre.cc ├── SDCClospre.hpp ├── SDCClrange.c ├── SDCClrange.h ├── SDCCmacro.c ├── SDCCmacro.h ├── SDCCmain.c ├── SDCCmem.c ├── SDCCmem.h ├── SDCCnaddr.cc ├── SDCCnaddr.hpp ├── SDCCopt.c ├── SDCCopt.h ├── SDCCpeeph.awk ├── SDCCpeeph.c ├── SDCCpeeph.h ├── SDCCptropt.c ├── SDCCptropt.h ├── SDCCralloc.hpp ├── SDCCset.c ├── SDCCset.h ├── SDCCsymt.c ├── SDCCsymt.h ├── SDCCsystem.c ├── SDCCsystem.h ├── SDCCtree_dec.hpp ├── SDCCutil.c ├── SDCCutil.h ├── SDCCval.c ├── SDCCval.h ├── backend ├── gen.c ├── gen.h ├── main.c ├── mappings.i ├── peep.c ├── peep.h ├── peeph-z80.def ├── peeph.def ├── ralloc.c ├── ralloc.h ├── ralloc2.cc ├── support.c ├── support.h └── z80.h ├── common.h ├── port.h ├── sdccconf.h ├── util ├── NewAlloc.c ├── dbuf.c ├── dbuf.h ├── dbuf_string.c ├── dbuf_string.h ├── newalloc.h ├── pstdint.h └── system.h └── version.h /.build.yml: -------------------------------------------------------------------------------- 1 | image: archlinux 2 | packages: 3 | - flex 4 | - bison 5 | - boost 6 | - cmake 7 | sources: 8 | - https://github.com/KnightOS/kcc 9 | environment: 10 | project: kcc 11 | tasks: 12 | - build: | 13 | cd ${project} 14 | cmake . 15 | make 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | CMakeCache.txt 3 | CMakeFiles 4 | Makefile 5 | cmake_install.cmake 6 | install_manifest.txt 7 | *.swp 8 | *.o 9 | *.1 10 | *.rul 11 | sdcc/gen/ 12 | build/ 13 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.5) 2 | 3 | project(kcc C CXX) 4 | 5 | set(CMAKE_CXX_FLAGS_DEBUG "-g") 6 | set(CMAKE_C_FLAGS_DEBUG "-g") 7 | 8 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -std=c99 -D_POSIX_C_SOURCE=200809") 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -std=c++11") 10 | 11 | if (NOT DEFINED KCC_DEFAULT_PREPROCESSOR) 12 | set(KCC_DEFAULT_PREPROCESSOR "cpp" CACHE PATH "The preprocessor KCC should use if none is explicitly specified") 13 | endif() 14 | 15 | if (NOT DEFINED KCC_DOCUMENTATION) 16 | set(KCC_DOCUMENTATION FALSE CACHE BOOL "Whether to build documentation") 17 | endif() 18 | 19 | add_definitions("-DKCC_DEFAULT_PREPROCESSOR=\"${KCC_DEFAULT_PREPROCESSOR}\"") 20 | 21 | find_package(BISON REQUIRED) 22 | find_package(FLEX REQUIRED) 23 | find_package(Boost REQUIRED) 24 | 25 | if (KCC_DOCUMENTATION) 26 | find_program(SCDOC NAMES scdoc REQUIRED) 27 | endif() 28 | 29 | if (NOT DEFINED CMAKE_BUILD_TYPE) 30 | set(CMAKE_BUILD_TYPE Release CACHE STRING "") 31 | endif() 32 | 33 | include_directories( 34 | ${PROJECT_SOURCE_DIR}/src/ 35 | ${PROJECT_SOURCE_DIR}/src/util/ 36 | ${PROJECT_BINARY_DIR}/gen/ 37 | ) 38 | 39 | BISON_TARGET(SDCCy ${PROJECT_SOURCE_DIR}/src/SDCC.y ${PROJECT_BINARY_DIR}/gen/SDCCy.c) 40 | FLEX_TARGET(SDCClex ${PROJECT_SOURCE_DIR}/src/SDCC.lex ${PROJECT_BINARY_DIR}/gen/SDCClex.c) 41 | 42 | FILE(GLOB SOURCES 43 | ${PROJECT_SOURCE_DIR}/src/*.c ${PROJECT_SOURCE_DIR}/src/*.cc 44 | ${PROJECT_SOURCE_DIR}/src/backend/*.c ${PROJECT_SOURCE_DIR}/src/backend/*.cc 45 | ${PROJECT_SOURCE_DIR}/src/util/*.c 46 | ${PROJECT_SOURCE_DIR}/src/backend/*.rul 47 | ) 48 | FILE(GLOB peep_defs ${PROJECT_SOURCE_DIR}/src/backend/*.def) 49 | file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/gen) 50 | 51 | foreach(peep ${peep_defs}) 52 | execute_process(COMMAND sh -c "basename '${peep}' .def | tr -d '\\n'" 53 | OUTPUT_VARIABLE rules 54 | ) 55 | set(rules ${PROJECT_SOURCE_DIR}/src/backend/${rules}.rul) 56 | add_custom_command(OUTPUT ${rules} 57 | COMMAND awk -f ${PROJECT_SOURCE_DIR}/src/SDCCpeeph.awk ${peep} > ${rules} 58 | DEPENDS ${peep_defs} 59 | ) 60 | list(APPEND peep_rules ${rules}) 61 | endforeach() 62 | 63 | add_executable(kcc 64 | ${BISON_SDCCy_OUTPUTS} 65 | ${FLEX_SDCClex_OUTPUTS} 66 | ${SOURCES} 67 | ${peep_rules} 68 | ) 69 | 70 | if (KCC_DOCUMENTATION) 71 | add_custom_target(man ALL DEPENDS ${PROJECT_BINARY_DIR}/kcc.1) 72 | add_custom_command( 73 | DEPENDS ${PROJECT_SOURCE_DIR}/kcc.1.scdoc 74 | COMMAND ${SCDOC} <${PROJECT_SOURCE_DIR}/kcc.1.scdoc >${PROJECT_BINARY_DIR}/kcc.1 75 | OUTPUT ${PROJECT_BINARY_DIR}/kcc.1 76 | ) 77 | install(FILES ${PROJECT_BINARY_DIR}/kcc.1 DESTINATION share/man/man1) 78 | endif() 79 | 80 | target_link_libraries(kcc m ${BOOST_LIBRARIES} ${LIBS}) 81 | 82 | install(TARGETS kcc DESTINATION bin) 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KnightOS C Compiler 2 | 3 | The KnightOS C Compiler (kcc) is a fork of [sdcc](http://sdcc.sourceforge.net/). It's a work in progress. 4 | 5 | ## Compiling 6 | 7 | kcc depends on flex/bison and boost. 8 | 9 | cmake . 10 | make 11 | make install # as root 12 | 13 | ## Differences from SDCC 14 | 15 | * KnightOS support 16 | * kcc includes man pages 17 | * Switched from autotools to cmake 18 | * Dropped all targets but z80 19 | * Removed unneccessary subsystems (like simulators) 20 | * General clean up and refactor 21 | 22 | ## Why a fork? 23 | 24 | We presented our needs upstream and they were not interested in them. 25 | 26 | ## Help, Bugs, Feedback 27 | 28 | If you need help with KnightOS, want to keep up with progress, chat with 29 | developers, or ask any other questions about KnightOS, you can hang out in the 30 | IRC channel: [#knightos on irc.freenode.net](http://webchat.freenode.net/?channels=knightos). 31 | 32 | To report bugs, please create [a GitHub issue](https://github.com/KnightOS/KnightOS/issues/new) or contact us on IRC. 33 | 34 | If you'd like to contribute to the project, please see the [contribution guidelines](http://www.knightos.org/contributing). 35 | -------------------------------------------------------------------------------- /kcc.1.scdoc: -------------------------------------------------------------------------------- 1 | kcc(1) 2 | 3 | # NAME 4 | 5 | kcc - the KnightOS C Compiler 6 | 7 | # SYNOPSIS 8 | 9 | kcc [*-c*|*-S*|*-E*] [*--std*=_standard_]++ 10 | [*-g*] [*--Werror*] [*-Wa* _scas_option_...]++ 11 | [*-I* _dir_...]++ 12 | [*-o* _outfile_...] infile 13 | 14 | For an exhaustive list of options, see the *OPTIONS* section. 15 | 16 | # DESCRIPTION 17 | 18 | KCC is the official KnightOS C compiler. It uses the scas assembler to build 19 | produced assembly; see *scas*(1) for usage details. KCC relies on the system's 20 | preprocessor - on most Linux systems, this is */usr/bin/cpp*. See *cpp*(1) for 21 | preprocessor options, or the man page for the relevant preprocessor if it's not 22 | GNU's *cpp*. 23 | 24 | # MODE 25 | 26 | A typical KCC invocation performs preprocessing, compilation, assembly, and 27 | linking. Preprocessing is shelled out to the configured preprocessor. The 28 | preprocessor to be used can be overridden with *--cpp* _path_. The preprocessed 29 | source is compiled by KCC into z80 assembly, with the format documented by scas. 30 | KCC then shells out to scas for assembly and linking. 31 | 32 | To preprocess only, use the *-E* flag. To only compile into asm, use *-S*. To 33 | compile and assemble only, and not link, use *-c*. With *-E*, output goes to 34 | stdout by default; in all other modes, the default is to write to a file with 35 | the same base name as the input but the correct extension. For instance, when 36 | compiling a file *example.c* with the *-c* flag, *example.o* will be used as the 37 | destination for the object file. 38 | 39 | # C STANDARD 40 | 41 | The *--std*=_standard_ option allows for selecting the C standard to use. The 42 | recommend standard is C99. KCC's support for C99 is not complete, but it's very 43 | usable, and it provides some key features missing from C89. We support the 44 | official C89, C99, and C11 standards. Use *cNN* for the _standard_ given, where 45 | *NN* is the number desired. For instance, to use C11, specify *--std=c11*. We 46 | also support the SDCC extensions, though it is *highly* recommends that you do 47 | *not* use those unless you have to. If you do choose to use SDCC extensions, 48 | simply replace *c* with *sdcc* in the compiler flag. For instance, 49 | *--std=sdcc99* selects the C99 standard with SDCC extensions. Standards given to 50 | *--std* must be given in lower case. 51 | 52 | # LINKING 53 | 54 | Dynamic linking is not yet officially supported with KCC; you're on your own for 55 | the time being. Static linking, however, is very well supported. 56 | 57 | Unlike other platforms, KnightOS doesn't currently have an "archive" format 58 | defined. Instead, a static library is simply another object file. Using scas 59 | directly, you can simply run: 60 | 61 | scas -c obj1.o obj2.o -o name 62 | 63 | Static libraries in knightos don't have a *lib* prefix, and have no extension, 64 | just like binaries. The only difference is that binaries are placed in */bin* 65 | and libraries in */lib*. 66 | 67 | Creating static libraries with kcc is currently not supported. It is a target 68 | for KCC 4.1. 69 | 70 | Linking should also be done with scas, presently; we're still working on tighter 71 | integration between KCC's CLI and scas. To link with scas, simply pass it the 72 | list of object files and the *-o* flag with the desired output file. For 73 | instance, to link a library *example* in a relative folder *../../example/lib/* 74 | with *source1.o* and *source2.o* into a binary *test*, run the following: 75 | 76 | scas source1.o source2.o ../../example/lib/example -o test 77 | 78 | # OTHER OPTIONS 79 | 80 | To generate debugging information, add *-g* to the KCC command line. This 81 | currently only provides mappings from the C source to the assembly given to scas 82 | (and thus to the final binary). This currently only integrates with z80e, 83 | allowing the debugger to print and breakpoint based on the C source. In the 84 | future, this will also result in DWARF generation. 85 | 86 | To pass arbitrary options through to scas, use the *-Wa* flag (for assembling) 87 | or the *-Wl* flag (for linking). For applicable options, see *scas*(1). 88 | 89 | To add to the list of search paths for includes, use *-I* _path_. 90 | 91 | To change the file used as the output, use *-o* _path_. 92 | 93 | To abort compilation on all warnings, use *--Werror*. 94 | 95 | To pass options through to the preprocessor, use *-Wp*. 96 | 97 | # SEE ALSO 98 | 99 | scas(1), cpp(1) 100 | 101 | # AUTHORS 102 | 103 | Maintained by the KnightOS Group. Up-to-date sources can be found at 104 | https://github.com/KnightOS/KCC and bugs/patches can be submitted by email to 105 | ~pixelherodev/knightos@lists.sr.ht or manually to 106 | https://github.com/KnightOS/KnightOS/issues/. 107 | 108 | -------------------------------------------------------------------------------- /src/KCCCleanup.cc: -------------------------------------------------------------------------------- 1 | #include "KCCCleanup.h" 2 | 3 | #include "SDCCglobl.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | extern struct options options; 12 | 13 | std::vector allowed_commands = { 14 | ".equ", ".globl", ".area", ".org", ".map", ".db", ".ds", 15 | ".dw", ".ascii", ".asciip", ".asciiz", ".if", ".ifdef", ".ifndef", 16 | ".elif", ".elseif", ".end", ".module", ".optsdcc", ".function"}; 17 | 18 | std::string trim(const std::string &str, 19 | const std::string &whitespace = " \t") { 20 | const auto strBegin = str.find_first_not_of(whitespace); 21 | if (strBegin == std::string::npos) 22 | return ""; // no content 23 | 24 | const auto strEnd = str.find_last_not_of(whitespace); 25 | const auto strRange = strEnd - strBegin + 1; 26 | 27 | return str.substr(strBegin, strRange); 28 | } 29 | 30 | std::string reduce(const std::string &str, const std::string &fill = " ", 31 | const std::string &whitespace = " \t") { 32 | // trim first 33 | auto result = trim(str, whitespace); 34 | 35 | // replace sub ranges 36 | auto beginSpace = result.find_first_of(whitespace); 37 | while (beginSpace != std::string::npos) { 38 | const auto endSpace = result.find_first_not_of(whitespace, beginSpace); 39 | const auto range = endSpace - beginSpace; 40 | 41 | result.replace(beginSpace, range, fill); 42 | 43 | const auto newStart = beginSpace + fill.length(); 44 | beginSpace = result.find_first_of(whitespace, newStart); 45 | } 46 | 47 | return result; 48 | } 49 | 50 | void cleanupFile(const char *file) { 51 | std::ifstream asm_file(file); 52 | if (!asm_file) { 53 | printf("Error: file \"%s\" doesn't exist!\n", file); 54 | return; 55 | } 56 | std::vector buffer; 57 | std::string line, o_line; 58 | bool dirty = false; 59 | // Keep the first five lines 60 | for (int i = 0; i < 4; i++) { 61 | std::getline(asm_file, o_line); 62 | buffer.push_back(o_line); 63 | } 64 | // Process the rest of them, discarding unneeded pieces 65 | for (int line_number = 0; std::getline(asm_file, o_line); line_number++) { 66 | line = reduce(o_line); 67 | size_t space = line.find(' '); 68 | bool keep = false; 69 | if (space != std::string::npos) 70 | line = line.substr(0, space); 71 | if (line[0] != ';') { 72 | if ((line[0] != '.' || line[line.length() - 1] == ':' || 73 | std::find(allowed_commands.begin(), allowed_commands.end(), line) != 74 | allowed_commands.end())) { 75 | if (buffer.size() != 0) { 76 | std::string last_line = buffer.back(); 77 | if (last_line.length() > 6 && last_line.substr(0, 6) == "\t.area" && 78 | o_line.length() > 6 && o_line.substr(0, 6) == "\t.area") { 79 | buffer.pop_back(); 80 | } 81 | } 82 | keep = true; 83 | } else if (options.verbose) { 84 | fprintf(stderr, "Discarded: %s\n", o_line.c_str()); 85 | } 86 | } 87 | if (keep) { 88 | buffer.push_back(o_line); 89 | } else { 90 | //~ printf("Dropping line: %s\n", o_line.c_str()); 91 | dirty = true; 92 | } 93 | } 94 | asm_file.close(); 95 | if (dirty) { 96 | std::ofstream output(file); 97 | if (!output) { 98 | printf("Error opening file for output!\n"); 99 | return; 100 | } else { 101 | for (std::string s : buffer) { 102 | output << s << std::endl; 103 | } 104 | output.close(); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/KCCCleanup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" 5 | #endif 6 | void 7 | cleanupFile(const char *file); 8 | -------------------------------------------------------------------------------- /src/SDCCBBlock.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCBBlock.h - header file for Basic Blocks 4 | 5 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | In other words, you are welcome to use, share and improve this program. 22 | You are forbidden to forbid anyone else to use, share and improve 23 | what you give them. Help stamp out software-hoarding! 24 | -------------------------------------------------------------------------*/ 25 | 26 | #ifndef SDCCBBLOCK_H 27 | #define SDCCBBLOCK_H 1 28 | 29 | #include "SDCCicode.h" 30 | #include "SDCCsymt.h" 31 | 32 | /* definition of a basic block */ 33 | typedef struct eBBlock { 34 | int dfnum; /* depth first number */ 35 | int bbnum; /* index into array of numbers */ 36 | int depth; /* loop depth of this block */ 37 | int fSeq; /* sequence number of first iCode */ 38 | int lSeq; /* sequence number of the last iCode */ 39 | unsigned int visited : 1; /* visitied flag */ 40 | unsigned int hasFcall : 1; /* has a function call */ 41 | unsigned int noPath : 1; /* there is no path from _entry to this block */ 42 | unsigned int isLastInLoop : 1; /* is the last block in a loop */ 43 | struct eBBlock *isConditionalExitFrom; /* this block ends with a return or 44 | goto from a conditional block */ 45 | symbol *entryLabel; /* entry label */ 46 | 47 | iCode *sch; /* pointer to start of code chain */ 48 | iCode *ech; /* pointer to last of code chain */ 49 | 50 | struct eBBlock *preHeader; /* preheader if this is a loop entry */ 51 | struct region 52 | *partOfLoop; /* pointer to the loop region this block is part of */ 53 | 54 | /* control flow analysis */ 55 | set *succList; /* list eBBlocks which are successors */ 56 | bitVect *succVect; /* bitVector of successors (index is bbnum) */ 57 | set *predList; /* predecessors of this basic block */ 58 | bitVect *domVect; /* list of nodes this is dominated by (index is bbnum) */ 59 | 60 | /* data flow analysis */ 61 | set *inExprs; /* in coming common expressions */ 62 | set *outExprs; /* out going common expressions */ 63 | set *killedExprs; /* killed common expressions */ 64 | bitVect *inDefs; /* in coming defintions */ 65 | bitVect *outDefs; /* out going defintions */ 66 | bitVect *defSet; /* symbols defined in block */ 67 | bitVect *ldefs; /* local definitions only */ 68 | bitVect *usesDefs; /* which definitions are used in this block */ 69 | bitVect *ptrsSet; /* pointers assigned values in the block */ 70 | bitVect *inPtrsSet; /* in coming pointers assigned values */ 71 | bitVect *ndompset; /* pointers set by non-dominating basic blocks */ 72 | set *addrOf; /* symbols for which addres has been taken in the block */ 73 | bitVect *linds; /* if loop exit this contains defNumbers 74 | for the inductions */ 75 | } eBBlock; 76 | 77 | typedef struct ebbIndex { 78 | int count; /* number of blocks in the index */ 79 | eBBlock **bbOrder; /* blocks in bbnum order */ 80 | eBBlock **dfOrder; /* blocks in dfnum (depth first) order */ 81 | } ebbIndex; 82 | 83 | typedef struct edge { 84 | 85 | eBBlock *from; /* from basic block */ 86 | eBBlock *to; /* to Basic Block */ 87 | } edge; 88 | 89 | extern int eBBNum; 90 | extern set *graphEdges; 91 | 92 | DEFSETFUNC(printEntryLabel); 93 | eBBlock *neweBBlock(); 94 | edge *newEdge(eBBlock *, eBBlock *); 95 | eBBlock *eBBWithEntryLabel(ebbIndex *, symbol *); 96 | DEFSETFUNC(ifFromIs); 97 | set *edgesTo(eBBlock *); 98 | void remiCodeFromeBBlock(eBBlock *, iCode *); 99 | void addiCodeToeBBlock(eBBlock *, iCode *, iCode *); 100 | ebbIndex *iCodeBreakDown(iCode *); 101 | void replaceSymBySym(set *, operand *, operand *); 102 | iCode *iCodeFromeBBlock(eBBlock **, int); 103 | int otherPathsPresent(eBBlock **, eBBlock *); 104 | void replaceLabel(eBBlock *, symbol *, symbol *); 105 | void dumpEbbsToFileExt(int, ebbIndex *); 106 | void dumpLiveRanges(int, hTab *liveRanges); 107 | void closeDumpFiles(); 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /src/SDCCargs.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCargs.c - command line arguments handling 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | /** Definition of the structures used by the options parser. The port 26 | may implement one of these for any options it wants parsed 27 | automatically. 28 | */ 29 | #ifndef SDCCARGS_H 30 | #define SDCCARGS_H 31 | 32 | /** Specifies option argument types. */ 33 | enum cl_opt_arg_type { 34 | CLAT_BOOLEAN = 0, /* has to be zero! */ 35 | CLAT_INTEGER, 36 | CLAT_STRING, 37 | CLAT_SET, 38 | CLAT_ADD_SET 39 | }; 40 | 41 | /** Table of all options supported by all ports. 42 | This table provides: 43 | * A reference for all options. 44 | * An easy way to maintain help for the options. 45 | * Automatic support for setting flags on simple options. 46 | */ 47 | typedef struct { 48 | /** The short option character e.g. 'h' for -h. 0 for none. */ 49 | char shortOpt; 50 | /** Long option e.g. "--help". Includes the -- prefix. NULL for 51 | none. */ 52 | const char *longOpt; 53 | /** Pointer to an int that will be incremented every time the 54 | option is encountered. May be NULL. 55 | */ 56 | void *pparameter; 57 | /** Help text to go with this option. May be NULL. */ 58 | const char *help; 59 | /** Option argument type */ 60 | enum cl_opt_arg_type arg_type; 61 | } OPTION; 62 | 63 | char *getStringArg(const char *szStart, char **argv, int *pi, int argc); 64 | int getIntArg(const char *szStart, char **argv, int *pi, int argc); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/SDCCasm.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCasm.h - header file for all types of stuff to support different 3 | assemblers. 4 | 5 | Copyright (C) 2000, Michael Hope 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | -------------------------------------------------------------------------*/ 21 | 22 | #ifndef SDCCASM_H 23 | #define SDCCASM_H 24 | 25 | #include "dbuf.h" 26 | 27 | void tfprintf(FILE *fp, const char *szFormat, ...); 28 | void dbuf_tprintf(struct dbuf_s *dbuf, const char *szFormat, ...); 29 | void dbuf_tvprintf(struct dbuf_s *dbuf, const char *szFormat, va_list ap); 30 | 31 | typedef struct { 32 | const char *szKey; 33 | const char *szValue; 34 | } ASM_MAPPING; 35 | 36 | typedef struct _ASM_MAPPINGS ASM_MAPPINGS; 37 | 38 | /* PENDING: could include the peephole rules here as well. 39 | */ 40 | struct _ASM_MAPPINGS { 41 | const ASM_MAPPINGS *pParent; 42 | const ASM_MAPPING *pMappings; 43 | }; 44 | 45 | /* The default asxxxx token mapping. 46 | */ 47 | extern const ASM_MAPPINGS asm_asxxxx_mapping; 48 | #if 0 49 | /* not used */ 50 | extern const ASM_MAPPINGS asm_gas_mapping; 51 | #endif 52 | extern const ASM_MAPPINGS asm_a390_mapping; 53 | #if !OPT_DISABLE_XA51 54 | extern const ASM_MAPPINGS asm_xa_asm_mapping; 55 | #endif 56 | 57 | /** Last entry has szKey = NULL. 58 | */ 59 | void asm_addTree(const ASM_MAPPINGS *pMappings); 60 | 61 | const char *FileBaseName(const char *fileFullName); 62 | 63 | const char *printILine(iCode *ic); 64 | const char *printCLine(const char *srcFile, int lineno); 65 | #endif 66 | -------------------------------------------------------------------------------- /src/SDCCast.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCast.h - header file for parser support & all ast related routines 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | #ifndef SDCCAST_H 26 | #define SDCCAST_H 27 | 28 | #include "SDCCglobl.h" 29 | #include "SDCCmem.h" 30 | #include "SDCCset.h" 31 | #include "SDCCsymt.h" 32 | #include "SDCCval.h" 33 | 34 | typedef enum { EX_OP = 0, EX_VALUE, EX_LINK, EX_OPERAND } ASTTYPE; 35 | 36 | /* expression tree */ 37 | typedef struct ast { 38 | ASTTYPE type; 39 | unsigned decorated : 1; 40 | unsigned isError : 1; 41 | unsigned funcName : 1; 42 | unsigned rvalue : 1; 43 | unsigned lvalue : 1; 44 | unsigned initMode : 1; 45 | unsigned reversed : 1; 46 | int level; /* level for expr */ 47 | int block; /* block number */ 48 | int seqPoint; /* sequence point */ 49 | /* union of values expression can have */ 50 | union { 51 | value *val; /* value if type = EX_VALUE */ 52 | sym_link *lnk; /* sym_link * if type= EX_LINK */ 53 | struct operand *oprnd; /* used only for side effecting function calls */ 54 | unsigned op; /* operator if type= EX_OP */ 55 | } opval; 56 | 57 | /* union for special processing */ 58 | union { 59 | const char *inlineasm; /* pointer to inline assembler code */ 60 | literalList *constlist; /* init list for array initializer. */ 61 | symbol *sym; /* if block then -> symbols */ 62 | value *args; /* if function then args */ 63 | /* if switch then switch values */ 64 | struct { 65 | value *swVals; /* switch comparison values */ 66 | int swDefault; /* default if present */ 67 | int swNum; /* switch number */ 68 | char *swSuffix; 69 | } switchVals; 70 | /* if for then for values */ 71 | struct { 72 | struct ast *initExpr; /* init portion */ 73 | struct ast *condExpr; /* conditional portion */ 74 | struct ast *loopExpr; /* iteration portion */ 75 | symbol *trueLabel; /* entry point into body */ 76 | symbol *falseLabel; /* exit point */ 77 | symbol *continueLabel; /* conditional check */ 78 | symbol *condLabel; /* conditional label */ 79 | } forVals; 80 | struct { 81 | unsigned literalFromCast : 1; /* true if this is an EX_VALUE of LITERAL 82 | * type resulting from a typecast. 83 | */ 84 | unsigned removedCast : 1; /* true if the explicit cast has been removed */ 85 | unsigned implicitCast : 1; /* true if compiler added this cast */ 86 | } cast; 87 | int argreg; /* argreg number when operand type == EX_OPERAND */ 88 | } values; 89 | 90 | int lineno; /* source file line number */ 91 | char *filename; /* filename of the source file */ 92 | 93 | sym_link *ftype; /* start of type chain for this subtree */ 94 | sym_link *etype; /* end of type chain for this subtree */ 95 | 96 | struct ast *left; /* pointer to left tree */ 97 | struct ast *right; /* pointer to right tree */ 98 | symbol *trueLabel; /* if statement trueLabel */ 99 | symbol *falseLabel; /* if statement falseLabel */ 100 | } ast; 101 | 102 | /* easy access macros */ 103 | #define IS_AST_OP(x) ((x) && (x)->type == EX_OP) 104 | #define IS_CALLOP(x) (IS_AST_OP(x) && (x)->opval.op == CALL) 105 | #define IS_BITOR(x) (IS_AST_OP(x) && (x)->opval.op == '|') 106 | #define IS_BITAND(x) \ 107 | (IS_AST_OP(x) && (x)->opval.op == '&' && (x)->left && (x)->right) 108 | #define IS_FOR_STMT(x) (IS_AST_OP(x) && (x)->opval.op == FOR) 109 | #define IS_LEFT_OP(x) (IS_AST_OP(x) && (x)->opval.op == LEFT_OP) 110 | #define IS_RIGHT_OP(x) (IS_AST_OP(x) && (x)->opval.op == RIGHT_OP) 111 | #define IS_AST_VALUE(x) ((x) && (x)->type == EX_VALUE && (x)->opval.val) 112 | #define IS_AST_LINK(x) ((x)->type == EX_LINK) 113 | #define IS_AST_NOT_OPER(x) (x && IS_AST_OP(x) && (x)->opval.op == '!') 114 | #define IS_ARRAY_OP(x) (IS_AST_OP(x) && (x)->opval.op == '[') 115 | #define IS_COMPARE_OP(x) \ 116 | (IS_AST_OP(x) && ((x)->opval.op == '>' || (x)->opval.op == '<' || \ 117 | (x)->opval.op == LE_OP || (x)->opval.op == GE_OP || \ 118 | (x)->opval.op == EQ_OP || (x)->opval.op == NE_OP)) 119 | #define IS_CAST_OP(x) (IS_AST_OP(x) && (x)->opval.op == CAST) 120 | #define IS_TERNARY_OP(x) (IS_AST_OP(x) && (x)->opval.op == '?') 121 | #define IS_COLON_OP(x) (IS_AST_OP(x) && (x)->opval.op == ':') 122 | #define IS_ADDRESS_OF_OP(x) \ 123 | (IS_AST_OP(x) && (x)->opval.op == '&' && (x)->right == NULL) 124 | #define IS_AST_LIT_VALUE(x) \ 125 | (IS_AST_VALUE(x) && IS_LITERAL((x)->opval.val->etype)) 126 | #define IS_AST_SYM_VALUE(x) (IS_AST_VALUE(x) && (x)->opval.val->sym) 127 | #define AST_FLOAT_VALUE(x) (floatFromVal((x)->opval.val)) 128 | #define AST_ULONG_VALUE(x) (ulFromVal((x)->opval.val)) 129 | #define AST_SYMBOL(x) ((x)->opval.val->sym) 130 | #define AST_VALUE(x) ((x)->opval.val) 131 | #define AST_VALUES(x, y) ((x)->values.y) 132 | #define AST_FOR(x, y) ((x)->values.forVals.y) 133 | #define AST_ARGREG(x) ((x)->values.argreg) 134 | 135 | #define IS_AST_PARAM(x) (IS_AST_OP(x) && (x)->opval.op == PARAM) 136 | 137 | #define CAN_EVAL(x) \ 138 | ((x) == '[' || (x) == '.' || (x) == PTR_OP || (x) == '&' || (x) == '|' || \ 139 | (x) == '^' || (x) == '*' || (x) == '-' || (x) == '+' || (x) == '~' || \ 140 | (x) == '!' || (x) == LEFT_OP || (x) == RIGHT_OP || (x) == '/' || \ 141 | (x) == '%' || (x) == '>' || (x) == '<' || (x) == LE_OP || (x) == GE_OP || \ 142 | (x) == EQ_OP || (x) == NE_OP || (x) == AND_OP || (x) == OR_OP || \ 143 | (x) == '=') 144 | 145 | #define LEFT_FIRST(x) (x == AND_OP || x == OR_OP) 146 | 147 | #define SIDE_EFFECTS_CHECK(op, rVal) \ 148 | if (!sideEffects) { \ 149 | werror(W_NO_SIDE_EFFECTS, op); \ 150 | return rVal; \ 151 | } 152 | #define IS_MODIFYING_OP(x) \ 153 | ((x) == INC_OP || (x) == DEC_OP || (x) == '=' || (x) == AND_ASSIGN || \ 154 | (x) == OR_ASSIGN || (x) == XOR_ASSIGN) 155 | 156 | #define IS_ASSIGN_OP(x) \ 157 | ((x) == '=' || (x) == ADD_ASSIGN || (x) == SUB_ASSIGN || \ 158 | (x) == MUL_ASSIGN || (x) == DIV_ASSIGN || (x) == XOR_ASSIGN || \ 159 | (x) == AND_ASSIGN || (x) == OR_ASSIGN || (x) == INC_OP || (x) == DEC_OP) 160 | #define IS_DEREF_OP(x) \ 161 | (((x)->opval.op == '*' && (x)->right == NULL) || (x)->opval.op == '.' || \ 162 | (x)->opval.op == PTR_OP) 163 | 164 | /* forward declarations for global variables */ 165 | extern ast *staticAutos; 166 | extern struct dbuf_s *codeOutBuf; 167 | extern struct memmap *GcurMemmap; 168 | 169 | /* forward definitions for functions */ 170 | ast *newAst_VALUE(value *val); 171 | ast *newAst_OP(unsigned op); 172 | ast *newAst_LINK(sym_link *val); 173 | 174 | void initAst(); 175 | ast *newNode(long, ast *, ast *); 176 | ast *copyAst(ast *); 177 | ast *removeIncDecOps(ast *); 178 | ast *removePreIncDecOps(ast *); 179 | ast *removePostIncDecOps(ast *); 180 | value *sizeofOp(sym_link *); 181 | value *alignofOp(sym_link *); 182 | ast *offsetofOp(sym_link *type, ast *snd); 183 | value *evalStmnt(ast *); 184 | ast *createRMW(ast *, unsigned, ast *); 185 | symbol *createFunctionDecl(symbol *); 186 | ast *createFunction(symbol *, ast *); 187 | ast *createBlock(symbol *, ast *); 188 | ast *createLabel(symbol *, ast *); 189 | ast *createCase(ast *, ast *, ast *); 190 | ast *createDefault(ast *, ast *, ast *); 191 | ast *forLoopOptForm(ast *); 192 | ast *argAst(ast *); 193 | ast *resolveSymbols(ast *); 194 | void CodePtrPointsToConst(sym_link *t); 195 | void checkPtrCast(sym_link *newType, sym_link *orgType, bool implicit); 196 | ast *decorateType(ast *, RESULT_TYPE); 197 | ast *createWhile(symbol *, symbol *, symbol *, ast *, ast *); 198 | ast *createIf(ast *, ast *, ast *); 199 | ast *createDo(symbol *, symbol *, symbol *, ast *, ast *); 200 | ast *createFor(symbol *, symbol *, symbol *, symbol *, ast *, ast *, ast *, 201 | ast *, ast *); 202 | void eval2icode(ast *); 203 | value *constExprValue(ast *, int); 204 | bool constExprTree(ast *); 205 | int setAstFileLine(ast *, char *, int); 206 | symbol *funcOfType(const char *, sym_link *, sym_link *, int, int); 207 | symbol *funcOfTypeVarg(const char *, const char *, int, const char **); 208 | ast *initAggregates(symbol *, initList *, ast *); 209 | bool hasSEFcalls(ast *); 210 | void addSymToBlock(symbol *, ast *); 211 | void freeStringSymbol(symbol *); 212 | DEFSETFUNC(resetParmKey); 213 | int astErrors(ast *); 214 | RESULT_TYPE getResultTypeFromType(sym_link *); 215 | 216 | // exported variables 217 | extern set *operKeyReset; 218 | extern int noAlloc; 219 | extern int inInitMode; 220 | 221 | #endif 222 | -------------------------------------------------------------------------------- /src/SDCCbitv.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | SDCCbitv.h - contains support routines for bitVectors 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | /* #include "SDCCglobl.h" */ 26 | /* #include "SDCCsymt.h" */ 27 | 28 | #ifndef SDCCBITV_H 29 | #define SDCCBITV_H 30 | 31 | /* bitvector */ 32 | typedef struct bitVect { 33 | int size; 34 | int bSize; 35 | unsigned char *vect; 36 | } bitVect; 37 | 38 | extern int bitVectDefault; 39 | /*-----------------------------------------------------------------*/ 40 | /* Forward definition for functions */ 41 | /*-----------------------------------------------------------------*/ 42 | /* bitvector related functions */ 43 | bitVect *newBitVect(int); 44 | void freeBitVect(bitVect *); 45 | bitVect *bitVectResize(bitVect *, int); 46 | bitVect *bitVectSetBit(bitVect *, int); 47 | void bitVectUnSetBit(const bitVect *, int); 48 | int bitVectBitValue(const bitVect *, int); 49 | bitVect *bitVectUnion(bitVect *, bitVect *); 50 | bitVect *bitVectIntersect(bitVect *, bitVect *); 51 | int bitVectBitsInCommon(const bitVect *, const bitVect *); 52 | bitVect *bitVectCplAnd(bitVect *, bitVect *); 53 | int bitVectEqual(bitVect *, bitVect *); 54 | bitVect *bitVectCopy(const bitVect *); 55 | int bitVectIsZero(const bitVect *); 56 | int bitVectnBitsOn(const bitVect *); 57 | int bitVectFirstBit(const bitVect *); 58 | void bitVectDebugOn(bitVect *, FILE *); 59 | #endif 60 | -------------------------------------------------------------------------------- /src/SDCCbtree.cc: -------------------------------------------------------------------------------- 1 | // Philipp Klaus Krause, philipp@informatik.uni-frankfurt.de, pkk@spth.de, 2011 2 | // 3 | // (c) 2011 Goethe-Universität Frankfurt 4 | // 5 | // This program is free software; you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by the 7 | // Free Software Foundation; either version 2, or (at your option) any 8 | // later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program; if not, write to the Free Software 17 | // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include "common.h" 25 | 26 | #ifdef HAVE_STX_BTREE_MAP_H 27 | #include 28 | #endif 29 | 30 | extern "C" { 31 | #include "SDCCbtree.h" 32 | } 33 | 34 | #undef BTREE_DEBUG 35 | 36 | typedef boost::adjacency_list, int>> 38 | btree_t; 39 | #ifdef HAVE_STX_BTREE_MAP_H 40 | typedef stx::btree_map bmap_t; 41 | typedef stx::btree_map bmaprev_t; 42 | #else 43 | typedef std::map bmap_t; 44 | typedef std::map bmaprev_t; 45 | #endif 46 | 47 | static btree_t btree; 48 | static bmap_t bmap; 49 | static bmaprev_t bmaprev; 50 | 51 | void btree_clear_subtree(btree_t::vertex_descriptor v) { 52 | btree[v].first.clear(); 53 | 54 | boost::graph_traits::out_edge_iterator e, e_end; 55 | for (boost::tie(e, e_end) = boost::out_edges(v, btree); e != e_end; ++e) 56 | btree_clear_subtree(boost::target(*e, btree)); 57 | } 58 | 59 | void btree_clear(void) { 60 | #ifdef BTREE_DEBUG 61 | std::cout << "Clearing.\n"; 62 | std::cout.flush(); 63 | #endif 64 | btree_clear_subtree(0); 65 | } 66 | 67 | void btree_add_child(short parent, short child) { 68 | #ifdef BTREE_DEBUG 69 | std::cout << "Adding child " << child << " at parent " << parent << "\n"; 70 | std::cout.flush(); 71 | #endif 72 | 73 | if (!boost::num_vertices(btree)) { 74 | boost::add_vertex(btree); 75 | bmap[0] = 0; 76 | bmaprev[0] = 0; 77 | } 78 | 79 | wassert(parent != child); 80 | wassert(bmap.find(parent) != bmap.end()); 81 | 82 | btree_t::vertex_descriptor c = boost::add_vertex(btree); 83 | bmap[child] = c; 84 | bmaprev[c] = child; 85 | 86 | wassert(bmap[parent] != c); 87 | 88 | boost::add_edge(bmap[parent], c, btree); 89 | } 90 | 91 | static btree_t::vertex_descriptor 92 | btree_lowest_common_ancestor_impl(btree_t::vertex_descriptor a, 93 | btree_t::vertex_descriptor b) { 94 | if (a == b) 95 | return (a); 96 | else if (a > b) 97 | a = boost::source(*boost::in_edges(a, btree).first, btree); 98 | else // (a < b) 99 | b = boost::source(*boost::in_edges(b, btree).first, btree); 100 | 101 | return (btree_lowest_common_ancestor(a, b)); 102 | } 103 | 104 | short btree_lowest_common_ancestor(short a, short b) { 105 | return (bmaprev[btree_lowest_common_ancestor_impl(bmap[a], bmap[b])]); 106 | } 107 | 108 | void btree_add_symbol(struct symbol *s) { 109 | int block; 110 | wassert(s); 111 | block = s->_isparm ? 0 : s->block; // This is essentially a workaround. TODO: 112 | // Ensure that the parameter block is 113 | // placed correctly in the btree instead! 114 | 115 | #ifdef BTREE_DEBUG 116 | std::cout << "Adding symbol " << s->name << " at " << block << "\n"; 117 | #endif 118 | 119 | wassert(bmap.find(block) != bmap.end()); 120 | wassert(bmap[block] < boost::num_vertices(btree)); 121 | btree[bmap[block]].first.insert(s); 122 | } 123 | 124 | static void btree_alloc_subtree(btree_t::vertex_descriptor v, int sPtr, 125 | int cssize, int *ssize) { 126 | std::set::iterator s, s_end; 127 | wassert(v < boost::num_vertices(btree)); 128 | for (s = btree[v].first.begin(), s_end = btree[v].first.end(); s != s_end; 129 | ++s) { 130 | struct symbol *const sym = *s; 131 | const int size = getSize(sym->type); 132 | 133 | #ifdef BTREE_DEBUG 134 | std::cout << "Allocating symbol " << sym->name << " (" << v << ") of size " 135 | << size << " to " << sPtr << "\n"; 136 | #endif 137 | 138 | if (port->stack.direction > 0) { 139 | SPEC_STAK(sym->etype) = sym->stack = (sPtr + 1); 140 | sPtr += size; 141 | } else { 142 | sPtr -= size; 143 | SPEC_STAK(sym->etype) = sym->stack = sPtr; 144 | } 145 | 146 | cssize += size; 147 | } 148 | btree[v].second = cssize; 149 | if (cssize > *ssize) 150 | *ssize = cssize; 151 | 152 | boost::graph_traits::out_edge_iterator e, e_end; 153 | for (boost::tie(e, e_end) = boost::out_edges(v, btree); e != e_end; ++e) 154 | btree_alloc_subtree(boost::target(*e, btree), sPtr, cssize, ssize); 155 | } 156 | 157 | void btree_alloc(void) { 158 | int ssize = 0; 159 | 160 | if (!boost::num_vertices(btree)) 161 | return; 162 | 163 | btree_alloc_subtree(0, 0, 0, &ssize); 164 | 165 | if (currFunc) { 166 | currFunc->stack += ssize; 167 | SPEC_STAK(currFunc->etype) += ssize; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/SDCCbtree.h: -------------------------------------------------------------------------------- 1 | // Philipp Klaus Krause, philipp@informatik.uni-frankfurt.de, pkk@spth.de, 2011 2 | // 3 | // (c) 2011 Goethe-Universität Frankfurt 4 | // 5 | // This program is free software; you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by the 7 | // Free Software Foundation; either version 2, or (at your option) any 8 | // later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program; if not, write to the Free Software 17 | // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | 19 | #ifndef SDCCBTREE_H 20 | #define SDCCBTREE_H 21 | 22 | // Clear block tree. To be called after each function. 23 | void btree_clear(void); 24 | 25 | // Add child as a sub-block of parent. 26 | void btree_add_child(short parent, short child); 27 | 28 | // Gives the lowest common ancestor for blocks a and b. 29 | short btree_lowest_common_ancestor(short a, short b); 30 | 31 | // Add symbol to block tree for allocation. 32 | void btree_add_symbol(struct symbol *s); 33 | 34 | // Allocate all previously added symbols on the stack. 35 | void btree_alloc(void); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/SDCCcflow.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCcflow.h - header file for control flow analysis 4 | 5 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | In other words, you are welcome to use, share and improve this program. 22 | You are forbidden to forbid anyone else to use, share and improve 23 | what you give them. Help stamp out software-hoarding! 24 | -------------------------------------------------------------------------*/ 25 | 26 | #include "SDCCset.h" 27 | 28 | #ifndef SDCCCFLOW_H 29 | #define SDCCCFLOW_H 1 30 | 31 | eBBlock *immedDom(ebbIndex *, eBBlock *); 32 | void computeControlFlow(ebbIndex *); 33 | void disconBBlock(eBBlock *, ebbIndex *); 34 | int returnAtEnd(eBBlock *); 35 | #endif 36 | -------------------------------------------------------------------------------- /src/SDCCcse.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCcse.h - header file for Common Subexpressions 4 | 5 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | In other words, you are welcome to use, share and improve this program. 22 | You are forbidden to forbid anyone else to use, share and improve 23 | what you give them. Help stamp out software-hoarding! 24 | -------------------------------------------------------------------------*/ 25 | 26 | #include "SDCCicode.h" 27 | 28 | #ifndef SDCCCSE_H 29 | #define SDCCCSE_H 1 30 | 31 | typedef struct cseDef { 32 | 33 | int key; 34 | operand *sym; /* defining symbol */ 35 | iCode *diCode; /* defining instruction */ 36 | bitVect *ancestors; /* keys of the symbol's ancestors */ 37 | int fromGlobal; /* defining symbol's value computed from a global */ 38 | int fromAddrTaken : 1; /* defining symbol's value computed from a */ 39 | /* symbol whose address was taken */ 40 | } cseDef; 41 | 42 | cseDef *newCseDef(operand *, iCode *); 43 | int isCseDefEqual(void *, void *); 44 | int pcseDef(void *, va_list); 45 | DEFSETFUNC(ifDiCodeIsX); 46 | int ifDiCodeIs(set *, iCode *); 47 | DEFSETFUNC(ifDefSymIsX); 48 | int ifDefSymIs(set *, operand *); 49 | DEFSETFUNC(findPrevIc); 50 | DEFSETFUNC(ifOperandsHave); 51 | DEFSETFUNC(findCheaperOp); 52 | int cseBBlock(eBBlock *, int, ebbIndex *); 53 | int cseAllBlocks(ebbIndex *, int computeOnly); 54 | void unsetDefsAndUses(iCode *); 55 | void updateSpillLocation(iCode *ic, int); 56 | void setUsesDefs(operand *, bitVect *, bitVect *, bitVect **); 57 | void replaceAllSymBySym(iCode *, operand *, operand *, bitVect **); 58 | iCode *findBackwardDef(operand *, iCode *); 59 | void ReplaceOpWithCheaperOp(operand **op, operand *cop); 60 | #endif 61 | -------------------------------------------------------------------------------- /src/SDCCdflow.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCdflow.c - source file for data flow analysis and other utility 4 | routines related to data flow. 5 | 6 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 7 | 8 | This program is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU General Public License as published by the 10 | Free Software Foundation; either version 2, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | In other words, you are welcome to use, share and improve this program. 23 | You are forbidden to forbid anyone else to use, share and improve 24 | what you give them. Help stamp out software-hoarding! 25 | -------------------------------------------------------------------------*/ 26 | 27 | #include "common.h" 28 | 29 | /*-----------------------------------------------------------------*/ 30 | /* ifKilledInBlock - will return 1 if the symbol is redefined in B */ 31 | /*-----------------------------------------------------------------*/ 32 | DEFSETFUNC(ifKilledInBlock) { 33 | cseDef *cdp = item; 34 | V_ARG(eBBlock *, src); 35 | bitVect *outs; 36 | 37 | /* if this is a global variable and this block 38 | has a function call then delete it */ 39 | if (isOperandGlobal(cdp->sym) && src->hasFcall) 40 | return 1; 41 | 42 | /* if this is pointer get then it will be killed 43 | if there is a pointer set for the same pointer 44 | in this block */ 45 | if (POINTER_GET(cdp->diCode) && 46 | bitVectBitValue(src->ptrsSet, IC_LEFT(cdp->diCode)->key)) 47 | return 1; 48 | 49 | /* if assignment to iTmep then if right is defined 50 | elsewhere kill this one */ 51 | if (ASSIGNMENT(cdp->diCode) && !POINTER_SET(cdp->diCode) && 52 | IS_ITEMP(IC_RESULT(cdp->diCode)) && IS_SYMOP(IC_RIGHT(cdp->diCode)) && 53 | bitVectBitsInCommon(src->outDefs, OP_DEFS(IC_RIGHT(cdp->diCode)))) 54 | return 1; 55 | 56 | /* if we find it in the defSet of this block */ 57 | if (bitVectBitsInCommon(src->defSet, OP_DEFS(cdp->sym))) 58 | return 1; 59 | 60 | /* if in the outdef we find a definition other than this one */ 61 | /* to do this we make a copy of the out definitions and turn */ 62 | /* this one off then check if there are other definitions */ 63 | bitVectUnSetBit(outs = bitVectCopy(src->outDefs), cdp->diCode->key); 64 | if (bitVectBitsInCommon(outs, OP_DEFS(cdp->sym))) { 65 | setToNull((void *)&outs); 66 | return 1; 67 | } 68 | 69 | setToNull((void *)&outs); 70 | 71 | /* if the operands of this one was changed in the block */ 72 | /* then delete it */ 73 | if (cdp->diCode && 74 | ((IS_SYMOP(IC_LEFT(cdp->diCode)) && 75 | bitVectBitsInCommon(src->defSet, OP_DEFS(IC_LEFT(cdp->diCode)))) || 76 | (IS_SYMOP(IC_RIGHT(cdp->diCode)) && 77 | bitVectBitsInCommon(src->defSet, OP_DEFS(IC_RIGHT(cdp->diCode)))))) 78 | return 1; 79 | 80 | /* kill if cseBBlock() found a case we missed here */ 81 | if (isinSetWith(src->killedExprs, cdp, isCseDefEqual)) 82 | return 1; 83 | 84 | return 0; 85 | } 86 | 87 | /*-----------------------------------------------------------------*/ 88 | /* mergeInExprs - copy the in expression if it dominates */ 89 | /*-----------------------------------------------------------------*/ 90 | DEFSETFUNC(mergeInExprs) { 91 | eBBlock *ebp = item; 92 | V_ARG(eBBlock *, dest); 93 | V_ARG(int *, firstTime); 94 | 95 | dest->killedExprs = 96 | unionSets(dest->killedExprs, ebp->killedExprs, THROW_DEST); 97 | 98 | /* if in the dominator list then */ 99 | if (bitVectBitValue(dest->domVect, ebp->bbnum) && dest != ebp) { 100 | /* if already present then intersect */ 101 | if (!dest->inExprs && *firstTime) { 102 | dest->inExprs = setFromSet(ebp->outExprs); 103 | /* copy the pointer set from the dominator */ 104 | dest->inPtrsSet = bitVectCopy(ebp->ptrsSet); 105 | dest->ndompset = bitVectCopy(ebp->ndompset); 106 | } else { 107 | dest->inExprs = intersectSets(dest->inExprs, ebp->outExprs, THROW_DEST); 108 | dest->inPtrsSet = bitVectUnion(dest->inPtrsSet, ebp->ptrsSet); 109 | dest->ndompset = bitVectUnion(dest->ndompset, ebp->ndompset); 110 | } 111 | } else { 112 | // if (dest != ebp) 113 | // dest->inExprs = intersectSets (dest->inExprs, ebp->outExprs, 114 | // THROW_DEST); 115 | 116 | /* delete only if killed in this block*/ 117 | deleteItemIf(&dest->inExprs, ifKilledInBlock, ebp); 118 | /* union the ndompset with pointers set in this block */ 119 | dest->ndompset = bitVectUnion(dest->ndompset, ebp->ptrsSet); 120 | } 121 | *firstTime = 0; 122 | 123 | return 0; 124 | } 125 | 126 | /*-----------------------------------------------------------------*/ 127 | /* mergeInDefs - merge in incoming definitions */ 128 | /*-----------------------------------------------------------------*/ 129 | DEFSETFUNC(mergeInDefs) { 130 | eBBlock *ebp = item; 131 | V_ARG(eBBlock *, dest); 132 | V_ARG(int *, firstTime); 133 | 134 | /* the in definition is the union of the out */ 135 | /* of all blocks that come to this block */ 136 | if (!dest->inDefs && *firstTime) 137 | dest->inDefs = bitVectCopy(ebp->outDefs); 138 | else 139 | dest->inDefs = bitVectUnion(dest->inDefs, ebp->outDefs); 140 | 141 | *firstTime = 0; 142 | 143 | return 0; 144 | } 145 | 146 | /*------------------------------------------------------------------*/ 147 | /* computeDataFlow - does computations for data flow accross blocks */ 148 | /*------------------------------------------------------------------*/ 149 | void computeDataFlow(ebbIndex *ebbi) { 150 | eBBlock **ebbs = ebbi->dfOrder; 151 | int count = ebbi->count; 152 | int i; 153 | int change; 154 | 155 | for (i = 0; i < count; i++) 156 | ebbs[i]->killedExprs = NULL; 157 | 158 | do { 159 | change = 0; 160 | 161 | /* for all blocks */ 162 | for (i = 0; i < count; i++) { 163 | set *pred; 164 | set *oldOutExprs = NULL; 165 | set *oldKilledExprs = NULL; 166 | bitVect *oldOutDefs = NULL; 167 | int firstTime; 168 | eBBlock *pBlock; 169 | 170 | /* if this is the entry block then continue */ 171 | /* since entry block can never have any inExprs */ 172 | if (ebbs[i]->noPath) 173 | continue; 174 | 175 | /* get blocks that can come to this block */ 176 | pred = edgesTo(ebbs[i]); 177 | 178 | /* make a copy of the outExpressions and outDefs : to be */ 179 | /* used for iteration */ 180 | if (optimize.global_cse) { 181 | oldOutExprs = setFromSet(ebbs[i]->outExprs); 182 | oldKilledExprs = setFromSet(ebbs[i]->killedExprs); 183 | } 184 | oldOutDefs = bitVectCopy(ebbs[i]->outDefs); 185 | setToNull((void *)&ebbs[i]->inDefs); 186 | 187 | /* indefitions are easy just merge them by union */ 188 | /* these are the definitions that can possibly */ 189 | /* reach this block */ 190 | firstTime = 1; 191 | applyToSet(pred, mergeInDefs, ebbs[i], &firstTime); 192 | 193 | /* if none of the edges coming to this block */ 194 | /* dominate this block then add the immediate dominator */ 195 | /* of this block to the list of predecessors */ 196 | for (pBlock = setFirstItem(pred); pBlock; pBlock = setNextItem(pred)) { 197 | if (bitVectBitValue(ebbs[i]->domVect, pBlock->bbnum)) 198 | break; 199 | } 200 | 201 | /* get the immediate dominator and put it there */ 202 | if (!pBlock) { 203 | eBBlock *idom = immedDom(ebbi, ebbs[i]); 204 | if (idom) 205 | addSetHead(&pred, idom); 206 | } 207 | 208 | /* figure out the incoming expressions */ 209 | /* this is a little more complex */ 210 | setToNull((void *)&ebbs[i]->inExprs); 211 | if (optimize.global_cse) { 212 | firstTime = 1; 213 | applyToSet(pred, mergeInExprs, ebbs[i], &firstTime); 214 | } 215 | setToNull((void *)&pred); 216 | 217 | /* do cse with computeOnly flag set to TRUE */ 218 | /* this is by far the quickest way of computing */ 219 | cseBBlock(ebbs[i], TRUE, ebbi); 220 | 221 | /* if it change we will need to iterate */ 222 | if (optimize.global_cse) { 223 | change += 224 | !isSetsEqualWith(ebbs[i]->outExprs, oldOutExprs, isCseDefEqual); 225 | change += !isSetsEqualWith(ebbs[i]->killedExprs, oldKilledExprs, 226 | isCseDefEqual); 227 | } 228 | change += !bitVectEqual(ebbs[i]->outDefs, oldOutDefs); 229 | } 230 | } while (change); /* iterate till no change */ 231 | 232 | return; 233 | } 234 | 235 | /*-----------------------------------------------------------------*/ 236 | /* usedBetweenPoints - used between start & end */ 237 | /*-----------------------------------------------------------------*/ 238 | int usedBetweenPoints(operand *op, iCode *start, iCode *end) { 239 | iCode *lic = start; 240 | 241 | for (; lic != end; lic = lic->next) { 242 | /* if the operand is a parameter */ 243 | /* then check for calls and return */ 244 | /* true if there is a call */ 245 | if (IS_PARM(op) && (lic->op == CALL || lic->op == PCALL)) { 246 | value *args; 247 | if (lic->op == CALL) { 248 | args = FUNC_ARGS(OP_SYMBOL(IC_LEFT(lic))->type); 249 | } else { 250 | args = FUNC_ARGS(OP_SYMBOL(IC_LEFT(lic))->type->next); 251 | } 252 | if (isParameterToCall(args, op)) 253 | return 1; 254 | } 255 | 256 | if (SKIP_IC2(lic)) 257 | continue; 258 | 259 | /* if ifx then check the condition */ 260 | if (lic->op == IFX && IC_COND(lic)->key == op->key) 261 | return 1; 262 | 263 | if (lic->op == JUMPTABLE && IC_JTCOND(lic)->key == op->key) 264 | return 1; 265 | 266 | if (IC_RIGHT(lic) && IC_RIGHT(lic)->key == op->key) 267 | return 1; 268 | 269 | if (IC_LEFT(lic) && IC_LEFT(lic)->key == op->key) 270 | return 1; 271 | 272 | /* for a pointer assignment usage */ 273 | if (POINTER_SET(lic) && op->key == IC_RESULT(lic)->key) 274 | return 1; 275 | else if (IC_RESULT(lic) && op->key == IC_RESULT(lic)->key) 276 | return 0; 277 | } 278 | 279 | return 0; 280 | } 281 | 282 | /*------------------------------------------------------------------*/ 283 | /* usedInRemaining - returns point of usage for an operand if found */ 284 | /*------------------------------------------------------------------*/ 285 | iCode *usedInRemaining(operand *op, iCode *ic) { 286 | iCode *lic = ic; 287 | 288 | if (!IS_SYMOP(op)) 289 | return 0; 290 | 291 | for (; lic; lic = lic->next) { 292 | /* if the operand is a parameter */ 293 | /* then check for calls and return */ 294 | /* true if there is a call */ 295 | /* if this is a global variable then 296 | return true */ 297 | if (lic->op == CALL || lic->op == PCALL) { 298 | value *args; 299 | if (lic->op == CALL) 300 | args = FUNC_ARGS(operandType(IC_LEFT(lic))); 301 | else 302 | args = FUNC_ARGS(operandType(IC_LEFT(lic))->next); 303 | if ((IS_PARM(op) && isParameterToCall(args, op)) || isOperandGlobal(op)) 304 | return lic; 305 | } 306 | 307 | if (ic->op == SEND && isOperandEqual(IC_LEFT(lic), op)) 308 | return lic; 309 | 310 | if (SKIP_IC1(lic)) 311 | continue; 312 | 313 | /* if ifx then check the condition */ 314 | if (lic->op == IFX && isOperandEqual(IC_COND(lic), op)) 315 | return lic; 316 | 317 | if (lic->op == JUMPTABLE && isOperandEqual(IC_JTCOND(lic), op)) 318 | return lic; 319 | 320 | if (IC_RIGHT(lic) && isOperandEqual(IC_RIGHT(lic), op)) 321 | return lic; 322 | 323 | if (IC_LEFT(lic) && isOperandEqual(IC_LEFT(lic), op)) 324 | return lic; 325 | 326 | /* for a pointer assignment usage */ 327 | if (POINTER_SET(lic) && isOperandEqual(op, IC_RESULT(lic))) 328 | return lic; 329 | else if (IC_RESULT(lic) && isOperandEqual(IC_RESULT(lic), op)) 330 | return NULL; 331 | } 332 | 333 | return NULL; 334 | } 335 | 336 | /*-------------------------------------------------------------------*/ 337 | /* isDefAlive - will return true if definiton reaches a block & used */ 338 | /*-------------------------------------------------------------------*/ 339 | DEFSETFUNC(isDefAlive) { 340 | eBBlock *ebp = item; 341 | V_ARG(iCode *, diCode); 342 | 343 | if (ebp->visited) 344 | return 0; 345 | 346 | ebp->visited = 1; 347 | 348 | /* if this definition is used in the block */ 349 | if (bitVectBitValue(ebp->usesDefs, diCode->key)) 350 | return 1; 351 | 352 | return applyToSet(ebp->succList, isDefAlive, diCode); 353 | } 354 | -------------------------------------------------------------------------------- /src/SDCCdflow.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCdflow.h - header file for data flow analysis & utility routines 4 | related to data flow. 5 | 6 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 7 | 8 | This program is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU General Public License as published by the 10 | Free Software Foundation; either version 2, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | In other words, you are welcome to use, share and improve this program. 23 | You are forbidden to forbid anyone else to use, share and improve 24 | what you give them. Help stamp out software-hoarding! 25 | -------------------------------------------------------------------------*/ 26 | 27 | #include "SDCCset.h" 28 | 29 | #ifndef SDCCDFLOW_H 30 | #define SDCCDFLOW_H 1 31 | 32 | DEFSETFUNC(mergeInExprs); 33 | DEFSETFUNC(ifKilledInBlock); 34 | void computeDataFlow(ebbIndex *); 35 | DEFSETFUNC(mergeInDefs); 36 | DEFSETFUNC(isDefAlive); 37 | iCode *usedInRemaining(operand *, iCode *); 38 | int usedBetweenPoints(operand *, iCode *, iCode *); 39 | #endif 40 | -------------------------------------------------------------------------------- /src/SDCCgen.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCgen.c - source files for target code generation common functions 3 | 4 | Copyright (C) 2012, Borut Razem 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | -------------------------------------------------------------------------*/ 20 | 21 | #include "common.h" 22 | #include "dbuf_string.h" 23 | 24 | /* Use the D macro for basic (unobtrusive) debugging messages */ 25 | #define D(x) \ 26 | do \ 27 | if (options.verboseAsm) { \ 28 | x; \ 29 | } \ 30 | while (0) 31 | 32 | genLine_t genLine; 33 | 34 | /*-----------------------------------------------------------------*/ 35 | /* newLineNode - creates a new peep line */ 36 | /*-----------------------------------------------------------------*/ 37 | lineNode *newLineNode(const char *line) { 38 | lineNode *pl; 39 | 40 | pl = Safe_alloc(sizeof(lineNode)); 41 | pl->line = Safe_strdup(line); 42 | pl->ic = NULL; 43 | return pl; 44 | } 45 | 46 | /*-----------------------------------------------------------------*/ 47 | /* connectLine - connects two lines */ 48 | /*-----------------------------------------------------------------*/ 49 | lineNode *connectLine(lineNode *pl1, lineNode *pl2) { 50 | if (!pl1 || !pl2) { 51 | fprintf(stderr, "trying to connect null line\n"); 52 | return NULL; 53 | } 54 | 55 | pl2->prev = pl1; 56 | pl1->next = pl2; 57 | 58 | return pl2; 59 | } 60 | 61 | void destroy_line_list(void) { 62 | lineNode *pl; 63 | 64 | pl = genLine.lineCurr; 65 | 66 | while (pl) { 67 | lineNode *p; 68 | 69 | if (pl->line) 70 | Safe_free(pl->line); 71 | 72 | if (pl->aln) 73 | Safe_free(pl->aln); 74 | 75 | p = pl; 76 | pl = pl->prev; 77 | Safe_free(p); 78 | } 79 | genLine.lineHead = genLine.lineCurr = NULL; 80 | } 81 | 82 | /*-----------------------------------------------------------------*/ 83 | /* emit_raw - emit raw unformatted line */ 84 | /*-----------------------------------------------------------------*/ 85 | static void add_line_node(const char *line) { 86 | lineNode *pl; 87 | 88 | pl = Safe_alloc(sizeof(lineNode)); 89 | 90 | #if 1 91 | memcpy(pl, (lineElem_t *)&genLine.lineElement, sizeof(lineElem_t)); 92 | #else 93 | pl->ic = genLine.lineElement.ic; 94 | pl->isInline = genLine.lineElement.isInline; 95 | pl->isComment = genLine.lineElement.isComment; 96 | pl->isDebug = genLine.lineElement.isDebug; 97 | pl->isLabel = genLine.lineElement.isLabel; 98 | pl->visited = genLine.lineElement.visited; 99 | pl->aln = genLine.lineElement.aln; 100 | #endif 101 | 102 | pl->line = Safe_strdup(line); 103 | 104 | if (genLine.lineCurr) { 105 | pl->next = NULL; 106 | genLine.lineCurr->next = pl; 107 | pl->prev = genLine.lineCurr; 108 | genLine.lineCurr = pl; 109 | } else { 110 | pl->prev = pl->next = NULL; 111 | genLine.lineCurr = genLine.lineHead = pl; 112 | } 113 | } 114 | 115 | void emit_raw(const char *line) { 116 | const char *p = line; 117 | 118 | while (isspace((unsigned char)*p)) 119 | p++; 120 | 121 | if (*p) { 122 | if (!port->rtrackUpdate || !port->rtrackUpdate(line)) { 123 | genLine.lineElement.isComment = (*p == ';'); 124 | add_line_node(line); 125 | } 126 | } 127 | } 128 | 129 | /*-----------------------------------------------------------------*/ 130 | /* format_opcode - format the opcode and arguments for emitting */ 131 | /*-----------------------------------------------------------------*/ 132 | const char *format_opcode(const char *inst, const char *fmt, va_list ap) { 133 | struct dbuf_s dbuf; 134 | 135 | dbuf_init(&dbuf, INITIAL_INLINEASM); 136 | 137 | if (inst && *inst) { 138 | dbuf_append_str(&dbuf, inst); 139 | 140 | if (fmt && *fmt) { 141 | dbuf_append_char(&dbuf, '\t'); 142 | dbuf_tvprintf(&dbuf, fmt, ap); 143 | } 144 | } else { 145 | if (fmt && *fmt) { 146 | dbuf_tvprintf(&dbuf, fmt, ap); 147 | } 148 | } 149 | 150 | return dbuf_detach_c_str(&dbuf); 151 | } 152 | 153 | void va_emitcode(const char *inst, const char *fmt, va_list ap) { 154 | const char *line = format_opcode(inst, fmt, ap); 155 | emit_raw(line); 156 | dbuf_free(line); 157 | } 158 | 159 | /*-----------------------------------------------------------------*/ 160 | /* emitcode - writes the code into a file : for now it is simple */ 161 | /*-----------------------------------------------------------------*/ 162 | void emitcode(const char *inst, const char *fmt, ...) { 163 | va_list ap; 164 | 165 | va_start(ap, fmt); 166 | va_emitcode(inst, fmt, ap); 167 | va_end(ap); 168 | } 169 | 170 | void emitLabel(symbol *tlbl) { 171 | if (!tlbl) 172 | return; 173 | emitcode("", "!tlabeldef", labelKey2num(tlbl->key)); 174 | genLine.lineCurr->isLabel = 1; 175 | } 176 | 177 | /*-----------------------------------------------------------------*/ 178 | /* genInline - write the inline code out */ 179 | /*-----------------------------------------------------------------*/ 180 | void genInline(iCode *ic) { 181 | char *buf, *bp, *begin; 182 | bool inComment = FALSE; 183 | 184 | D(emitcode(";", "genInline")); 185 | 186 | genLine.lineElement.isInline += (!options.asmpeep); 187 | 188 | buf = bp = begin = Safe_strdup(IC_INLINE(ic)); 189 | 190 | /* Emit each line as a code */ 191 | while (*bp) { 192 | switch (*bp) { 193 | case ';': 194 | inComment = TRUE; 195 | ++bp; 196 | break; 197 | 198 | case '\x87': 199 | case '\n': 200 | inComment = FALSE; 201 | *bp++ = '\0'; 202 | 203 | /* Don't emit leading whitespaces */ 204 | while (isspace(*begin)) 205 | ++begin; 206 | 207 | if (*begin) 208 | emitcode(begin, NULL); 209 | 210 | begin = bp; 211 | break; 212 | 213 | default: 214 | /* Add \n for labels, not dirs such as c:\mydir */ 215 | if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1]))) { 216 | ++bp; 217 | *bp = '\0'; 218 | ++bp; 219 | emitcode(begin, NULL); 220 | begin = bp; 221 | } else 222 | ++bp; 223 | break; 224 | } 225 | } 226 | if (begin != bp) { 227 | /* Don't emit leading whitespaces */ 228 | while (isspace(*begin)) 229 | ++begin; 230 | 231 | if (*begin) 232 | emitcode(begin, NULL); 233 | } 234 | 235 | Safe_free(buf); 236 | 237 | /* consumed; we can free it here */ 238 | dbuf_free(IC_INLINE(ic)); 239 | 240 | genLine.lineElement.isInline -= (!options.asmpeep); 241 | } 242 | 243 | /*-----------------------------------------------------------------*/ 244 | /* printLine - prints a line chain into a given file */ 245 | /*-----------------------------------------------------------------*/ 246 | void printLine(lineNode *head, struct dbuf_s *oBuf) { 247 | iCode *last_ic = NULL; 248 | bool debug_iCode_tracking = (getenv("DEBUG_ICODE_TRACKING") != NULL); 249 | 250 | while (head) { 251 | if (head->ic != last_ic) { 252 | last_ic = head->ic; 253 | if (debug_iCode_tracking) { 254 | if (head->ic) 255 | dbuf_printf(oBuf, "; block = %d, seq = %d\n", head->ic->block, 256 | head->ic->seq); 257 | else 258 | dbuf_append_str(oBuf, "; iCode lost\n"); 259 | } 260 | } 261 | 262 | /* don't indent comments & labels */ 263 | if (head->line && (head->isComment || head->isLabel)) { 264 | dbuf_printf(oBuf, "%s\n", head->line); 265 | } else { 266 | if (head->isInline && *head->line == '#') { 267 | /* comment out preprocessor directives in inline asm */ 268 | dbuf_append_char(oBuf, ';'); 269 | } 270 | dbuf_printf(oBuf, "\t%s\n", head->line); 271 | } 272 | head = head->next; 273 | } 274 | } 275 | 276 | /*-----------------------------------------------------------------*/ 277 | /* ifxForOp - returns the icode containing the ifx for operand */ 278 | /*-----------------------------------------------------------------*/ 279 | iCode *ifxForOp(operand *op, const iCode *ic) { 280 | iCode *ifxIc; 281 | 282 | /* if true symbol then needs to be assigned */ 283 | if (!IS_TRUE_SYMOP(op)) { 284 | /* if this has register type condition and 285 | while skipping ipop's (see bug 1509084), 286 | the next instruction is ifx with the same operand 287 | and live to of the operand is upto the ifx only then */ 288 | for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next) 289 | ; 290 | 291 | if (ifxIc && ifxIc->op == IFX && IC_COND(ifxIc)->key == op->key && 292 | OP_SYMBOL(op)->liveTo <= ifxIc->seq) 293 | return ifxIc; 294 | } 295 | 296 | return NULL; 297 | } 298 | -------------------------------------------------------------------------------- /src/SDCCgen.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCgen.h - header file for target code generation common functions 3 | 4 | Copyright (C) 2012, Borut Razem 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | -------------------------------------------------------------------------*/ 20 | 21 | #ifndef SDCCGEN_H 22 | #define SDCCGEN_H 1 23 | 24 | #include 25 | 26 | #include "SDCCicode.h" 27 | 28 | #define initGenLineElement() memset(&genLine.lineElement, 0, sizeof(lineElem_t)) 29 | #define labelKey2num(key) ((key) + 100) 30 | 31 | /* can be inherited by each port */ 32 | typedef struct asmLineNodeBase { 33 | int size; 34 | bitVect *regsRead; 35 | bitVect *regsWritten; 36 | } asmLineNodeBase; 37 | 38 | typedef struct lineElem_s { 39 | char *line; 40 | iCode *ic; 41 | unsigned int isInline : 1; 42 | unsigned int isComment : 1; 43 | unsigned int isDebug : 1; 44 | unsigned int isLabel : 1; 45 | unsigned int visited : 1; 46 | asmLineNodeBase *aln; 47 | } lineElem_t; 48 | 49 | typedef struct lineNode_s { 50 | char *line; 51 | iCode *ic; 52 | unsigned int isInline : 1; 53 | unsigned int isComment : 1; 54 | unsigned int isDebug : 1; 55 | unsigned int isLabel : 1; 56 | unsigned int visited : 1; 57 | asmLineNodeBase *aln; 58 | struct lineNode_s *prev; 59 | struct lineNode_s *next; 60 | } lineNode; 61 | 62 | typedef struct genLine_s { 63 | /* double linked list of lines */ 64 | lineNode *lineHead; 65 | lineNode *lineCurr; 66 | 67 | /* global line */ 68 | lineElem_t lineElement; 69 | } genLine_t; 70 | 71 | extern genLine_t genLine; 72 | 73 | #ifdef __cplusplus 74 | extern "C" { 75 | #endif 76 | 77 | lineNode *newLineNode(const char *line); 78 | lineNode *connectLine(lineNode *pl1, lineNode *pl2); 79 | void destroy_line_list(void); 80 | const char *format_opcode(const char *inst, const char *fmt, va_list ap); 81 | void emit_raw(const char *line); 82 | void va_emitcode(const char *inst, const char *fmt, va_list ap); 83 | void emitcode(const char *inst, const char *fmt, ...); 84 | void emitLabel(symbol *tlbl); 85 | void genInline(iCode *ic); 86 | void printLine(lineNode *, struct dbuf_s *); 87 | iCode *ifxForOp(operand *op, const iCode *ic); 88 | 89 | #ifdef __cplusplus 90 | } 91 | #endif 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /src/SDCCglue.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCglue.h - glues everything we have done together into one file. 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | #include "SDCCglobl.h" 25 | #include "SDCCmem.h" 26 | 27 | #ifndef SDCCGLUE_H 28 | #define SDCCGLUE_H 1 29 | 30 | void glue(void); 31 | /* drdani Jan 30 2000 32 | This is needed in gen.c of z80 port */ 33 | char *aopLiteral(value *, int); 34 | void flushStatics(void); 35 | int printIvalCharPtr(symbol *, sym_link *, value *, struct dbuf_s *); 36 | 37 | extern symbol *interrupts[]; 38 | extern set *publics; 39 | 40 | int pointerTypeToGPByte(const int p_type, const char *iname, const char *oname); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/SDCChasht.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | SDCChast.h - contains support routines for hashtables/sets . 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | #ifndef SDCCHASHT_H 26 | #define SDCCHASHT_H 27 | 28 | /* hashtable item */ 29 | typedef struct hashtItem { 30 | int key; 31 | /* Pointer to the key that was hashed for key. 32 | Used for a hash table with unique keys. */ 33 | void *pkey; 34 | void *item; 35 | struct hashtItem *next; 36 | } hashtItem; 37 | 38 | /* hashtable */ 39 | typedef struct hTab { 40 | int size; /* max number of items */ 41 | int minKey; /* minimum key value */ 42 | int maxKey; /* maximum key value */ 43 | hashtItem **table; /* the actual table */ 44 | int currKey; /* used for iteration */ 45 | hashtItem *currItem; /* current item within the list */ 46 | int nItems; 47 | } hTab; 48 | 49 | typedef enum { DELETE_CHAIN = 1, DELETE_ITEM } DELETE_ACTION; 50 | 51 | /*-----------------------------------------------------------------*/ 52 | /* Forward definition for functions */ 53 | /*-----------------------------------------------------------------*/ 54 | 55 | /* hashtable related functions */ 56 | hTab *newHashTable(int); 57 | void hTabAddItem(hTab **, int key, void *item); 58 | /** Adds a new item to the hash table. 59 | @param h The hash table to add to 60 | @param key A hashed version of pkey 61 | @param pkey A copy of the key. Owned by the 62 | hash table after this function. 63 | @param item Value for this key. 64 | */ 65 | void hTabAddItemLong(hTab **h, int key, void *pkey, void *item); 66 | /** Finds a item by exact key. 67 | Searches all items in the key 'key' for a key that 68 | according to 'compare' matches pkey. 69 | @param h The hash table to search 70 | @param key A hashed version of pkey. 71 | @param pkey The key to search for 72 | @param compare Returns 0 if pkey == this 73 | */ 74 | void *hTabFindByKey(hTab *h, int key, const void *pkey, 75 | int (*compare)(const void *, const void *)); 76 | /** Deletes an item with the exact key 'pkey' 77 | @see hTabFindByKey 78 | */ 79 | int hTabDeleteByKey(hTab **h, int key, const void *pkey, 80 | int (*compare)(const void *, const void *)); 81 | 82 | void hTabDeleteItem(hTab **, int key, const void *item, DELETE_ACTION action, 83 | int (*compareFunc)(const void *, const void *)); 84 | int hTabIsInTable(hTab *, int, void *, int (*compareFunc)(void *, void *)); 85 | void *hTabFirstItem(hTab *, int *); 86 | void *hTabNextItem(hTab *, int *); 87 | hTab *hTabFromTable(hTab *); 88 | int isHtabsEqual(hTab *, hTab *, int (*compareFunc)(void *, void *)); 89 | hashtItem *hTabSearch(hTab *, int); 90 | 91 | /* return the first item with the given key */ 92 | void *hTabItemWithKey(hTab *, int); 93 | 94 | void hTabAddItemIfNotP(hTab **, int, void *); 95 | void hTabDeleteAll(hTab *); 96 | void *hTabFirstItemWK(hTab *htab, int wk); 97 | void *hTabNextItemWK(hTab *htab); 98 | void hTabClearAll(hTab *htab); 99 | int hTabMaxKey(hTab *htab); 100 | 101 | /** Find the first item that either is 'item' or which 102 | according to 'compareFunc' is the same as item. 103 | @param compareFunc strcmp like compare function, may be null. 104 | */ 105 | void *hTabFindItem(hTab *htab, int key, void *item, 106 | int (*compareFunc)(void *, void *)); 107 | 108 | void shash_add(hTab **h, const char *szKey, const char *szValue); 109 | const char *shash_find(hTab *h, const char *szKey); 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /src/SDCClabel.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | SDCClabel.h - label optimizations on iCode (intermediate code) 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | #include "SDCCglobl.h" 26 | #include "SDCCsymt.h" 27 | 28 | #ifndef SDCCLABEL_H 29 | #define SDCCLABEL_H 30 | 31 | extern hTab *labelRef; 32 | extern hTab *labelDef; 33 | extern int labelKey; 34 | 35 | iCode *iCodeLabelOptimize(iCode *); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/SDCCloop.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCloop.h - header file for loop detection & optimizations 4 | 5 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | In other words, you are welcome to use, share and improve this program. 22 | You are forbidden to forbid anyone else to use, share and improve 23 | what you give them. Help stamp out software-hoarding! 24 | -------------------------------------------------------------------------*/ 25 | #include "SDCCBBlock.h" 26 | #include "SDCCcse.h" 27 | 28 | #ifndef SDCCLOOP_H 29 | #define SDCCLOOP_H 1 30 | 31 | typedef struct region { 32 | 33 | unsigned int merged : 1; 34 | unsigned int visited : 1; 35 | eBBlock *entry; /* entry Block */ 36 | int containsLoops; /* contains other loops */ 37 | set *regBlocks; /* set of all blocks */ 38 | set *exits; /* set of exits */ 39 | } region; 40 | 41 | typedef struct induction { 42 | 43 | operand *sym; 44 | operand *asym; 45 | unsigned int op; 46 | long cval; 47 | iCode *ic; 48 | } induction; 49 | 50 | int loopOptimizations(hTab *, ebbIndex *); 51 | hTab *createLoopRegions(ebbIndex *); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/SDCClospre.cc: -------------------------------------------------------------------------------- 1 | // Philipp Klaus Krause, philipp@informatik.uni-frankfurt.de, pkk@spth.de, 2012 2 | // 3 | // (c) 2012 Goethe-Universität Frankfurt 4 | // 5 | // This program is free software; you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by the 7 | // Free Software Foundation; either version 2, or (at your option) any 8 | // later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program; if not, write to the Free Software 17 | // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | // 19 | // 20 | // Lifetime-optimal speculative partial redundancy elimination. 21 | 22 | // #define DEBUG_LOSPRE // Uncomment to get debug messages while doing lospre. 23 | 24 | #include "SDCClospre.hpp" 25 | 26 | // A quick-and-dirty function to get the CFG from sdcc (a simplified version of 27 | // the function from SDCCralloc.hpp). 28 | void create_cfg_lospre(cfg_lospre_t &cfg, iCode *start_ic, ebbIndex *ebbi) { 29 | iCode *ic; 30 | 31 | std::map key_to_index; 32 | { 33 | int i; 34 | 35 | for (ic = start_ic, i = 0; ic; ic = ic->next, i++) { 36 | boost::add_vertex(cfg); 37 | key_to_index[ic->key] = i; 38 | cfg[i].ic = ic; 39 | } 40 | } 41 | 42 | // Get control flow graph from sdcc. 43 | for (ic = start_ic; ic; ic = ic->next) { 44 | if ((ic->op == '>' || ic->op == '<' || ic->op == LE_OP || ic->op == GE_OP || 45 | ic->op == EQ_OP || ic->op == NE_OP || ic->op == '^' || ic->op == '|' || 46 | ic->op == BITWISEAND) && 47 | ifxForOp(IC_RESULT(ic), ic)) 48 | boost::add_edge(key_to_index[ic->key], key_to_index[ic->next->key], 4.0f, 49 | cfg); // Try not to separate op from ifx. 50 | else if (ic->op != GOTO && ic->op != RETURN && ic->op != JUMPTABLE && 51 | ic->next) 52 | boost::add_edge(key_to_index[ic->key], key_to_index[ic->next->key], 3.0f, 53 | cfg); 54 | 55 | if (ic->op == GOTO) 56 | boost::add_edge( 57 | key_to_index[ic->key], 58 | key_to_index[eBBWithEntryLabel(ebbi, ic->label)->sch->key], 6.0f, 59 | cfg); 60 | else if (ic->op == RETURN) 61 | boost::add_edge( 62 | key_to_index[ic->key], 63 | key_to_index[eBBWithEntryLabel(ebbi, returnLabel)->sch->key], 6.0f, 64 | cfg); 65 | else if (ic->op == IFX) 66 | boost::add_edge( 67 | key_to_index[ic->key], 68 | key_to_index[eBBWithEntryLabel(ebbi, IC_TRUE(ic) ? IC_TRUE(ic) 69 | : IC_FALSE(ic)) 70 | ->sch->key], 71 | 6.0f, cfg); 72 | else if (ic->op == JUMPTABLE) 73 | for (symbol *lbl = (symbol *)(setFirstItem(IC_JTLABELS(ic))); lbl; 74 | lbl = (symbol *)(setNextItem(IC_JTLABELS(ic)))) 75 | boost::add_edge(key_to_index[ic->key], 76 | key_to_index[eBBWithEntryLabel(ebbi, lbl)->sch->key], 77 | 6.0f, cfg); 78 | } 79 | } 80 | 81 | static bool candidate_expression(const iCode *const ic, int lkey) { 82 | wassert(ic); 83 | 84 | if (ic->op != '!' && ic->op != '~' && ic->op != UNARYMINUS && ic->op != '+' && 85 | ic->op != '-' && ic->op != '*' && ic->op != '/' && ic->op != '%' && 86 | ic->op != '>' && ic->op != '<' && ic->op != LE_OP && ic->op != GE_OP && 87 | ic->op != NE_OP && ic->op != EQ_OP && ic->op != AND_OP && 88 | ic->op != OR_OP && ic->op != '^' && ic->op != '|' && 89 | ic->op != BITWISEAND && ic->op != RRC && ic->op != RLC && 90 | ic->op != GETABIT && ic->op != GETHBIT && ic->op != LEFT_OP && 91 | ic->op != RIGHT_OP && 92 | !(ic->op == '=' && !POINTER_SET(ic) && 93 | !(IS_ITEMP(IC_RIGHT(ic)) /*&& IC_RIGHT(ic)->key > lkey*/)) && 94 | ic->op != GET_VALUE_AT_ADDRESS && ic->op != CAST) 95 | return (false); 96 | 97 | const operand *const left = IC_LEFT(ic); 98 | const operand *const right = IC_RIGHT(ic); 99 | const operand *const result = IC_RESULT(ic); 100 | 101 | // Todo: Allow literal right operand once backends can rematerialize literals! 102 | if (ic->op == '=' && IS_OP_LITERAL(right)) 103 | return (false); 104 | 105 | if (IS_OP_VOLATILE(left) || IS_OP_VOLATILE(right)) 106 | return (false); 107 | 108 | if (POINTER_GET(ic) && IS_VOLATILE(operandType(IC_LEFT(ic))->next)) 109 | return (false); 110 | 111 | // Todo: Allow more operands! 112 | if (ic->op != CAST && left && !(IS_SYMOP(left) || IS_OP_LITERAL(left)) || 113 | right && !(IS_SYMOP(right) || IS_OP_LITERAL(right)) || 114 | result && !(IS_SYMOP(result) || IS_OP_LITERAL(result))) 115 | return (false); 116 | 117 | return (true); 118 | } 119 | 120 | static bool same_expression(const iCode *const lic, const iCode *const ric) { 121 | wassert(lic); 122 | wassert(ric); 123 | 124 | if (lic->op != ric->op) 125 | return (false); 126 | 127 | const operand *lleft = IC_LEFT(lic); 128 | const operand *lright = IC_RIGHT(lic); 129 | const operand *lresult = IC_RESULT(lic); 130 | const operand *rleft = IC_LEFT(ric); 131 | const operand *rright = IC_RIGHT(ric); 132 | const operand *rresult = IC_RESULT(ric); 133 | 134 | if ((isOperandEqual(lleft, rleft) && isOperandEqual(lright, rright) || 135 | IS_COMMUTATIVE(lic) && isOperandEqual(lleft, rright) && 136 | isOperandEqual(lright, rleft)) && 137 | (lresult && rresult && 138 | compareTypeInexact(operandType(lresult), operandType(rresult)) > 0)) 139 | return (true); 140 | 141 | return (false); 142 | } 143 | 144 | static void get_candidate_set(std::set *c, const iCode *const sic, 145 | int lkey) { 146 | // TODO: For loop invariant code motion allow expression that only occurs 147 | // once, too - will be needed when optimizing for speed. 148 | for (const iCode *ic = sic; ic; ic = ic->next) { 149 | if (!candidate_expression(ic, lkey)) 150 | continue; 151 | for (const iCode *pic = sic; pic != ic; pic = pic->next) 152 | if (candidate_expression(pic, lkey) && same_expression(ic, pic) && 153 | c->find(pic->key) == c->end()) { 154 | // Found expression that occurs at least twice. 155 | c->insert(pic->key); 156 | break; 157 | } 158 | } 159 | } 160 | 161 | static bool setup_cfg_for_expression(cfg_lospre_t *const cfg, 162 | const iCode *const eic) { 163 | typedef boost::graph_traits::vertex_descriptor vertex_t; 164 | const operand *const eleft = IC_LEFT(eic); 165 | const operand *const eright = IC_RIGHT(eic); 166 | const bool uses_global = 167 | (eic->op == GET_VALUE_AT_ADDRESS || isOperandGlobal(eleft) || 168 | isOperandGlobal(eright) || 169 | IS_SYMOP(eleft) && OP_SYMBOL_CONST(eleft)->addrtaken || 170 | IS_SYMOP(eright) && OP_SYMBOL_CONST(eright)->addrtaken); 171 | bool safety_required = false; 172 | 173 | // In redundancy elimination, safety means not doing a computation on any path 174 | // were it was not done before. This is important, if the compuation can have 175 | // side-effects, which depends on the target architecure. E.g. On some systems 176 | // division requires safety, since division by zero might result in an 177 | // interrupt. When there are memory-mapped devices or there is memory 178 | // management, reading from a pointer requires safety, since reading from an 179 | // unknown location could result in making the device do something or in a 180 | // SIGSEGV. On the other hand, addition is something that typically does not 181 | // require safety, since adding two undefined operands gives just another 182 | // undefined (the C standard allows trap representations, which, could result 183 | // in addition requiring safety though; AFAIK none of the targets currently 184 | // supported by sdcc have trap representations). Philipp, 2012-07-06. 185 | // 186 | // For now we just always require safety for "dangerous" operations. 187 | // 188 | // TODO: Replace the current one by a more exact mechanism, that takes into 189 | // account information from (not yet implemented) generalized constant 190 | // propagation, pointer analysis, etc. 191 | 192 | // Function calls can have any side effects. 193 | if (eic->op == CALL || eic->op == PCALL) 194 | safety_required = true; 195 | 196 | // Reading from an invalid address might be dangerous, since there could be 197 | // memory-mapped I/O. 198 | if (eic->op == GET_VALUE_AT_ADDRESS && !optimize.lospre_unsafe_read) 199 | safety_required = true; 200 | 201 | // TODO: Relax this! There are cases where allowing unsafe optimizations will 202 | // improve speed. This probably needs implementation of profile-guided 203 | // optimization though. 204 | if (optimize.codeSpeed) 205 | safety_required = true; 206 | 207 | for (vertex_t i = 0; i < boost::num_vertices(*cfg); i++) { 208 | const iCode *const ic = (*cfg)[i].ic; 209 | (*cfg)[i].uses = same_expression(eic, ic); 210 | (*cfg)[i].invalidates = false; 211 | if (IC_RESULT(ic) && !IS_OP_LITERAL(IC_RESULT(ic)) && !POINTER_SET(ic) && 212 | (eleft && isOperandEqual(eleft, IC_RESULT(ic)) || 213 | eright && isOperandEqual(eright, IC_RESULT(ic)))) 214 | (*cfg)[i].invalidates = true; 215 | if (ic->op == FUNCTION || ic->op == ENDFUNCTION || ic->op == RECEIVE) 216 | (*cfg)[i].invalidates = true; 217 | if (uses_global && (ic->op == CALL || ic->op == PCALL)) 218 | (*cfg)[i].invalidates = true; 219 | if (uses_global && POINTER_SET(ic)) // TODO: More accuracy here! 220 | (*cfg)[i].invalidates = true; 221 | 222 | (*cfg)[i].forward = std::pair(-1, -1); 223 | } 224 | 225 | return (safety_required); 226 | } 227 | 228 | // Dump cfg, with numbered nodes. 229 | void dump_cfg_lospre(const cfg_lospre_t &cfg) { 230 | if (!currFunc) 231 | return; 232 | 233 | std::ofstream dump_file( 234 | (std::string(dstFileName) + ".dumplosprecfg" + currFunc->rname + ".dot") 235 | .c_str()); 236 | 237 | std::string *name = new std::string[num_vertices(cfg)]; 238 | for (unsigned int i = 0; i < boost::num_vertices(cfg); i++) { 239 | const char *iLine = printILine(cfg[i].ic); 240 | std::ostringstream os; 241 | os << i << ", " << cfg[i].ic->key << " : " << iLine; 242 | dbuf_free(iLine); 243 | name[i] = os.str(); 244 | } 245 | boost::write_graphviz(dump_file, cfg, boost::make_label_writer(name)); 246 | delete[] name; 247 | } 248 | 249 | #if 0 250 | // Dump tree decomposition. 251 | static void dump_tree_decomposition(const tree_dec_lospre_t &tree_dec) 252 | { 253 | std::ofstream dump_file((std::string(dstFileName) + ".dumplospredec" + currFunc->rname + ".dot").c_str()); 254 | 255 | unsigned int w = 0; 256 | 257 | std::string *name = new std::string[num_vertices(tree_dec)]; 258 | for (unsigned int i = 0; i < boost::num_vertices(tree_dec); i++) 259 | { 260 | if (tree_dec[i].bag.size() > w) 261 | w = tree_dec[i].bag.size(); 262 | std::ostringstream os; 263 | std::set::const_iterator v1; 264 | os << i << " | "; 265 | for (v1 = tree_dec[i].bag.begin(); v1 != tree_dec[i].bag.end(); ++v1) 266 | os << *v1 << " "; 267 | name[i] = os.str(); 268 | } 269 | boost::write_graphviz(dump_file, tree_dec, boost::make_label_writer(name)); 270 | delete[] name; 271 | } 272 | #endif 273 | 274 | void lospre(iCode *sic, ebbIndex *ebbi) { 275 | cfg_lospre_t control_flow_graph; 276 | tree_dec_lospre_t tree_decomposition; 277 | 278 | wassert(sic); 279 | 280 | #ifdef DEBUG_LOSPRE 281 | if (currFunc) 282 | std::cout << "lospre for " << currFunc->rname << "()\n"; 283 | #endif 284 | 285 | create_cfg_lospre(control_flow_graph, sic, ebbi); 286 | 287 | if (options.dump_graphs) 288 | dump_cfg_lospre(control_flow_graph); 289 | 290 | thorup_tree_decomposition(tree_decomposition, control_flow_graph); 291 | nicify(tree_decomposition); 292 | 293 | int lkey = operandKey; 294 | 295 | for (bool change = true; change;) { 296 | change = false; 297 | 298 | std::set candidate_set; 299 | get_candidate_set(&candidate_set, sic, lkey); 300 | 301 | std::set::iterator ci, ci_end; 302 | for (ci = candidate_set.begin(), ci_end = candidate_set.end(); ci != ci_end; 303 | ++ci) { 304 | const iCode *ic; 305 | for (ic = sic; ic && ic->key != *ci; ic = ic->next) 306 | ; 307 | 308 | if (!ic || !candidate_expression(ic, lkey)) 309 | continue; 310 | 311 | bool safety = setup_cfg_for_expression(&control_flow_graph, ic); 312 | 313 | if (safety && 314 | tree_dec_safety(tree_decomposition, control_flow_graph, ic) < 0) 315 | continue; 316 | 317 | change |= 318 | (tree_dec_lospre(tree_decomposition, control_flow_graph, ic) > 0); 319 | } 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /src/SDCClrange.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCClrange.h - header file for live range computations 4 | 5 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | In other words, you are welcome to use, share and improve this program. 22 | You are forbidden to forbid anyone else to use, share and improve 23 | what you give them. Help stamp out software-hoarding! 24 | -------------------------------------------------------------------------*/ 25 | 26 | #ifndef SDCCLRANGE_H 27 | #define SDCCLRANGE_H 1 28 | 29 | extern hTab *liveRanges; 30 | extern hTab *iCodehTab; 31 | extern hTab *iCodeSeqhTab; 32 | 33 | int notUsedInBlock(symbol *, eBBlock *, iCode *); 34 | bool allDefsOutOfRange(bitVect *, int, int); 35 | void computeLiveRanges(eBBlock **ebbs, int count, bool emitWarnings); 36 | void recomputeLiveRanges(eBBlock **ebbs, int count, bool emitWarnings); 37 | 38 | void setToRange(operand *, int, bool); 39 | void hashiCodeKeys(eBBlock **, int); 40 | 41 | void adjustIChain(eBBlock **ebbs, int count); 42 | 43 | void separateLiveRanges( 44 | iCode *sic, 45 | ebbIndex *ebbi); /* Split iTemps that have non-connected live-ranges. */ 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/SDCCmacro.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCmain.c - Macro support code. 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | #include "common.h" 26 | #include "dbuf_string.h" 27 | 28 | char *eval_macros(hTab *pvals, const char *pfrom) { 29 | bool fdidsomething = FALSE; 30 | char quote = '\0'; 31 | struct dbuf_s dbuf; 32 | 33 | assert(pvals); 34 | assert(pfrom); 35 | 36 | dbuf_init(&dbuf, 256); 37 | while (*pfrom) { 38 | switch (*pfrom) { 39 | case '"': 40 | case '\'': 41 | if (quote != '\0') { 42 | /* write previous quote */ 43 | dbuf_append_char(&dbuf, quote); 44 | } 45 | quote = *pfrom++; 46 | break; 47 | 48 | case '{': { 49 | const char *pend = ++pfrom; 50 | const char *pval; 51 | char *name; 52 | 53 | /* Find the end of macro */ 54 | while (*pend && '}' != *pend) { 55 | pend++; 56 | } 57 | if ('}' != *pend) { 58 | wassertl(0, "Unterminated macro expansion"); 59 | } 60 | 61 | name = Safe_strndup(pfrom, pend - pfrom); 62 | 63 | /* Look up the value in the hash table */ 64 | pval = shash_find(pvals, name); 65 | Safe_free(name); 66 | 67 | if (NULL == pval) { 68 | /* Empty macro value */ 69 | if ('\0' != quote) { 70 | /* It was a quote */ 71 | if (pend[1] == quote) { 72 | /* Start quote equals end quote: skip both */ 73 | ++pend; 74 | } else { 75 | /* Start quote not equals end quote: add both */ 76 | dbuf_append_char(&dbuf, quote); 77 | } 78 | } 79 | } else { 80 | if ('\0' != quote) { 81 | dbuf_append_char(&dbuf, quote); 82 | } 83 | dbuf_append_str(&dbuf, pval); 84 | fdidsomething = TRUE; 85 | } 86 | 87 | quote = '\0'; 88 | pfrom = pend + 1; 89 | } break; 90 | 91 | default: 92 | if ('\0' != quote) { 93 | dbuf_append_char(&dbuf, quote); 94 | quote = '\0'; 95 | } 96 | 97 | dbuf_append_char(&dbuf, *pfrom++); 98 | } 99 | } 100 | 101 | if ('\0' != quote) { 102 | dbuf_append_char(&dbuf, quote); 103 | } 104 | 105 | /* If we did something then recursivly expand any expanded macros */ 106 | if (fdidsomething) { 107 | char *ret = eval_macros(pvals, dbuf_c_str(&dbuf)); 108 | dbuf_destroy(&dbuf); 109 | return ret; 110 | } 111 | 112 | return dbuf_detach_c_str(&dbuf); 113 | } 114 | 115 | char *mvsprintf(hTab *pvals, const char *pformat, va_list ap) { 116 | char *p; 117 | struct dbuf_s dbuf; 118 | 119 | dbuf_init(&dbuf, 256); 120 | 121 | /* Recursivly evaluate all the macros in the string */ 122 | p = eval_macros(pvals, pformat); 123 | 124 | /* Evaluate all the arguments */ 125 | dbuf_vprintf(&dbuf, p, ap); 126 | Safe_free(p); 127 | 128 | /* Recursivly evaluate any macros that were used as arguments */ 129 | p = eval_macros(pvals, dbuf_c_str(&dbuf)); 130 | dbuf_destroy(&dbuf); 131 | return p; 132 | } 133 | 134 | char *msprintf(hTab *pvals, const char *pformat, ...) { 135 | va_list ap; 136 | char *pret; 137 | 138 | va_start(ap, pformat); 139 | 140 | pret = mvsprintf(pvals, pformat, ap); 141 | 142 | va_end(ap); 143 | 144 | return pret; 145 | } 146 | 147 | void mfprintf(FILE *fp, hTab *pvals, const char *pformat, ...) { 148 | va_list ap; 149 | char *p; 150 | 151 | va_start(ap, pformat); 152 | 153 | p = mvsprintf(pvals, pformat, ap); 154 | 155 | va_end(ap); 156 | 157 | fputs(p, fp); 158 | Safe_free(p); 159 | } 160 | -------------------------------------------------------------------------------- /src/SDCCmacro.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | SDCChast.h - contains support routines for hashtables/sets . 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | #ifndef SDCCMACRO_H 26 | #define SDCCMACRO_H 27 | 28 | #include "SDCChasht.h" 29 | #include 30 | #include 31 | 32 | char *eval_macros(hTab *pvals, const char *pfrom); 33 | char *mvsprintf(hTab *pvals, const char *pformat, va_list ap); 34 | char *msprintf(hTab *pvals, const char *pformat, ...); 35 | void mfprintf(FILE *fp, hTab *pvals, const char *pformat, ...); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/SDCCmem.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------*/ 2 | /* SDCCmem.h - header file for memory management */ 3 | /*-----------------------------------------------------------------*/ 4 | 5 | #ifndef SDCCMEM_H 6 | #define SDCCMEM_H 7 | 8 | #include "dbuf.h" 9 | 10 | struct set; 11 | struct value; 12 | struct eBBlock; 13 | 14 | typedef struct memmap { 15 | unsigned char pageno; /* page no for this variable */ 16 | const char *sname; /* character prefix for map */ 17 | char dbName; /* debugger address space name */ 18 | int ptrType; /* pointer Type for this space */ 19 | int slbl; /* label counter for space */ 20 | unsigned sloc; /* starting location */ 21 | unsigned fmap : 1; /* 1 = 16bit addressing reqd */ 22 | unsigned paged : 1; /* this is a paged mem space */ 23 | unsigned direct : 1; /* 1 = indirect access only */ 24 | unsigned bitsp : 1; /* 1 = bit addressable space */ 25 | unsigned codesp : 1; /* 1 = code space */ 26 | unsigned regsp : 1; /* 1 = sfr space */ 27 | struct dbuf_s oBuf; /* object buffer associated */ 28 | struct set *syms; /* symbols defined in this segment */ 29 | } memmap; 30 | 31 | /* For performance we might want to use a hash map instead of the linked list */ 32 | typedef struct namedspacemap { 33 | char *name; 34 | bool is_const; 35 | memmap *map; 36 | struct namedspacemap *next; 37 | } namedspacemap; 38 | 39 | extern FILE *junkFile; 40 | 41 | /* memory map prefixes MOF added the DATA,CODE,XDATA,BIT */ 42 | #define XSTACK_NAME port->mem.xstack_name 43 | #define ISTACK_NAME port->mem.istack_name 44 | #define CODE_NAME port->mem.code_name 45 | #define DATA_NAME port->mem.data_name 46 | #define INITIALIZED_NAME port->mem.initialized_name 47 | #define INITIALIZER_NAME port->mem.initializer_name 48 | #define IDATA_NAME port->mem.idata_name 49 | #define PDATA_NAME port->mem.pdata_name 50 | #define XDATA_NAME port->mem.xdata_name 51 | #define XIDATA_NAME port->mem.xidata_name 52 | #define XINIT_NAME port->mem.xinit_name 53 | #define BIT_NAME port->mem.bit_name 54 | #define REG_NAME port->mem.reg_name 55 | #define STATIC_NAME port->mem.static_name 56 | #define HOME_NAME port->mem.home_name 57 | #define OVERLAY_NAME port->mem.overlay_name 58 | #define CONST_NAME port->mem.const_name 59 | #define CABS_NAME port->mem.cabs_name 60 | #define XABS_NAME port->mem.xabs_name 61 | #define IABS_NAME port->mem.iabs_name 62 | 63 | /* forward definition for variables */ 64 | extern memmap *xstack; /* xternal stack data */ 65 | extern memmap *istack; /* internal stack */ 66 | extern memmap *code; /* code segment */ 67 | extern memmap *data; /* internal data upto 128 */ 68 | extern memmap *initialized; /* initialized data, such as initalized, nonzero 69 | globals or local statics. */ 70 | extern memmap *initializer; /* a copy of the values for the initalized data from 71 | initialized in code space */ 72 | extern memmap *pdata; /* paged external data upto 256 */ 73 | extern memmap *xdata; /* external data */ 74 | extern memmap *xidata; /* the initialized xdata */ 75 | extern memmap *xinit; /* the initializers for xidata */ 76 | extern memmap *idata; /* internal data upto 256 */ 77 | extern memmap *bit; /* bit addressable space */ 78 | extern memmap *statsg; /* static code segment */ 79 | extern memmap *c_abs; /* constant absolute data */ 80 | extern memmap *x_abs; /* absolute xdata/pdata */ 81 | extern memmap *i_abs; /* absolute idata upto 256 */ 82 | extern memmap *d_abs; /* absolute data upto 128 */ 83 | extern memmap *sfr; /* register space */ 84 | extern memmap *sfrbit; /* sfr bit space */ 85 | extern memmap *reg; /* register space */ 86 | extern memmap *generic; /* unknown */ 87 | extern memmap *overlay; /* the overlay segment */ 88 | extern memmap *eeprom; /* eeprom space */ 89 | extern memmap *home; /* Non-banked home space */ 90 | 91 | extern namedspacemap *namedspacemaps; 92 | 93 | extern int fatalError; 94 | 95 | extern struct set *ovrSetSets; 96 | 97 | /* easy access macros */ 98 | #define IN_BITSPACE(map) (map && map->bitsp) 99 | #define IN_STACK(x) \ 100 | (IS_SPEC(x) && (SPEC_OCLS(x) == xstack || SPEC_OCLS(x) == istack)) 101 | #define IN_FARSPACE(map) (map && map->fmap) 102 | #define IN_DIRSPACE(map) (map && map->direct) 103 | #define IN_PAGEDSPACE(map) (map && map->paged) 104 | #define IN_CODESPACE(map) (map && map->codesp) 105 | #define IN_REGSP(map) (map && map->regsp) 106 | #define PTR_TYPE(map) \ 107 | (map ? (map->ptrType ? map->ptrType : POINTER) : port->unqualified_pointer) 108 | 109 | /* forward decls for functions */ 110 | memmap *allocMap(char, char, char, char, char, char, unsigned, const char *, 111 | char, int); 112 | void initMem(); 113 | bool defaultOClass(struct symbol *); 114 | void allocGlobal(struct symbol *); 115 | void allocLocal(struct symbol *); 116 | void allocParms(struct value *); 117 | void deallocParms(struct value *); 118 | void deallocLocal(struct symbol *); 119 | int allocVariables(struct symbol *); 120 | void overlay2Set(); 121 | void overlay2data(); 122 | void redoStackOffsets(); 123 | void printAllocInfo(struct symbol *, struct dbuf_s *); 124 | void doOverlays(struct eBBlock **, int count); 125 | void deleteFromSeg(struct symbol *); 126 | #endif 127 | -------------------------------------------------------------------------------- /src/SDCCnaddr.cc: -------------------------------------------------------------------------------- 1 | // Philipp Klaus Krause, philipp@informatik.uni-frankfurt.de, pkk@spth.de, 2011 2 | // 3 | // (c) 2011 Goethe-Universität Frankfurt 4 | // 5 | // This program is free software; you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by the 7 | // Free Software Foundation; either version 2, or (at your option) any 8 | // later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program; if not, write to the Free Software 17 | // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | // 19 | // 20 | // Optimal placement of bank switching instructions for named address spaces. 21 | 22 | #include "SDCCnaddr.hpp" 23 | 24 | // A quick-and-dirty function to get the CFG from sdcc (a simplified version of 25 | // the function from SDCCralloc.hpp). 26 | void create_cfg_naddr(cfg_t &cfg, iCode *start_ic, ebbIndex *ebbi) { 27 | iCode *ic; 28 | 29 | std::map key_to_index; 30 | { 31 | int i; 32 | 33 | for (ic = start_ic, i = 0; ic; ic = ic->next, i++) { 34 | boost::add_vertex(cfg); 35 | key_to_index[ic->key] = i; 36 | cfg[i].ic = ic; 37 | } 38 | } 39 | 40 | // Get control flow graph from sdcc. 41 | for (ic = start_ic; ic; ic = ic->next) { 42 | if (ic->op != GOTO && ic->op != RETURN && ic->op != JUMPTABLE && ic->next) 43 | boost::add_edge(key_to_index[ic->key], key_to_index[ic->next->key], 3.0f, 44 | cfg); 45 | 46 | if (ic->op == GOTO) 47 | boost::add_edge( 48 | key_to_index[ic->key], 49 | key_to_index[eBBWithEntryLabel(ebbi, ic->label)->sch->key], 6.0f, 50 | cfg); 51 | else if (ic->op == RETURN) 52 | boost::add_edge( 53 | key_to_index[ic->key], 54 | key_to_index[eBBWithEntryLabel(ebbi, returnLabel)->sch->key], 6.0f, 55 | cfg); 56 | else if (ic->op == IFX) 57 | boost::add_edge( 58 | key_to_index[ic->key], 59 | key_to_index[eBBWithEntryLabel(ebbi, IC_TRUE(ic) ? IC_TRUE(ic) 60 | : IC_FALSE(ic)) 61 | ->sch->key], 62 | 6.0f, cfg); 63 | else if (ic->op == JUMPTABLE) 64 | for (symbol *lbl = (symbol *)(setFirstItem(IC_JTLABELS(ic))); lbl; 65 | lbl = (symbol *)(setNextItem(IC_JTLABELS(ic)))) 66 | boost::add_edge(key_to_index[ic->key], 67 | key_to_index[eBBWithEntryLabel(ebbi, lbl)->sch->key], 68 | 6.0f, cfg); 69 | } 70 | } 71 | 72 | int switchAddressSpacesOptimally(iCode *ic, ebbIndex *ebbi) { 73 | cfg_t control_flow_graph; 74 | tree_dec_naddr_t tree_decomposition; 75 | std::map addrspaces; 76 | 77 | create_cfg_naddr(control_flow_graph, ic, ebbi); 78 | annotate_cfg_naddr(control_flow_graph, addrspaces); 79 | 80 | if (options.dump_graphs) 81 | dump_cfg_naddr(control_flow_graph); 82 | 83 | thorup_tree_decomposition(tree_decomposition, control_flow_graph); 84 | nicify(tree_decomposition); 85 | 86 | return (tree_dec_address_switch(tree_decomposition, control_flow_graph, 87 | addrspaces)); 88 | } 89 | -------------------------------------------------------------------------------- /src/SDCCopt.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCopt.h - header file for Optimizations 4 | 5 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | In other words, you are welcome to use, share and improve this program. 22 | You are forbidden to forbid anyone else to use, share and improve 23 | what you give them. Help stamp out software-hoarding! 24 | -------------------------------------------------------------------------*/ 25 | #include "SDCCBBlock.h" 26 | 27 | #ifndef SDCCOPT_H 28 | #define SDCCOPT_H 1 29 | 30 | /*----------------------------------------------------------------------------*/ 31 | eBBlock **eBBlockFromiCode(iCode *); 32 | void printEbbs(eBBlock **); 33 | iCode *iCodeLabelOptimize(iCode *); 34 | eBBlock *iCode2eBBlock(iCode *ic); 35 | void lospre(iCode *ic, ebbIndex *ebbi); 36 | int switchAddressSpacesOptimally(iCode *ic, ebbIndex *ebbi); 37 | const symbol *getAddrspaceiCode(const iCode *ic); 38 | void switchAddressSpaceAt(iCode *ic, const symbol *const addrspace); 39 | bool isPowerOf2(unsigned long val); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/SDCCpeeph.awk: -------------------------------------------------------------------------------- 1 | BEGIN { 2 | print "/* Generated file, DO NOT Edit! */" 3 | print "/* To Make changes to rules edit */" 4 | print "/* /peeph.def instead. */" 5 | } 6 | 7 | /^\/\// { next} 8 | 9 | { printf "\"" ; 10 | printf "%s",$0; 11 | print "\\n\""; 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/SDCCpeeph.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCpeeph.h - Header file for The peep hole optimizer: for interpreting 3 | the peep hole rules 4 | 5 | Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | -------------------------------------------------------------------------*/ 21 | 22 | #ifndef SDCCPEEPH_H 23 | #define SDCCPEEPH_H 1 24 | 25 | #include "SDCCgen.h" 26 | 27 | #define MAX_PATTERN_LEN 256 28 | 29 | typedef struct peepRule { 30 | lineNode *match; 31 | lineNode *replace; 32 | unsigned int restart : 1; 33 | unsigned int barrier : 1; 34 | char *cond; 35 | hTab *vars; 36 | struct peepRule *next; 37 | } peepRule; 38 | 39 | typedef struct { 40 | char name[SDCC_NAME_MAX + 1]; 41 | int refCount; 42 | /* needed for deadMove: */ 43 | bool passedLabel; 44 | int jmpToCount; 45 | } labelHashEntry; 46 | 47 | bool isLabelDefinition(const char *line, const char **start, int *len, 48 | bool isPeepRule); 49 | 50 | extern hTab *labelHash; 51 | labelHashEntry *getLabelRef(const char *label, lineNode *head); 52 | 53 | void initPeepHole(void); 54 | void peepHole(lineNode **); 55 | 56 | const char *StrStr(const char *str1, const char *str2); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/SDCCptropt.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCptropt.h - header file for pointer arithmetic Optimizations 4 | 5 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | In other words, you are welcome to use, share and improve this program. 22 | You are forbidden to forbid anyone else to use, share and improve 23 | what you give them. Help stamp out software-hoarding! 24 | -------------------------------------------------------------------------*/ 25 | 26 | #ifndef SDCCPTROPT_H 27 | #define SDCCPTROPT_H 1 28 | 29 | void ptrPostIncDecOpt(iCode *); 30 | int ptrAddition(iCode *); 31 | symbol *ptrBaseRematSym(symbol *); 32 | int ptrPseudoSymSafe(symbol *, iCode *); 33 | void ptrPseudoSymConvert(symbol *, iCode *, const char *); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/SDCCset.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | SDCCset.h - contains support routines for sets . 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | #ifndef SDCCSET_H 26 | #define SDCCSET_H 27 | #include 28 | 29 | #ifndef THROWS 30 | #define THROWS 31 | #define THROW_NONE 0 32 | #define THROW_SRC 1 33 | #define THROW_DEST 2 34 | #define THROW_BOTH 3 35 | #endif 36 | 37 | /* linear linked list generic */ 38 | typedef struct set { 39 | void *item; 40 | struct set *curr; 41 | struct set *next; 42 | } set; 43 | 44 | #define DEFSETFUNC(fname) int fname(void *item, va_list ap) 45 | #define V_ARG(type, var) type var = va_arg(ap, type) 46 | 47 | /* set related functions */ 48 | set *newSet(void); 49 | void *addSet(set **, void *); 50 | void *addSetHead(set **, void *); 51 | void *getSet(set **); 52 | void deleteSetItem(set **, void *); 53 | void deleteItemIf(set **, int (*cond)(void *, va_list), ...); 54 | int isinSet(const set *, const void *); 55 | typedef int (*insetwithFunc)(void *, void *); 56 | int isinSetWith(set *, void *, insetwithFunc cfunc); 57 | int applyToSet(set *list, int (*somefunc)(void *, va_list), ...); 58 | int applyToSetFTrue(set *list, int (*somefunc)(void *, va_list), ...); 59 | void mergeSets(set **sset, set *list); 60 | set *unionSets(set *, set *, int); 61 | set *unionSetsWith(set *, set *, int (*cFunc)(), int); 62 | set *intersectSets(set *, set *, int); 63 | void *addSetIfnotP(set **, void *); 64 | set *setFromSet(const set *); 65 | set *setFromSetNonRev(const set *); 66 | int isSetsEqual(const set *, const set *); 67 | set *subtractFromSet(set *, set *, int); 68 | int elementsInSet(const set *); 69 | void *indexSet(set *, int); 70 | set *intersectSetsWith(set *, set *, int (*cFunc)(void *, void *), int); 71 | int isSetsEqualWith(set *, set *, int (*cFunc)(void *, void *)); 72 | void *peekSet(const set *); 73 | void *setFirstItem(set *); 74 | void *setNextItem(set *); 75 | void setToNull(void **); 76 | set *reverseSet(set *); 77 | void deleteSet(set **s); 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/SDCCsystem.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCsystem - SDCC system & pipe functions 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | #ifdef _WIN32 26 | /* avoid DATADIR definition clash :-( */ 27 | #undef DATADIR 28 | #include 29 | #undef TRUE 30 | #undef FALSE 31 | #include 32 | #include 33 | #else 34 | #include 35 | #endif 36 | 37 | #include "SDCCglobl.h" 38 | #include "SDCCsystem.h" 39 | #include "SDCCutil.h" 40 | #include "dbuf_string.h" 41 | #include "newalloc.h" 42 | #include 43 | #include 44 | #include 45 | 46 | set *binPathSet = NULL; /* set of binary paths */ 47 | 48 | /*! 49 | * get command and arguments from command line 50 | */ 51 | 52 | static void split_command(const char *cmd_line, char **command, char **params) { 53 | const char *p, *cmd_start; 54 | char delim; 55 | char *str; 56 | unsigned len; 57 | 58 | /* skip leading spaces */ 59 | for (p = cmd_line; isspace(*p); p++) 60 | ; 61 | 62 | /* get command */ 63 | switch (*p) { 64 | case '\'': 65 | case '"': 66 | delim = *p; 67 | cmd_start = ++p; 68 | break; 69 | 70 | default: 71 | delim = ' '; 72 | cmd_start = p; 73 | } 74 | 75 | if (delim == ' ') { 76 | while (*p != '\0' && !isspace(*p)) 77 | p++; 78 | } else { 79 | while (*p != '\0' && *p != delim) 80 | p++; 81 | } 82 | 83 | if (command != NULL) { 84 | len = p - cmd_start; 85 | str = Safe_alloc(len + 1); 86 | strncpy(str, cmd_start, len); 87 | str[len] = '\0'; 88 | *command = str; 89 | } 90 | 91 | p++; 92 | 93 | /* skip spaces before parameters */ 94 | while (isspace(*p)) 95 | p++; 96 | 97 | /* get parameters */ 98 | if (params != NULL) 99 | *params = Safe_strdup(p); 100 | } 101 | 102 | /*! 103 | * find the command: 104 | * 1) if the command is specified by path, try it 105 | * 2) try to find the command in predefined path's 106 | * 3) trust on $PATH 107 | */ 108 | 109 | #ifdef _WIN32 110 | /* WIN32 version */ 111 | 112 | /* 113 | * I don't like this solution, but unfortunately cmd.exe and command.com 114 | * don't accept something like this: 115 | * "program" "argument" 116 | * Cmd.exe accepts the following: 117 | * ""program" "argument"" 118 | * but command.com doesn't. 119 | * The following is accepted by both: 120 | * program "argument" 121 | * 122 | * So the most portable WIN32 solution is to use GetShortPathName() for 123 | * program to get rid of spaces, so that quotes are not needed :-( 124 | * Using spawnvp() instead of system() is more portable cross platform approach, 125 | * but then also a substitute for _popen() should be developed... 126 | */ 127 | 128 | #define EXE_EXT ".exe" 129 | 130 | /*! 131 | * merge command and parameters to command line 132 | */ 133 | 134 | static const char *merge_command(const char *command, const char *params) { 135 | struct dbuf_s dbuf; 136 | 137 | /* allocate extra space for ' ' and '\0' */ 138 | dbuf_init(&dbuf, strlen(command) + strlen(params) + 2); 139 | 140 | dbuf_append_str(&dbuf, command); 141 | dbuf_append(&dbuf, " ", 1); 142 | dbuf_append_str(&dbuf, params); 143 | 144 | return dbuf_detach_c_str(&dbuf); 145 | } 146 | 147 | /*! 148 | * check if path/command exist by converting it to short file name 149 | * if it exists, compose with args and return it 150 | */ 151 | 152 | static const char *compose_command_line(const char *path, const char *command, 153 | const char *args) { 154 | unsigned len; 155 | struct dbuf_s cmdPath; 156 | char shortPath[PATH_MAX]; 157 | 158 | dbuf_init(&cmdPath, PATH_MAX); 159 | 160 | if (path != NULL) 161 | dbuf_makePath(&cmdPath, path, command); 162 | else 163 | dbuf_append_str(&cmdPath, command); 164 | 165 | /* Try if cmdPath or cmdPath.exe exist by converting it to the short path name 166 | */ 167 | len = GetShortPathName(dbuf_c_str(&cmdPath), shortPath, sizeof shortPath); 168 | assert(len < sizeof shortPath); 169 | if (0 == len) { 170 | dbuf_append_str(&cmdPath, EXE_EXT); 171 | len = GetShortPathName(dbuf_c_str(&cmdPath), shortPath, sizeof shortPath); 172 | assert(len < sizeof shortPath); 173 | } 174 | if (0 != len) { 175 | /* compose the command line */ 176 | return merge_command(shortPath, args); 177 | } else { 178 | /* path/command not found */ 179 | return NULL; 180 | } 181 | } 182 | 183 | static const char *get_path(const char *cmd) { 184 | const char *cmdLine; 185 | char *command; 186 | char *args; 187 | char *path; 188 | 189 | /* get the command */ 190 | split_command(cmd, &command, &args); 191 | 192 | if (NULL == (cmdLine = compose_command_line(NULL, command, args))) { 193 | /* not an absolute path: try to find the command in predefined binary paths 194 | */ 195 | if (NULL != (path = (char *)setFirstItem(binPathSet))) { 196 | while (NULL == (cmdLine = compose_command_line(path, command, args)) && 197 | NULL != (path = (char *)setNextItem(binPathSet))) 198 | ; 199 | } 200 | 201 | if (NULL == cmdLine) { 202 | /* didn't found the command in predefined binary paths: try with PATH */ 203 | char *envPath; 204 | 205 | if (NULL != (envPath = getenv("PATH"))) { 206 | /* make a local copy; strtok() will modify it */ 207 | envPath = Safe_strdup(envPath); 208 | 209 | if (NULL != (path = strtok(envPath, ";"))) { 210 | while (NULL == 211 | (cmdLine = compose_command_line(path, command, args)) && 212 | NULL != (path = strtok(NULL, ";"))) 213 | ; 214 | } 215 | 216 | Safe_free(envPath); 217 | } 218 | } 219 | 220 | /* didn't found it; probably this won't help neither :-( */ 221 | if (NULL == cmdLine) 222 | cmdLine = merge_command(command, args); 223 | } 224 | 225 | Safe_free(command); 226 | Safe_free(args); 227 | 228 | return cmdLine; 229 | } 230 | 231 | #else 232 | /* *nix version */ 233 | 234 | /*! 235 | * merge command and parameters to command line 236 | */ 237 | 238 | static const char *merge_command(const char *command, const char *params) { 239 | struct dbuf_s dbuf; 240 | char *s = shell_escape(command); 241 | 242 | /* allocate extra space for ' ' and '\0' */ 243 | dbuf_init(&dbuf, strlen(command) + strlen(params) + 2); 244 | 245 | dbuf_append_str(&dbuf, s); 246 | dbuf_append(&dbuf, " ", 1); 247 | dbuf_append_str(&dbuf, params); 248 | 249 | return dbuf_detach_c_str(&dbuf); 250 | } 251 | 252 | /*! 253 | * check if the path is relative or absolute (if contains the dir separator) 254 | */ 255 | 256 | static int has_path(const char *path) { 257 | return dbuf_splitPath(path, NULL, NULL); 258 | } 259 | 260 | static const char *get_path(const char *cmd) { 261 | const char *cmdLine = NULL; 262 | char *command; 263 | char *args; 264 | char *path; 265 | 266 | /* get the command */ 267 | split_command(cmd, &command, &args); 268 | 269 | if (!has_path(command)) { 270 | /* try to find the command in predefined binary paths */ 271 | if (NULL != (path = (char *)setFirstItem(binPathSet))) { 272 | do { 273 | struct dbuf_s dbuf; 274 | const char *cmdPath; 275 | 276 | dbuf_init(&dbuf, PATH_MAX); 277 | dbuf_makePath(&dbuf, path, command); 278 | cmdPath = dbuf_detach(&dbuf); 279 | 280 | /* Try if cmdPath */ 281 | if (0 == access(cmdPath, X_OK)) { 282 | /* compose the command line */ 283 | cmdLine = merge_command(cmdPath, args); 284 | break; 285 | } 286 | } while (NULL != (path = (char *)setNextItem(binPathSet))); 287 | } 288 | if (NULL == cmdLine) 289 | cmdLine = merge_command(command, args); 290 | 291 | Safe_free(command); 292 | Safe_free(args); 293 | 294 | return cmdLine; 295 | } else { 296 | /* 297 | * the command is defined with absolute path: 298 | * just return it 299 | */ 300 | Safe_free(command); 301 | Safe_free(args); 302 | 303 | return Safe_strdup(cmd); 304 | } 305 | } 306 | #endif 307 | 308 | /*! 309 | * call an external program with arguements 310 | */ 311 | 312 | int sdcc_system(const char *cmd) { 313 | int e; 314 | const char *cmdLine = get_path(cmd); 315 | 316 | assert(NULL != cmdLine); 317 | 318 | if (options.verboseExec) 319 | printf("+ %s\n", cmdLine); 320 | 321 | e = system(cmdLine); 322 | 323 | if (options.verboseExec && e) 324 | printf("+ %s returned errorcode %d\n", cmdLine, e); 325 | 326 | dbuf_free(cmdLine); 327 | 328 | return e; 329 | } 330 | 331 | /*! 332 | * pipe an external program with arguements 333 | */ 334 | 335 | #ifdef _WIN32 336 | #define sdcc_popen_read(cmd) _popen((cmd), "rt") 337 | int sdcc_pclose(FILE *fp) { return _pclose(fp); } 338 | #else 339 | #define sdcc_popen_read(cmd) popen((cmd), "r") 340 | int sdcc_pclose(FILE *fp) { return pclose(fp); } 341 | #endif 342 | 343 | FILE *sdcc_popen(const char *cmd) { 344 | FILE *fp; 345 | const char *cmdLine = get_path(cmd); 346 | 347 | assert(NULL != cmdLine); 348 | 349 | if (options.verboseExec) { 350 | printf("+ %s\n", cmdLine); 351 | } 352 | 353 | fp = sdcc_popen_read(cmdLine); 354 | dbuf_free(cmdLine); 355 | 356 | return fp; 357 | } 358 | -------------------------------------------------------------------------------- /src/SDCCsystem.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCsystem - SDCC system & pipe functions 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | #ifndef SDCCSYSTEM_H 26 | #define SDCCSYSTEM_H 27 | 28 | #include "SDCCset.h" 29 | #include 30 | 31 | extern set *binPathSet; /* set of binary paths */ 32 | 33 | int sdcc_system(const char *cmd); 34 | FILE *sdcc_popen(const char *cmd); 35 | int sdcc_pclose(FILE *fp); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/SDCCutil.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCutil.c - Small utility functions. 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | #ifndef SDCCUTIL_H 26 | #define SDCCUTIL_H 27 | 28 | #include "SDCChasht.h" 29 | #include "SDCCset.h" 30 | #include "sdccconf.h" 31 | #include "util/dbuf.h" 32 | #include 33 | #include 34 | #include 35 | 36 | /** Given an array of name, value string pairs creates a new hash 37 | * containing all of the pairs. 38 | */ 39 | hTab *populateStringHash(const char **pin); 40 | 41 | /** Given an array of name, value string pairs creates a new hash 42 | * containing all of the pairs. 43 | */ 44 | char *shell_escape(const char *str); 45 | 46 | /** Prints elements of the set to the file, each element on new line 47 | */ 48 | void fputStrSet(FILE *fp, set *list); 49 | 50 | /** Prepend / append given strings to each item of string set. The result is in 51 | * a new string set. 52 | */ 53 | set *processStrSet(set *list, const char *pre, const char *post, 54 | char *(*file)(const char *)); 55 | 56 | /** Given a set returns a string containing all of the strings seperated 57 | * by spaces. The returned string is on the heap. 58 | */ 59 | const char *joinStrSet(set *list); 60 | 61 | /** Split the path string to the directory and file name (including extension) 62 | * components. The directory component doesn't contain trailing directory 63 | * separator. Returns true if the path contains the directory separator. 64 | */ 65 | int dbuf_splitPath(const char *path, struct dbuf_s *dir, struct dbuf_s *file); 66 | 67 | /** Split the path string to the file name (including directory) and file 68 | * extension components. The file name component doesn't contain trailing 69 | * extension separator. Returns true if the path contains the extension 70 | * separator. 71 | */ 72 | int dbuf_splitFile(const char *path, struct dbuf_s *file, struct dbuf_s *ext); 73 | 74 | /** Combile directory and the file name to a path string using the 75 | * DIR_SEPARATOR_CHAR. 76 | */ 77 | void dbuf_makePath(struct dbuf_s *path, const char *dir, const char *file); 78 | 79 | /** Given a file with path information in the binary files directory, 80 | * returns the directory component. Used for discovery of bin 81 | * directory of SDCC installation. Returns NULL if the path is 82 | * impossible. 83 | */ 84 | const char *getBinPath(const char *prel); 85 | 86 | /** Returns true if the given path exists. 87 | */ 88 | bool pathExists(const char *ppath); 89 | 90 | void setMainValue(const char *pname, const char *pvalue); 91 | 92 | char *buildMacros(const char *cmd); 93 | 94 | void populateMainValues(const char **ppin); 95 | 96 | char *buildCmdLine(const char **cmds, const char *p1, const char *p2, 97 | const char *p3, set *list); 98 | 99 | char *buildCmdLine2(const char *pcmd, ...); 100 | 101 | /** Returns true if sz starts with the string given in key. 102 | */ 103 | bool startsWith(const char *sz, const char *key); 104 | 105 | /** Removes any newline characters from the string. 106 | * Not strictly the same as perl's chomp. 107 | */ 108 | void chomp(char *sz); 109 | 110 | hTab *getRuntimeVariables(void); 111 | 112 | /* strncpy() with guaranteed NULL termination. 113 | */ 114 | char *strncpyz(char *dest, const char *src, size_t n); 115 | 116 | /* like strncat() with guaranteed NULL termination 117 | * The passed size should be the size of the dest buffer, not the number of 118 | * bytes to copy. 119 | */ 120 | char *strncatz(char *dest, const char *src, size_t n); 121 | 122 | /* return SDCC build date 123 | */ 124 | const char *getBuildDate(void); 125 | 126 | /* return environment used to build SDCC 127 | */ 128 | const char *getBuildEnvironment(void); 129 | 130 | /** snprintf, by hook or by crook. 131 | */ 132 | size_t SDCCsnprintf(char *, size_t, const char *, ...); 133 | 134 | #if defined(HAVE_VSNPRINTF) 135 | 136 | /* best option: we can define our own snprintf which logs errors. 137 | */ 138 | #define SNPRINTF SDCCsnprintf 139 | 140 | #elif defined(HAVE_SPRINTF) 141 | 142 | /* if we can't build a safe snprintf for lack of vsnprintf but there 143 | * is a native snprintf, use it. 144 | */ 145 | #define SNPRINTF snprintf 146 | 147 | #elif defined(HAVE_VSPRINTF) 148 | 149 | /* we can at least define our own unsafe version. 150 | */ 151 | #define SNPRINTF SDCCsnprintf 152 | 153 | #else 154 | /* We don't have a native snprintf nor the functions we need to write one. 155 | */ 156 | #error "Need at least one of snprintf, vsnprintf, vsprintf!" 157 | #endif 158 | 159 | /** Pragma tokenizer 160 | */ 161 | enum pragma_token_e { TOKEN_UNKNOWN, TOKEN_STR, TOKEN_INT, TOKEN_EOL }; 162 | 163 | struct pragma_token_s { 164 | enum pragma_token_e type; 165 | struct dbuf_s dbuf; 166 | union { 167 | int int_val; 168 | } val; 169 | }; 170 | 171 | void init_pragma_token(struct pragma_token_s *token); 172 | char *get_pragma_token(const char *s, struct pragma_token_s *token); 173 | const char *get_pragma_string(struct pragma_token_s *token); 174 | void free_pragma_token(struct pragma_token_s *token); 175 | 176 | unsigned char hexEscape(const char **src); 177 | unsigned char universalEscape(const char **src, unsigned int n); 178 | unsigned char octalEscape(const char **src); 179 | const char *copyStr(const char *src, size_t *size); 180 | 181 | #endif 182 | -------------------------------------------------------------------------------- /src/SDCCval.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | SDCCval.h - value wrapper related header information 3 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1997) 4 | 5 | This program is free software; you can redistribute it and/or modify it 6 | under the terms of the GNU General Public License as published by the 7 | Free Software Foundation; either version 2, or (at your option) any 8 | later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | 19 | In other words, you are welcome to use, share and improve this program. 20 | You are forbidden to forbid anyone else to use, share and improve 21 | what you give them. Help stamp out software-hoarding! 22 | -------------------------------------------------------------------------*/ 23 | #ifndef SDCCVAL_H 24 | #define SDCCVAL_H 25 | 26 | #include "SDCCsymt.h" 27 | 28 | /* value wrapper */ 29 | typedef struct value { 30 | char name[SDCC_NAME_MAX + 1]; /* operand accessing this value */ 31 | sym_link *type; /* start of type chain */ 32 | sym_link *etype; /* end of type chain */ 33 | symbol *sym; /* Original Symbol */ 34 | struct value *next; /* used in initializer list */ 35 | unsigned vArgs : 1; /* arg list ended with variable arg */ 36 | } value; 37 | 38 | typedef struct literalList { 39 | double literalValue; 40 | unsigned count; 41 | struct literalList *next; 42 | } literalList; 43 | 44 | enum { INIT_NODE, INIT_DEEP, INIT_HOLE }; 45 | 46 | /* initializer lists use this structure */ 47 | typedef struct initList { 48 | int type; 49 | int lineno; 50 | char *filename; 51 | struct designation *designation; 52 | union { 53 | struct ast *node; 54 | struct initList *deep; 55 | } init; 56 | 57 | struct initList *next; 58 | } initList; 59 | 60 | enum { DESIGNATOR_STRUCT, DESIGNATOR_ARRAY }; 61 | 62 | /* designated initializers */ 63 | typedef struct designation { 64 | int type; 65 | int lineno; 66 | char *filename; 67 | union { 68 | struct symbol *tag; /* tag part of structure */ 69 | int elemno; /* array element (constant expr) */ 70 | } designator; 71 | 72 | struct designation *next; /* next part of nested designator */ 73 | } designation; 74 | 75 | /* return values from checkConstantRange */ 76 | typedef enum { 77 | CCR_OK, /* evaluate at runtime */ 78 | CCR_OVL, 79 | CCR_ALWAYS_FALSE, 80 | CCR_ALWAYS_TRUE 81 | } CCR_RESULT; 82 | 83 | #define IS_VARG(x) (x->vArgs) 84 | 85 | /* forward definitions for the symbol table related functions */ 86 | value *newValue(void); 87 | value *constVal(const char *); 88 | value *constCharVal(unsigned char); 89 | value *constBoolVal(bool v); 90 | value *reverseVal(value *); 91 | value *reverseValWithType(value *); 92 | value *copyValue(value *); 93 | value *copyValueChain(value *); 94 | value *strVal(const char *); 95 | value *charVal(const char *); 96 | value *symbolVal(symbol *); 97 | void printVal(value *); 98 | double floatFromVal(value *); 99 | unsigned long ulFromVal(value *); 100 | 101 | /* convert a fixed16x16 type to double */ 102 | double doubleFromFixed16x16(TYPE_TARGET_ULONG value); 103 | 104 | /* convert a double type to fixed16x16 */ 105 | TYPE_TARGET_ULONG fixed16x16FromDouble(double value); 106 | 107 | CCR_RESULT checkConstantRange(sym_link *var, sym_link *lit, int op, 108 | bool exchangeOps); 109 | value *array2Ptr(value *); 110 | value *valUnaryPM(value *); 111 | value *valComplement(value *); 112 | value *valNot(value *); 113 | value *valMult(value *, value *); 114 | value *valDiv(value *, value *); 115 | value *valMod(value *, value *); 116 | value *valPlus(value *, value *); 117 | value *valMinus(value *, value *); 118 | value *valShift(value *, value *, int); 119 | value *valCompare(value *, value *, int); 120 | value *valBitwise(value *, value *, int); 121 | value *valLogicAndOr(value *, value *, int); 122 | value *valCastLiteral(sym_link *, double); 123 | value *valueFromLit(double); 124 | initList *newiList(int, void *); 125 | initList *revinit(initList *); 126 | initList *copyIlist(initList *); 127 | double list2int(initList *); 128 | value *list2val(initList *); 129 | struct ast *list2expr(initList *); 130 | void resolveIvalSym(initList *, sym_link *); 131 | designation *newDesignation(int, void *); 132 | designation *revDesignation(designation *); 133 | designation *copyDesignation(designation *); 134 | initList *reorderIlist(sym_link *, initList *); 135 | value *valFromType(sym_link *); 136 | value *constFloatVal(const char *); 137 | value *constFixed16x16Val(const char *); 138 | int getNelements(sym_link *, initList *); 139 | value *valForArray(struct ast *); 140 | value *valForStructElem(struct ast *, struct ast *); 141 | value *valForCastAggr(struct ast *, sym_link *, struct ast *, int); 142 | value *valForCastArr(struct ast *, sym_link *); 143 | bool convertIListToConstList(initList *src, literalList **lList, int size); 144 | literalList *copyLiteralList(literalList *src); 145 | unsigned long double2ul(double val); 146 | unsigned char byteOfVal(value *, int); 147 | int isEqualVal(value *, int); 148 | TYPE_TARGET_ULONGLONG ullFromLit(sym_link *lit); 149 | value *valRecastLitVal(sym_link *dtype, value *val); 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /src/backend/gen.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | SDCCgen51.h - header file for code generation for 8051 3 | 4 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | -------------------------------------------------------------------------*/ 20 | 21 | #ifndef Z80GEN_H 22 | #define Z80GEN_H 23 | 24 | #include "../SDCCicode.h" 25 | #include "../SDCCval.h" 26 | #include "ralloc.h" 27 | 28 | typedef enum { 29 | AOP_INVALID, 30 | /* Is a literal */ 31 | AOP_LIT = 1, 32 | /* Is in a register */ 33 | AOP_REG, 34 | /* Is in direct space */ 35 | AOP_DIR, 36 | /* SFR space ($FF00 and above) */ 37 | AOP_SFR, 38 | /* Is on the stack */ 39 | AOP_STK, 40 | /* Is an immediate value */ 41 | AOP_IMMD, 42 | /* Is a string (?) */ 43 | AOP_STR, 44 | /* Is in the carry register */ 45 | AOP_CRY, 46 | /* Is pointed to by IY */ 47 | AOP_IY, 48 | /* Is pointed to by HL */ 49 | AOP_HL, 50 | /* Is in A */ 51 | AOP_ACC, 52 | /* Is in H and L */ 53 | AOP_HLREG, 54 | /* Simple literal. */ 55 | AOP_SIMPLELIT, 56 | /* Is in the extended stack pointer (IY on the Z80) */ 57 | AOP_EXSTK, 58 | /* Is referenced by a pointer in a register pair. */ 59 | AOP_PAIRPTR, 60 | /* Read undefined, discard writes */ 61 | AOP_DUMMY 62 | } AOP_TYPE; 63 | 64 | /* type asmop : a homogenised type for 65 | all the different spaces an operand can be 66 | in */ 67 | typedef struct asmop { 68 | AOP_TYPE type; 69 | short coff; /* current offset */ 70 | short size; /* total size */ 71 | unsigned code : 1; /* is in Code space */ 72 | unsigned paged : 1; /* in paged memory */ 73 | unsigned freed : 1; /* already freed */ 74 | unsigned bcInUse : 1; /* for banked I/O, which uses bc for the I/O address */ 75 | union { 76 | value *aop_lit; /* if literal */ 77 | reg_info *aop_reg[4]; /* array of registers */ 78 | char *aop_dir; /* if direct */ 79 | char *aop_immd; /* if immediate others are implied */ 80 | int aop_stk; /* stack offset when AOP_STK */ 81 | const char *aop_str[4]; /* just a string array containing the location */ 82 | unsigned long aop_simplelit; /* Just the value. */ 83 | int aop_pairId; /* The pair ID */ 84 | } aopu; 85 | } asmop; 86 | 87 | void genZ80Code(iCode *); 88 | void z80_emitDebuggerSymbol(const char *); 89 | 90 | extern bool z80_assignment_optimal; 91 | extern bool should_omit_frame_ptr; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /src/backend/mappings.i: -------------------------------------------------------------------------------- 1 | static const ASM_MAPPING _asxxxx_gb_mapping[] = { 2 | /* We want to prepend the _ */ 3 | { "area", ".area _%s" }, 4 | { "areacode", ".area _%s" }, 5 | { "areadata", ".area _%s" }, 6 | { "areahome", ".area _%s" }, 7 | { "functionlabeldef", "%s:" }, 8 | { "*hl", "(hl)" }, 9 | { "di", "di" }, 10 | { "ei", "ei" }, 11 | /*{ "ldahli", "ldi\ta,(hl)" }, use when assembler update is complete*/ 12 | {"ldahli", "ld\ta,(hl)\ninc\thl"}, 13 | { "ldahlsp", "ldhl\tsp,#%d" }, 14 | { "ldaspsp", "add sp, #%d" }, 15 | { "*pair", "(%s)" }, 16 | { "enter", "" }, 17 | { "enterx", 18 | "add sp, #-%d" }, 19 | { "pusha", 20 | "push af\n" 21 | "push bc\n" 22 | "push de\n" 23 | "push hl" 24 | }, 25 | { "popa", 26 | "pop hl\n" 27 | "pop de\n" 28 | "pop bc\n" 29 | "pop af" 30 | }, 31 | { "adjustsp", "lda sp,-(sp + %d)" }, 32 | { "fileprelude", "" }, 33 | { "profileenter", 34 | "ld a,#3\n" 35 | "rst\t0x08" 36 | }, 37 | { "profileexit", 38 | "ld a,#4\n" 39 | "rst\t0x08" 40 | }, 41 | { NULL, NULL } 42 | }; 43 | 44 | static const ASM_MAPPING _asxxxx_z80_mapping[] = { 45 | /* We want to prepend the _ */ 46 | { "area", ".area _%s" }, 47 | { "areacode", ".area _%s" }, 48 | { "areadata", ".area _%s" }, 49 | { "areahome", ".area _%s" }, 50 | { "*ixx", "(ix + %d)" }, 51 | { "*iyx", "(iy + %d)" }, 52 | { "*hl", "(hl)" }, 53 | { "di", "di" }, 54 | { "ei", "ei" }, 55 | { "ldahli", 56 | "ld a,(hl)\n" 57 | "inc\thl" }, 58 | { "ldahlsp", 59 | "ld hl,#%d\n" 60 | "add\thl,sp" }, 61 | { "ldaspsp", 62 | "ld iy,#%d\n" 63 | "add\tiy,sp\n" 64 | "ld\tsp,iy" }, 65 | { "*pair", "(%s)" }, 66 | { "*offspair", "%s" }, 67 | { "enter", 68 | "push\tix\n" 69 | "ld\tix,#0\n" 70 | "add\tix,sp" }, 71 | { "pusha", 72 | "push af\n" 73 | "push\tbc\n" 74 | "push\tde\n" 75 | "push\thl\n" 76 | "push\tiy" 77 | }, 78 | { "popa", 79 | "pop iy\n" 80 | "pop\thl\n" 81 | "pop\tde\n" 82 | "pop\tbc\n" 83 | "pop\taf" 84 | }, 85 | { "adjustsp", "lda sp,-(sp + %d)" }, 86 | { "profileenter", 87 | "ld a,#3\n" 88 | "rst\t0x08" 89 | }, 90 | { "profileexit", 91 | "ld a,#4\n" 92 | "rst\t0x08" 93 | }, 94 | { NULL, NULL } 95 | }; 96 | 97 | static const ASM_MAPPING _asxxxx_r2k_mapping[] = { 98 | /* We want to prepend the _ */ 99 | { "area", ".area _%s" }, 100 | { "areacode", ".area _%s" }, 101 | { "areadata", ".area _%s" }, 102 | { "areahome", ".area _%s" }, 103 | { "*ixx", "(ix + %d)" }, 104 | { "*iyx", "(iy + %d)" }, 105 | { "*hl", "(hl)" }, 106 | { "di", "ipset3" }, 107 | { "ei", "ipres" }, 108 | { "ldahli", 109 | "ld a,(hl)\n" 110 | "inc\thl" }, 111 | { "ldahlsp", 112 | "ld hl,#%d\n" 113 | "add\thl,sp" }, 114 | { "ldaspsp", 115 | "ld iy,#%d\n" 116 | "add\tiy,sp\n" 117 | "ld\tsp,iy" }, 118 | { "*pair", "(%s)" }, 119 | { "enter", 120 | "push\tix\n" 121 | "ld\tix,#0\n" 122 | "add\tix,sp" }, 123 | { "pusha", 124 | "push af\n" 125 | "push\tbc\n" 126 | "push\tde\n" 127 | "push\thl\n" 128 | "push\tiy" 129 | }, 130 | { "popa", 131 | "pop iy\n" 132 | "pop\thl\n" 133 | "pop\tde\n" 134 | "pop\tbc\n" 135 | "pop\taf" 136 | }, 137 | { "adjustsp", "lda sp,-(sp + %d)" }, 138 | { "profileenter", 139 | "ld a,#3\n" 140 | "rst\t0x28" 141 | }, 142 | { "profileexit", 143 | "ld a,#4\n" 144 | "rst\t0x28" 145 | }, 146 | { NULL, NULL } 147 | }; 148 | 149 | static const ASM_MAPPING _rgbds_mapping[] = { 150 | { "global", "GLOBAL %s" }, 151 | { "extern", "GLOBAL %s" }, 152 | { "slabeldef", "%s:" }, 153 | { "labeldef", "%s:" }, 154 | { "tlabeldef", ".l%05d:" }, 155 | { "tlabel", ".l%05d" }, 156 | { "fileprelude", 157 | "; Generated using the rgbds tokens.\n" 158 | "\t; We have to define these here as sdcc doesn't make them global by default\n" 159 | "\tGLOBAL __mulschar\n" 160 | "\tGLOBAL __muluchar\n" 161 | "\tGLOBAL __mulint\n" 162 | "\tGLOBAL __divschar\n" 163 | "\tGLOBAL __divuchar\n" 164 | "\tGLOBAL __divsint\n" 165 | "\tGLOBAL __divuint\n" 166 | "\tGLOBAL __modschar\n" 167 | "\tGLOBAL __moduchar\n" 168 | "\tGLOBAL __modsint\n" 169 | "\tGLOBAL __moduint\n" 170 | "\tGLOBAL __mullong\n" 171 | "\tGLOBAL __modslong\n" 172 | "\tGLOBAL __divslong\n" 173 | "\tGLOBAL banked_call\n" 174 | "\tGLOBAL banked_ret\n" 175 | }, 176 | { "functionheader", 177 | "; ---------------------------------\n" 178 | "; Function %s\n" 179 | "; ---------------------------------" 180 | }, 181 | { "functionlabeldef", "%s:" }, 182 | { "zero", "$00" }, 183 | { "one", "$01" }, 184 | { "area", "SECTION \"%s\",CODE" }, 185 | { "areadata", "SECTION \"%F_%s\",BSS" }, 186 | { "areacode", "SECTION \"%F_CODE\",%s" }, 187 | { "areahome", "SECTION \"%F_CODE\",%s" }, 188 | { "ascii", "DB \"%s\"" }, 189 | { "ds", "DS %d" }, 190 | { "db", "DB" }, 191 | { "dbs", "DB %s" }, 192 | { "dw", "DW" }, 193 | { "dws", "DW %s" }, 194 | { "immed", "" }, 195 | { "constbyte", "$%02X" }, 196 | { "constword", "$%04X" }, 197 | { "immedword", "$%04X" }, 198 | { "immedbyte", "$%02X" }, 199 | { "hashedstr", "%s" }, 200 | { "lsbimmeds", "%s & $FF" }, 201 | { "msbimmeds", "%s >> 8" }, 202 | { "bankimmeds", "BANK(%s)" }, 203 | { "module", "; MODULE %s" }, 204 | { NULL, NULL } 205 | }; 206 | 207 | static const ASM_MAPPING _rgbds_gb_mapping[] = { 208 | { "pusha", 209 | "push af\n" 210 | "\tpush bc\n" 211 | "\tpush de\n" 212 | "\tpush hl" 213 | }, 214 | { "popa", 215 | "pop hl\n" 216 | "\tpop de\n" 217 | "\tpop bc\n" 218 | "\tpop af" 219 | }, 220 | { "di", "di" }, 221 | { "ei", "ei" }, 222 | { "adjustsp", "add sp,-%d" }, 223 | { "enter", "" }, 224 | { "ldahli", "ld a,[hl+]" }, 225 | { "*hl", "[hl]" }, 226 | { "ldahlsp", "ld hl,[sp+%d]" }, 227 | { "ldaspsp", "add sp,%d" }, 228 | { "*pair", "[%s]" }, 229 | { NULL, NULL } 230 | }; 231 | 232 | static const ASM_MAPPING _isas_mapping[] = { 233 | { "global", "GLOBAL %s" }, 234 | { "extern", "GLOBAL %s" }, 235 | { "slabeldef", "%s:" }, 236 | { "labeldef", "%s:" }, 237 | { "tlabeldef", "?l%05d:" }, 238 | { "tlabel", "?l%05d" }, 239 | { "fileprelude", 240 | ";Generated using the isas tokens.\n" 241 | "\tLPREFIX '?' ; Treat labels starting with ? as local.\n" 242 | "\tONCNUM ; Numbers are hex\n" 243 | "\tCAPSOFF ; Case sensitive\n" 244 | "\tISDMG ; Gameboy mode\n" 245 | "_CODE\tGROUP\n" 246 | "\t; We have to define these here as sdcc doesnt make them global by default\n" 247 | "\tGLOBAL __mulschar\n" 248 | "\tGLOBAL __muluchar\n" 249 | "\tGLOBAL __mulint\n" 250 | "\tGLOBAL __divschar\n" 251 | "\tGLOBAL __divuchar\n" 252 | "\tGLOBAL __divsint\n" 253 | "\tGLOBAL __divuint\n" 254 | "\tGLOBAL __modschar\n" 255 | "\tGLOBAL __moduchar\n" 256 | "\tGLOBAL __modsint\n" 257 | "\tGLOBAL __moduint\n" 258 | "\tGLOBAL banked_call\n" 259 | "\tGLOBAL banked_ret\n" 260 | }, 261 | { "functionheader", 262 | "; ---------------------------------\n" 263 | "; Function %s\n" 264 | "; ---------------------------------" 265 | }, 266 | { "functionlabeldef", "%s:" }, 267 | { "zero", "$00" }, 268 | { "one", "$01" }, 269 | { "area", "%s\tGROUP" }, 270 | { "areacode", "_CODE\tGROUP" }, 271 | { "areadata", "_DATA\tGROUP" }, 272 | { "areahome", "_CODE\tGROUP" }, 273 | { "ascii", "DB \"%s\"" }, 274 | { "ds", "DS %d" }, 275 | { "db", "DB" }, 276 | { "dbs", "DB %s" }, 277 | { "dw", "DW" }, 278 | { "dws", "DW %s" }, 279 | { "immed", "" }, 280 | { "constbyte", "0x%02X" }, 281 | { "constword", "0x%04X" }, 282 | { "immedword", "0x%04X" }, 283 | { "immedbyte", "0x%02X" }, 284 | { "hashedstr", "%s" }, 285 | { "lsbimmeds", "%s & 0xFF" }, 286 | { "msbimmeds", "%s >> 8" }, 287 | { "bankimmeds", "!%s" }, 288 | { "module", "; MODULE %s" }, 289 | { NULL, NULL } 290 | }; 291 | 292 | static const ASM_MAPPING _isas_gb_mapping[] = { 293 | { "pusha", 294 | "push af\n" 295 | "push bc\n" 296 | "push de\n" 297 | "push hl" 298 | }, 299 | { "popa", 300 | "pop hl\n" 301 | "pop de\n" 302 | "pop bc\n" 303 | "pop af" 304 | }, 305 | { "di", "di" }, 306 | { "ei", "ei" }, 307 | { "adjustsp", "add sp,-%d" }, 308 | { "enter", "" }, 309 | { "ldahli", "ld a,(hli)" }, 310 | { "*hl", "(hl)" }, 311 | { "ldahlsp", "ldhl sp,%d" }, 312 | { "ldaspsp", "add sp,%d" }, 313 | { "*pair", "(%s)" }, 314 | { NULL, NULL } 315 | }; 316 | 317 | static const ASM_MAPPING _z80asm_mapping[] = { 318 | { "global", "XDEF %s" }, 319 | { "extern", "XREF %s" }, 320 | { "slabeldef", "\n.%s" }, 321 | { "labeldef", "\n.%s" }, 322 | { "tlabeldef", "\n.l%N%05d" }, 323 | { "tlabel", "l%N%05d" }, 324 | { "fileprelude", 325 | "; Generated using the z80asm/z88 tokens.\n" 326 | "\tXREF __muluchar_rrx_s\n" 327 | "\tXREF __mulschar_rrx_s\n" 328 | "\tXREF __mulint_rrx_s\n" 329 | "\tXREF __mullong_rrx_s\n" 330 | "\tXREF __divuchar_rrx_s\n" 331 | "\tXREF __divschar_rrx_s\n" 332 | "\tXREF __divsint_rrx_s\n" 333 | "\tXREF __divuint_rrx_s\n" 334 | "\tXREF __divulong_rrx_s\n" 335 | "\tXREF __divslong_rrx_s\n" 336 | "\tXREF __rrulong_rrx_s\n" 337 | "\tXREF __rrslong_rrx_s\n" 338 | "\tXREF __rlulong_rrx_s\n" 339 | "\tXREF __rlslong_rrx_s\n" 340 | }, 341 | { "functionheader", 342 | "; ---------------------------------\n" 343 | "; Function %s\n" 344 | "; ---------------------------------" 345 | }, 346 | { "functionlabeldef", ".%s" }, 347 | { "zero", "$00" }, 348 | { "one", "$01" }, 349 | { "ascii", "DEFM \"%s\"" }, 350 | { "ds", "DEFS %d" }, 351 | { "db", "DEFB" }, 352 | { "dbs", "DEFB %s" }, 353 | { "dw", "DEFW" }, 354 | { "dws", "DEFB %s" }, 355 | { "immed", "" }, 356 | { "constbyte", "$%02X" }, 357 | { "constword", "$%04X" }, 358 | { "immedword", "$%04X" }, 359 | { "immedbyte", "$%02X" }, 360 | { "hashedstr", "%s" }, 361 | { "lsbimmeds", "%s ~ $FF" }, 362 | { "msbimmeds", "%s / 256" }, 363 | 364 | { "bankimmeds", "BANK(%s)" }, 365 | { "module", "MODULE %s" }, 366 | { "area", "; Area %s" }, 367 | { "areadata", "; Aread BSS" }, 368 | { "areacode", "; Area CODE" }, 369 | { "areahome", "; Area HOME" }, 370 | { NULL, NULL } 371 | }; 372 | 373 | static const ASM_MAPPING _z80asm_z80_mapping[] = { 374 | { "*ixx", "(ix%+d)" }, 375 | { "*iyx", "(iy%+d)" }, 376 | { "*hl", "(hl)" }, 377 | { "di", "di" }, 378 | { "ei", "ei" }, 379 | { "ldahli", 380 | "ld a,(hl)\n" 381 | "inc\thl" }, 382 | { "ldahlsp", 383 | "ld hl,%d\n" 384 | "add\thl,sp" }, 385 | { "ldaspsp", 386 | "ld iy,%d\n" 387 | "add\tiy,sp\n" 388 | "ld\tsp,iy" }, 389 | { "*pair", "(%s)" }, 390 | { "enter", 391 | "push\tix\n" 392 | "ld\tix,0\n" 393 | "add\tix,sp" }, 394 | { "pusha", 395 | "push af\n" 396 | "push\tbc\n" 397 | "push\tde\n" 398 | "push\thl\n" 399 | "push\tiy" 400 | }, 401 | { "popa", 402 | "pop\tiy\n" 403 | "pop\thl\n" 404 | "pop\tde\n" 405 | "pop\tbc\n" 406 | "pop\taf" 407 | }, 408 | { "adjustsp", "lda sp,(sp%+d)" }, 409 | { "profileenter", 410 | "ld a,3\n" 411 | "rst\t$08" 412 | }, 413 | { "profileexit", 414 | "ld a,4\n" 415 | "rst\t$08" 416 | }, 417 | { NULL, NULL } 418 | }; 419 | 420 | static const ASM_MAPPINGS _isas = { 421 | NULL, 422 | _isas_mapping 423 | }; 424 | 425 | const ASM_MAPPINGS _isas_gb = { 426 | &_isas, 427 | _isas_gb_mapping 428 | }; 429 | 430 | static const ASM_MAPPINGS _rgbds = { 431 | NULL, 432 | _rgbds_mapping 433 | }; 434 | 435 | const ASM_MAPPINGS _rgbds_gb = { 436 | &_rgbds, 437 | _rgbds_gb_mapping 438 | }; 439 | 440 | const ASM_MAPPINGS _asxxxx_gb = { 441 | &asm_asxxxx_mapping, 442 | _asxxxx_gb_mapping 443 | }; 444 | 445 | const ASM_MAPPINGS _asxxxx_z80 = { 446 | &asm_asxxxx_mapping, 447 | _asxxxx_z80_mapping 448 | }; 449 | 450 | static const ASM_MAPPINGS _z80asm = { 451 | NULL, 452 | _z80asm_mapping 453 | }; 454 | 455 | const ASM_MAPPINGS _z80asm_z80 = { 456 | &_z80asm, 457 | _z80asm_z80_mapping 458 | }; 459 | 460 | const ASM_MAPPINGS _asxxxx_r2k = { 461 | &asm_asxxxx_mapping, 462 | _asxxxx_r2k_mapping 463 | }; 464 | -------------------------------------------------------------------------------- /src/backend/peep.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | peep.h - header file for peephole optimizer helper functions 3 | 4 | Written By - Philipp Klaus Krause 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | In other words, you are welcome to use, share and improve this program. 21 | You are forbidden to forbid anyone else to use, share and improve 22 | what you give them. Help stamp out software-hoarding! 23 | -------------------------------------------------------------------------*/ 24 | 25 | bool z80notUsed(const char *what, lineNode *endPl, lineNode *head); 26 | bool z80notUsedFrom(const char *what, const char *label, lineNode *head); 27 | bool z80canAssign(const char *dst, const char *src, const char *exotic); 28 | int z80instructionSize(lineNode *node); 29 | -------------------------------------------------------------------------------- /src/backend/peeph.def: -------------------------------------------------------------------------------- 1 | // peeph.def - Common Z80 and gbz80 peephole rules 2 | 3 | // This file should contain common Z80/GBZ80 peepholes. 4 | // However the GBZ80 port is currently unmaintained; 5 | // a GBZ80 expert could extract peepholes that are useful for both Z80 and GBZ80 6 | // from peeph-z80.def and peeph-gbz80.def and move them here. 7 | 8 | -------------------------------------------------------------------------------- /src/backend/ralloc.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | 3 | SDCCralloc.h - header file register allocation 4 | 5 | Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | In other words, you are welcome to use, share and improve this program. 22 | You are forbidden to forbid anyone else to use, share and improve 23 | what you give them. Help stamp out software-hoarding! 24 | -------------------------------------------------------------------------*/ 25 | #include "SDCCBBlock.h" 26 | #include "SDCCicode.h" 27 | #ifndef SDCCRALLOC_H 28 | #define SDCCRALLOC_H 1 29 | 30 | #define DEBUG_FAKE_EXTRA_REGS 0 31 | 32 | enum { 33 | C_IDX = 0, 34 | B_IDX, 35 | E_IDX, 36 | D_IDX, 37 | L_IDX, 38 | H_IDX, 39 | IYL_IDX, 40 | IYH_IDX, 41 | #if DEBUG_FAKE_EXTRA_REGS 42 | M_IDX, 43 | N_IDX, 44 | O_IDX, 45 | P_IDX, 46 | Q_IDX, 47 | R_IDX, 48 | S_IDX, 49 | T_IDX, 50 | #endif 51 | CND_IDX 52 | }; 53 | 54 | #define A_IDX (IS_GB ? 4 : (IY_RESERVED ? 6 : 8)) 55 | 56 | enum { REG_PTR = 1, REG_GPR = 2, REG_CND = 4, REG_PAIR = 8 }; 57 | 58 | /* definition for the registers */ 59 | typedef struct reg_info { 60 | short type; /* can have value 61 | REG_GPR, REG_PTR or REG_CND */ 62 | short rIdx; /* index into register table */ 63 | char *name; /* name */ 64 | unsigned isFree : 1; /* is currently unassigned */ 65 | } reg_info; 66 | 67 | extern reg_info *regsZ80; 68 | 69 | void assignRegisters(eBBlock **, int); 70 | reg_info *regWithIdx(int); 71 | 72 | void z80_assignRegisters(ebbIndex *); 73 | bitVect *z80_rUmaskForOp(const operand *op); 74 | 75 | void spillThis(symbol *); 76 | iCode *z80_ralloc2_cc(ebbIndex *ebbi); 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/backend/support.c: -------------------------------------------------------------------------------- 1 | /** @file z80/support.c 2 | */ 3 | #include "z80.h" 4 | #include 5 | 6 | int convertFloat(Z80_FLOAT *f, double native) { 7 | unsigned long mantissa, exponent; 8 | double f2; 9 | wassert(f); 10 | if (native != 0) { 11 | f2 = floor(log(fabs(native)) / log(2)) + 1; 12 | mantissa = (unsigned long)(0x1000000 * fabs(native) / exp(f2 * log(2))); 13 | mantissa &= 0xffffff; 14 | exponent = (unsigned long)(f2 + 0x40); 15 | if (native < 0) 16 | exponent |= 0x80; 17 | } else { 18 | mantissa = 0; 19 | exponent = 0; 20 | } 21 | 22 | f->w[0] = (WORD)mantissa; 23 | f->w[1] = (BYTE)(mantissa >> 16); 24 | f->w[1] |= exponent << 8; 25 | 26 | f->b[0] = (BYTE)f->w[0]; 27 | f->b[1] = (BYTE)(f->w[0] >> 8); 28 | f->b[2] = (BYTE)f->w[1]; 29 | f->b[3] = (BYTE)(f->w[1] >> 8); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /src/backend/support.h: -------------------------------------------------------------------------------- 1 | /** @file z80/support.h 2 | Support functions for the z80 port. 3 | */ 4 | #ifndef Z80_SUPPORT_INCLUDE 5 | #define Z80_SUPPORT_INCLUDE 6 | 7 | typedef unsigned short WORD; 8 | typedef unsigned char BYTE; 9 | 10 | typedef struct { 11 | WORD w[2]; 12 | BYTE b[4]; 13 | } Z80_FLOAT; 14 | 15 | /** Convert a native float into 'z80' format */ 16 | int convertFloat(Z80_FLOAT *f, double native); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/backend/z80.h: -------------------------------------------------------------------------------- 1 | /** @file z80/z80.h 2 | Common definitions between the z80 and gbz80 parts. 3 | */ 4 | #include "common.h" 5 | #include "gen.h" 6 | #include "peep.h" 7 | #include "ralloc.h" 8 | #include "support.h" 9 | 10 | typedef enum { 11 | SUB_Z80, 12 | SUB_Z180, 13 | SUB_R2K, 14 | SUB_R3KA, 15 | SUB_GBZ80, 16 | SUB_TLCS90 17 | } Z80_SUB_PORT; 18 | 19 | typedef struct { 20 | Z80_SUB_PORT sub; 21 | int calleeSavesBC; 22 | int port_mode; 23 | int port_back; 24 | int reserveIY; 25 | int noOmitFramePtr; 26 | } Z80_OPTS; 27 | 28 | extern Z80_OPTS z80_opts; 29 | 30 | #define IS_Z80 (z80_opts.sub == SUB_Z80) 31 | #define IS_Z180 (z80_opts.sub == SUB_Z180) 32 | #define IS_R2K (z80_opts.sub == SUB_R2K) 33 | #define IS_R3KA (z80_opts.sub == SUB_R3KA) 34 | #define IS_RAB (IS_R2K || IS_R3KA) 35 | #define IS_GB (z80_opts.sub == SUB_GBZ80) 36 | #define IS_TLCS90 (z80_opts.sub == SUB_TLCS90) 37 | 38 | #define IY_RESERVED (z80_opts.reserveIY) 39 | 40 | #define OPTRALLOC_HL (!IS_GB) 41 | #define OPTRALLOC_IY !(IY_RESERVED || IS_GB) 42 | 43 | enum { ACCUSE_A = 1, ACCUSE_SCRATCH, ACCUSE_IY }; 44 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | common.h - include common header files 3 | 4 | Copyright (C) 2000, KEvin Vigor 5 | 6 | This program is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by the 8 | Free Software Foundation; either version 2, or (at your option) any 9 | later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | -------------------------------------------------------------------------*/ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #ifndef COMMON_H 27 | #define COMMON_H 28 | 29 | #if defined(__APPLE__) && (__MACH__) 30 | #ifdef _G 31 | #undef _G 32 | #endif 33 | #endif 34 | 35 | /* C++ incompatible heared files */ 36 | #ifdef __cplusplus 37 | /* TODO: the extern "C" should be moved to each header file */ 38 | extern "C" { 39 | #endif 40 | 41 | #include "SDCCBBlock.h" 42 | #include "SDCCasm.h" 43 | #include "SDCCast.h" 44 | #include "SDCCbitv.h" 45 | #include "SDCCcflow.h" 46 | #include "SDCCcse.h" 47 | #include "SDCCdflow.h" 48 | #include "SDCCglobl.h" 49 | #include "SDCCglue.h" 50 | #include "SDCChasht.h" 51 | #include "SDCCicode.h" 52 | #include "SDCClabel.h" 53 | #include "SDCCloop.h" 54 | #include "SDCClrange.h" 55 | #include "SDCCmem.h" 56 | #include "SDCCopt.h" 57 | #include "SDCCpeeph.h" 58 | #include "SDCCptropt.h" 59 | #include "SDCCset.h" 60 | #include "SDCCsystem.h" 61 | #include "SDCCutil.h" 62 | #include "SDCCy.h" 63 | 64 | #include "port.h" 65 | 66 | #include "newalloc.h" 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | /* C++ compatible header files */ 73 | #include "SDCCgen.h" 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/port.h: -------------------------------------------------------------------------------- 1 | /** @file port.h 2 | Definitions for what a port must provide. 3 | All ports are referenced in SDCCmain.c. 4 | */ 5 | #ifndef PORT_INCLUDE 6 | #define PORT_INCLUDE 7 | 8 | #include "SDCCargs.h" 9 | #include "SDCCicode.h" 10 | #include "SDCCpeeph.h" 11 | #include "dbuf.h" 12 | 13 | #define MAX_BUILTIN_ARGS 16 14 | /* definition of builtin functions */ 15 | typedef struct builtins { 16 | char *name; /* name of builtin function */ 17 | char *rtype; /* return type as string : see typeFromStr */ 18 | int nParms; /* number of parms : max 8 */ 19 | char *parm_types[MAX_BUILTIN_ARGS]; /* each parm type as string : see 20 | typeFromStr */ 21 | } builtins; 22 | 23 | struct ebbIndex; 24 | 25 | /* pragma structure */ 26 | struct pragma_s { 27 | const char *name; 28 | int id; 29 | char deprecated; 30 | int (*func)(int id, const char *name, const char *cp); 31 | }; 32 | 33 | /* defined in SDCClex.lex */ 34 | int process_pragma_tbl(const struct pragma_s *pragma_tbl, const char *s); 35 | 36 | /* Processor specific names */ 37 | typedef struct { 38 | /** Unique id for this target */ 39 | const int id; 40 | /** Target name used for -m */ 41 | const char *const target; 42 | 43 | /** Target name string, used for --help */ 44 | const char *const target_name; 45 | 46 | /** Specific processor for the given target family. specified by -p */ 47 | char *processor; 48 | 49 | struct { 50 | /** Pointer to glue function */ 51 | void (*do_glue)(void); 52 | /** TRUE if all types of glue functions should be inserted into 53 | the file that also defines main. 54 | We dont want this in cases like the z80 where the startup 55 | code is provided by a seperate module. 56 | */ 57 | bool glue_up_main; 58 | /* OR of MODEL_* */ 59 | } general; 60 | 61 | /* assembler related information */ 62 | struct { 63 | /** Command to run and arguments (eg as-z80) */ 64 | const char **cmd; 65 | /** Alternate macro based form. */ 66 | const char *mcmd; 67 | /** Arguments for debug mode. */ 68 | const char *debug_opts; 69 | /** Arguments for normal assembly mode. */ 70 | const char *plain_opts; 71 | /* print externs as global */ 72 | int externGlobal; 73 | /* assembler file extension */ 74 | const char *file_ext; 75 | /** If non-null will be used to execute the assembler. */ 76 | void (*do_assemble)(set *); 77 | } assembler; 78 | 79 | /* linker related info */ 80 | struct { 81 | /** Command to run (eg link-z80) */ 82 | const char **cmd; 83 | /** Alternate macro based form. */ 84 | const char *mcmd; 85 | /** If non-null will be used to execute the link. */ 86 | void (*do_link)(void); 87 | /** Extension for object files (.rel, .obj, ...) */ 88 | const char *rel_ext; 89 | /** 1 if port needs the .lnk file, 0 otherwise */ 90 | const int needLinkerScript; 91 | const char *const *crt; 92 | const char *const *libs; 93 | } linker; 94 | 95 | /** Default peephole rules */ 96 | struct { 97 | char *default_rules; 98 | int (*getSize)(lineNode *line); 99 | bitVect *(*getRegsRead)(lineNode *line); 100 | bitVect *(*getRegsWritten)(lineNode *line); 101 | bool (*deadMove)(const char *reg, lineNode *currPl, lineNode *head); 102 | bool (*notUsed)(const char *reg, lineNode *currPl, lineNode *head); 103 | bool (*canAssign)(const char *op1, const char *op2, const char *op3); 104 | bool (*notUsedFrom)(const char *reg, const char *label, lineNode *head); 105 | } peep; 106 | 107 | /** Basic type sizes */ 108 | struct { 109 | int char_size; 110 | int short_size; 111 | unsigned int int_size; 112 | int long_size; 113 | int longlong_size; 114 | int ptr_size; // near 115 | int fptr_size; // far 116 | int gptr_size; // generic 117 | int bit_size; 118 | int float_size; 119 | int max_base_size; 120 | } s; 121 | 122 | /** tags for far, near, xstack, code generic pointers */ 123 | struct { 124 | int tag_far; 125 | int tag_near; 126 | int tag_xstack; 127 | int tag_code; 128 | } gp_tags; 129 | 130 | /** memory regions related stuff */ 131 | struct { 132 | const char *const xstack_name; 133 | const char *const istack_name; 134 | /* 135 | * The following 2 items can't be const pointers 136 | * due to ugly implementation in gbz80 target; 137 | * this should be fixed in src/z80/main.c (borutr) 138 | */ 139 | const char *code_name; 140 | const char *data_name; 141 | const char *const idata_name; 142 | const char *const pdata_name; 143 | const char *const xdata_name; 144 | const char *const bit_name; 145 | const char *const reg_name; 146 | const char *const static_name; 147 | const char *const overlay_name; 148 | const char *const post_static_name; 149 | const char *const home_name; 150 | const char *const xidata_name; // initialized xdata 151 | const char *const xinit_name; // a code copy of xidata 152 | const char *const const_name; // const data (code or not) 153 | const char *const cabs_name; // const absolute data (code or not) 154 | const char *const xabs_name; // absolute xdata/pdata 155 | const char *const iabs_name; // absolute idata/data 156 | const char *const 157 | initialized_name; // Initialized global (and static local) variables. 158 | const char *const initializer_name; // A code copy of initialized_name (to 159 | // be copied for fast initialization). 160 | struct memmap *default_local_map; // default location for auto vars 161 | struct memmap *default_globl_map; // default location for globl vars 162 | int code_ro; // code space read-only 1=yes 163 | unsigned int 164 | maxextalign; // maximum extended alignment supported, nonnegative power 165 | // of 2 (C11 standard, section 6.2.8). 166 | } mem; 167 | 168 | struct { 169 | void (*genExtraAreaDeclaration)(FILE *, bool); 170 | void (*genExtraAreaLinkOptions)(FILE *); 171 | } extraAreas; 172 | 173 | /* stack related information */ 174 | struct { 175 | /** -1 for grows down (z80), +1 for grows up (mcs51) */ 176 | int direction; 177 | /** Extra overhead when calling between banks */ 178 | int bank_overhead; 179 | /** Extra overhead when the function is an ISR */ 180 | int isr_overhead; 181 | /** Standard overhead for a function call */ 182 | int call_overhead; 183 | /** Re-enterant space */ 184 | int reent_overhead; 185 | /** 'banked' call overhead. 186 | Mild overlap with bank_overhead */ 187 | int banked_overhead; 188 | } stack; 189 | 190 | struct { 191 | /** One more than the smallest 192 | mul/div operation the processor can do natively 193 | Eg if the processor has an 8 bit mul, native below is 2 */ 194 | unsigned int muldiv; 195 | /** Size of the biggest shift the port can handle. -1 if port can handle 196 | * shifts of arbitrary size. */ 197 | signed int shift; 198 | } support; 199 | 200 | struct { 201 | void (*emitDebuggerSymbol)(const char *); 202 | struct { 203 | int (*regNum)(const struct reg_info *); 204 | bitVect *cfiSame; 205 | bitVect *cfiUndef; 206 | int addressSize; 207 | int regNumRet; 208 | int regNumSP; 209 | int regNumBP; 210 | int offsetSP; 211 | } dwarf; 212 | } debugger; 213 | 214 | struct { 215 | int maxCount; 216 | int sizeofElement; 217 | int sizeofMatchJump[3]; 218 | int sizeofRangeCompare[3]; 219 | int sizeofSubtract; 220 | int sizeofDispatch; 221 | } jumptableCost; 222 | 223 | /** Prefix to add to a C function (eg "_") */ 224 | const char *fun_prefix; 225 | 226 | /** Called once the processor target has been selected. 227 | First chance to initalise and set any port specific variables. 228 | 'port' is set before calling this. May be NULL. 229 | */ 230 | void (*init)(void); 231 | /** Parses one option + its arguments */ 232 | bool (*parseOption)(int *pargc, char **argv, int *i); 233 | /** Optional list of automatically parsed options. Should be 234 | implemented to at least show the help text correctly. */ 235 | OPTION *poptions; 236 | /** Initialise port spectific paths */ 237 | void (*initPaths)(void); 238 | /** Called after all the options have been parsed. */ 239 | void (*finaliseOptions)(void); 240 | /** Called after the port has been selected but before any 241 | options are parsed. */ 242 | void (*setDefaultOptions)(void); 243 | /** Does the dirty work. */ 244 | void (*assignRegisters)(struct ebbIndex *); 245 | 246 | /** Returns the register name of a symbol. 247 | Used so that 'reg_info' can be an incomplete type. */ 248 | const char *(*getRegName)(const struct reg_info *reg); 249 | 250 | /** Try to keep track of register contents. */ 251 | bool (*rtrackUpdate)(const char *line); 252 | 253 | /* list of keywords that are used by this 254 | target (used by lexer) */ 255 | char **keywords; 256 | 257 | /* Write any port specific assembler output. */ 258 | void (*genAssemblerPreamble)(FILE *of); 259 | /* invoked at end assembler file */ 260 | void (*genAssemblerEnd)(FILE *of); 261 | 262 | /* Write the port specific IVT. If genIVT is NULL or if 263 | * it returns zero, default (8051) IVT generation code 264 | * will be used. 265 | */ 266 | int (*genIVT)(struct dbuf_s *oBuf, symbol **intTable, int intCount); 267 | 268 | void (*genXINIT)(FILE *of); 269 | 270 | /* Write port specific startup code */ 271 | void (*genInitStartup)(FILE *of); 272 | 273 | /* parameter passing in register related functions */ 274 | void (*reset_regparms)(void); /* reset the register count */ 275 | int (*reg_parm)( 276 | struct sym_link *, 277 | bool reentrant); /* will return 1 if can be passed in register */ 278 | 279 | /** Process the pragma string 'sz'. Returns 0 if recognised and 280 | processed, 1 otherwise. May be NULL. 281 | */ 282 | int (*process_pragma)(const char *sz); 283 | 284 | /** Mangles a support function name to reflect the calling model. 285 | */ 286 | const char *(*getMangledFunctionName)(const char *szOrginial); 287 | 288 | /** Returns true if the port can multiply the two types nativly 289 | without using support functions. 290 | */ 291 | bool (*hasNativeMulFor)(iCode *ic, sym_link *left, sym_link *right); 292 | 293 | /** Returns true if the port has implemented certain bit 294 | manipulation iCodes (RRC, RLC, SWAP, GETHBIT, GETABIT, GETBYTE, GETWORD) 295 | */ 296 | bool (*hasExtBitOp)(int op, int size); 297 | 298 | /** Returns the relative expense of accessing a particular output 299 | storage class. Larger values indicate higher expense. 300 | */ 301 | int (*oclsExpense)(struct memmap *oclass); 302 | 303 | /** If TRUE, then tprintf and !dw will be used for some initalisers 304 | */ 305 | bool use_dw_for_init; 306 | 307 | /** TRUE for targets with little endian byte ordering, FALSE for 308 | targets with big endian byte ordering. 309 | */ 310 | bool little_endian; 311 | 312 | /* condition transformations */ 313 | bool lt_nge; /* transform (a < b) to !(a >= b) */ 314 | bool gt_nle; /* transform (a > b) to !(a <= b) */ 315 | bool le_ngt; /* transform (a <= b) to !(a > b) */ 316 | bool ge_nlt; /* transform (a >= b) to !(a < b) */ 317 | bool ne_neq; /* transform a != b --> ! (a == b) */ 318 | bool eq_nne; /* transform a == b --> ! (a != b) */ 319 | 320 | bool arrayInitializerSuppported; 321 | bool (*cseOk)(iCode *ic, iCode *pdic); 322 | builtins *builtintable; /* table of builtin functions */ 323 | int unqualified_pointer; /* unqualified pointers type is */ 324 | int reset_labelKey; /* reset Label no 1 at the start of a function */ 325 | int globals_allowed; /* global & static locals not allowed ? 0 ONLY 326 | TININative */ 327 | 328 | int num_regs; /* Number of registers handled in the tree-decomposition-based 329 | register allocator in SDCCralloc.hpp */ 330 | #define PORT_MAGIC 0xAC32 331 | /** Used at runtime to detect if this structure has been completly filled in. 332 | */ 333 | int magic; 334 | } PORT; 335 | 336 | extern PORT *port; 337 | 338 | extern PORT z80_port; 339 | 340 | #endif /* PORT_INCLUDE */ 341 | -------------------------------------------------------------------------------- /src/sdccconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Generated during an SDCC build 3 | * We should work on getting rid of this 4 | */ 5 | 6 | /* sdccconf.h. Generated from sdccconf_in.h by configure. */ 7 | /* sdccconf_in.h. Generated from configure.in by autoheader. */ 8 | 9 | #ifndef SDCCCONF_HEADER 10 | #define SDCCCONF_HEADER 11 | 12 | #define BIN2DATA_DIR DIR_SEPARATOR_STRING "../share" 13 | #define BINDIR "/usr/local/bin" 14 | 15 | #define DATADIR "/usr/local/share" 16 | #define DIR_SEPARATOR_CHAR '/' 17 | 18 | #define DIR_SEPARATOR_STRING "/" 19 | #define EXEC_PREFIX "/usr/local" 20 | 21 | /* Define to 1 if you have the header file. 22 | */ 23 | #define HAVE_BOOST_GRAPH_ADJACENCY_LIST_HPP 1 24 | 25 | /* Define to 1 if you have the header file. */ 26 | #define HAVE_ENDIAN_H 1 27 | 28 | /* Define to 1 if you have the header file. */ 29 | #define HAVE_INTTYPES_H 1 30 | 31 | /* Define to 1 if you have the `gc' library (-lgc). */ 32 | /* #undef HAVE_LIBGC */ 33 | 34 | /* Define to 1 if you have the header file. */ 35 | /* #undef HAVE_MACHINE_ENDIAN_H */ 36 | 37 | /* Define to 1 if you have the header file. */ 38 | #define HAVE_MEMORY_H 1 39 | 40 | /* Define to 1 if you have the `mkstemp' function. */ 41 | #define HAVE_MKSTEMP 1 42 | 43 | /* Define to 1 if you have the `snprintf' function. */ 44 | #define HAVE_SNPRINTF 1 45 | 46 | /* Define to 1 if you have the header file. */ 47 | #define HAVE_STDINT_H 1 48 | 49 | /* Define to 1 if you have the header file. */ 50 | #define HAVE_STDLIB_H 1 51 | 52 | /* Define to 1 if you have the `strerror' function. */ 53 | #define HAVE_STRERROR 1 54 | 55 | /* Define to 1 if you have the header file. */ 56 | #define HAVE_STRINGS_H 1 57 | 58 | /* Define to 1 if you have the header file. */ 59 | #define HAVE_STRING_H 1 60 | 61 | /* Define to 1 if you have the header file. */ 62 | /* #undef HAVE_STX_BTREE_MAP_H */ 63 | 64 | /* Define to 1 if you have the header file. */ 65 | /* #undef HAVE_STX_BTREE_SET_H */ 66 | 67 | /* Define to 1 if you have the header file. */ 68 | /* #undef HAVE_SYS_ENDIAN_H */ 69 | 70 | /* Define to 1 if you have the header file. */ 71 | /* #undef HAVE_SYS_ISA_DEFS_H */ 72 | 73 | /* Define to 1 if you have the header file. */ 74 | #define HAVE_SYS_STAT_H 1 75 | 76 | /* Define to 1 if you have the header file. */ 77 | #define HAVE_SYS_TYPES_H 1 78 | 79 | /* Define to 1 if you have the header file. */ 80 | #define HAVE_UNISTD_H 1 81 | 82 | /* Define to 1 if you have the `vsnprintf' function. */ 83 | #define HAVE_VSNPRINTF 1 84 | 85 | /* Define to 1 if you have the `vsprintf' function. */ 86 | #define HAVE_VSPRINTF 1 87 | #define INCLUDE_DIR_SUFFIX DIR_SEPARATOR_STRING "sdcc/include" 88 | #define LIB_DIR_SUFFIX DIR_SEPARATOR_STRING "sdcc/lib" 89 | #define NON_FREE_INCLUDE_DIR_SUFFIX DIR_SEPARATOR_STRING "sdcc/non-free/include" 90 | #define NON_FREE_LIB_DIR_SUFFIX DIR_SEPARATOR_STRING "sdcc/non-free/lib" 91 | 92 | #define OPT_DISABLE_AVR 1 93 | #define OPT_DISABLE_DEVICE_LIB 1 94 | #define OPT_DISABLE_DS390 1 95 | #define OPT_DISABLE_DS400 1 96 | #define OPT_DISABLE_GBZ80 1 97 | #define OPT_DISABLE_HC08 1 98 | #define OPT_DISABLE_MCS51 1 99 | #define OPT_DISABLE_NON_FREE 1 100 | #define OPT_DISABLE_PACKIHX 0 101 | #define OPT_DISABLE_PIC14 1 102 | #define OPT_DISABLE_PIC16 1 103 | #define OPT_DISABLE_R2K 1 104 | #define OPT_DISABLE_R3KA 1 105 | #define OPT_DISABLE_S08 1 106 | #define OPT_DISABLE_SDBINUTILS 1 107 | #define OPT_DISABLE_SDCDB 1 108 | #define OPT_DISABLE_SDCPP 1 109 | #define OPT_DISABLE_STM8 1 110 | #define OPT_DISABLE_TININative 1 111 | #define OPT_DISABLE_TLCS90 1 112 | #define OPT_DISABLE_UCSIM 1 113 | #define OPT_DISABLE_XA51 1 114 | #define OPT_DISABLE_Z180 1 115 | #define OPT_DISABLE_Z80 0 116 | #define OPT_ENABLE_DOC 0 117 | #define OPT_ENABLE_LIBGC 0 118 | 119 | #define PREFIX "/usr/local" 120 | #define PREFIX2BIN_DIR DIR_SEPARATOR_STRING "bin" 121 | #define PREFIX2DATA_DIR DIR_SEPARATOR_STRING "share" 122 | 123 | /* Define as the return type of signal handlers (`int' or `void'). */ 124 | #define RETSIGTYPE void 125 | #define SDCC_DIR_NAME "KCC_HOME" 126 | #define SDCC_INCLUDE_NAME "KCC_INCLUDE" 127 | #define SDCC_LIB_NAME "KCC_LIB" 128 | 129 | /* The size of `char', as computed by sizeof. */ 130 | #define SIZEOF_CHAR 1 131 | /* The size of `int', as computed by sizeof. */ 132 | #define SIZEOF_INT 4 133 | /* The size of `long', as computed by sizeof. */ 134 | #define SIZEOF_LONG 8 135 | /* The size of `long long', as computed by sizeof. */ 136 | #define SIZEOF_LONG_LONG 8 137 | /* The size of `short', as computed by sizeof. */ 138 | #define SIZEOF_SHORT 2 139 | 140 | /* Define to 1 if you have the ANSI C header files. */ 141 | #define STDC_HEADERS 1 142 | #define TYPE_BYTE char 143 | #define TYPE_DWORD int 144 | #define TYPE_QWORD long 145 | #define TYPE_UBYTE unsigned char 146 | #define TYPE_UDWORD unsigned int 147 | #define TYPE_UQWORD unsigned long 148 | #define TYPE_UWORD unsigned short 149 | #define TYPE_WORD short 150 | 151 | /* Define to 1 if c supports tags in unnamed struct. */ 152 | #define UNNAMED_STRUCT_TAG 1 153 | 154 | #endif /* SDCCCONF_HEADER */ 155 | -------------------------------------------------------------------------------- /src/util/NewAlloc.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | newalloc.c - SDCC Memory allocation functions 3 | 4 | These functions are wrappers for the standard malloc, realloc and free 5 | functions. 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | -------------------------------------------------------------------------*/ 21 | 22 | #include "newalloc.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #if OPT_ENABLE_LIBGC 30 | #include 31 | 32 | #define MALLOC GC_malloc 33 | #define REALLOC GC_realloc 34 | /* PENDING: This is a mild hack. If we try to GC_free something 35 | allocated with malloc() then the program will segfault. Might as 36 | well drop it and let the garbase collector take care of things. 37 | */ 38 | #define FREE(_a) 39 | 40 | #else 41 | 42 | #define MALLOC malloc 43 | #define REALLOC realloc 44 | #define FREE free 45 | 46 | #endif 47 | 48 | #define TRACEMALLOC 0 49 | 50 | #if TRACEMALLOC 51 | enum { TRACESIZE = 4096 }; 52 | 53 | static int _allocs[TRACESIZE]; 54 | static int _above; 55 | 56 | static void _dumpTrace(int code, void *parg) { 57 | int i; 58 | for (i = 0; i < TRACESIZE; i++) { 59 | if (_allocs[i]) { 60 | printf("%u %u\n", _allocs[i], i); 61 | } 62 | } 63 | printf("%u above\n", _above); 64 | } 65 | 66 | static void _log(int size) { 67 | static int registered; 68 | 69 | if (registered == 0) { 70 | on_exit(_dumpTrace, NULL); 71 | registered = 1; 72 | } 73 | if (size == 12) { 74 | _above++; 75 | } 76 | 77 | if (size >= TRACESIZE) { 78 | _above++; 79 | } else { 80 | _allocs[size]++; 81 | } 82 | } 83 | #endif 84 | 85 | /* 86 | ------------------------------------------------------------------------------- 87 | Clear_realloc - Reallocate a memory block and clear any memory added with 88 | out of memory error detection 89 | 90 | ------------------------------------------------------------------------------- 91 | */ 92 | 93 | void *Clear_realloc(void *OldPtr, size_t OldSize, size_t NewSize) { 94 | void *NewPtr; 95 | 96 | NewPtr = REALLOC(OldPtr, NewSize); 97 | 98 | if (!NewPtr) { 99 | printf("ERROR - No more memory\n"); 100 | /* werror(E_OUT_OF_MEM,__FILE__,NewSize);*/ 101 | exit(1); 102 | } 103 | 104 | if (NewPtr) 105 | if (NewSize > OldSize) 106 | memset((char *)NewPtr + OldSize, 0x00, NewSize - OldSize); 107 | 108 | return NewPtr; 109 | } 110 | 111 | /* 112 | ------------------------------------------------------------------------------- 113 | Safe_realloc - Reallocate a memory block with out of memory error detection 114 | 115 | ------------------------------------------------------------------------------- 116 | */ 117 | 118 | void *Safe_realloc(void *OldPtr, size_t NewSize) { 119 | void *NewPtr; 120 | 121 | NewPtr = REALLOC(OldPtr, NewSize); 122 | 123 | if (!NewPtr) { 124 | printf("ERROR - No more memory\n"); 125 | /* werror(E_OUT_OF_MEM,__FILE__,NewSize);*/ 126 | exit(1); 127 | } 128 | 129 | return NewPtr; 130 | } 131 | 132 | /* 133 | ------------------------------------------------------------------------------- 134 | Safe_calloc - Allocate a block of memory from the application heap, clearing 135 | all data to zero and checking for out of memory errors. 136 | 137 | ------------------------------------------------------------------------------- 138 | */ 139 | 140 | void *Safe_calloc(size_t Elements, size_t Size) { 141 | void *NewPtr; 142 | 143 | NewPtr = MALLOC(Elements * Size); 144 | #if TRACEMALLOC 145 | _log(Elements * Size); 146 | #endif 147 | 148 | if (!NewPtr) { 149 | printf("ERROR - No more memory\n"); 150 | /* werror(E_OUT_OF_MEM,__FILE__,Size);*/ 151 | exit(1); 152 | } 153 | 154 | memset(NewPtr, 0, Elements * Size); 155 | 156 | return NewPtr; 157 | } 158 | 159 | /* 160 | ------------------------------------------------------------------------------- 161 | Safe_malloc - Allocate a block of memory from the application heap 162 | and checking for out of memory errors. 163 | 164 | ------------------------------------------------------------------------------- 165 | */ 166 | 167 | void *Safe_malloc(size_t Size) { 168 | void *NewPtr; 169 | 170 | NewPtr = MALLOC(Size); 171 | 172 | #if TRACEMALLOC 173 | _log(Size); 174 | #endif 175 | 176 | if (!NewPtr) { 177 | printf("ERROR - No more memory\n"); 178 | /* werror(E_OUT_OF_MEM,__FILE__,Size);*/ 179 | exit(1); 180 | } 181 | 182 | return NewPtr; 183 | } 184 | 185 | void *Safe_alloc(size_t Size) { return Safe_calloc(1, Size); } 186 | 187 | void Safe_free(void *p) { FREE(p); } 188 | 189 | char *Safe_strndup(const char *sz, size_t size) { 190 | char *pret; 191 | assert(sz); 192 | 193 | pret = Safe_alloc(size + 1); 194 | strncpy(pret, sz, size); 195 | pret[size] = '\0'; 196 | 197 | return pret; 198 | } 199 | 200 | char *Safe_strdup(const char *sz) { 201 | assert(sz); 202 | 203 | return Safe_strndup(sz, strlen(sz)); 204 | } 205 | 206 | void *traceAlloc(allocTrace *ptrace, void *p) { 207 | assert(ptrace); 208 | assert(p); 209 | 210 | /* Also handles where max == 0 */ 211 | if (ptrace->num == ptrace->max) { 212 | /* Add an offset to handle max == 0 */ 213 | ptrace->max = (ptrace->max + 2) * 2; 214 | ptrace->palloced = 215 | Safe_realloc(ptrace->palloced, ptrace->max * sizeof(*ptrace->palloced)); 216 | } 217 | ptrace->palloced[ptrace->num++] = p; 218 | 219 | return p; 220 | } 221 | 222 | void freeTrace(allocTrace *ptrace) { 223 | int i; 224 | assert(ptrace); 225 | 226 | for (i = 0; i < ptrace->num; i++) { 227 | Safe_free(ptrace->palloced[i]); 228 | } 229 | ptrace->num = 0; 230 | 231 | Safe_free(ptrace->palloced); 232 | ptrace->palloced = NULL; 233 | ptrace->max = 0; 234 | } 235 | -------------------------------------------------------------------------------- /src/util/dbuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | dbuf.c - Dynamic buffer implementation 3 | version 1.4.0, 2011-03-27 4 | 5 | Copyright (c) 2002-2011 Borut Razem 6 | 7 | This software is provided 'as-is', without any express or implied 8 | warranty. In no event will the authors be held liable for any damages 9 | arising from the use of this software. 10 | 11 | Permission is granted to anyone to use this software for any purpose, 12 | including commercial applications, and to alter it and redistribute it 13 | freely, subject to the following restrictions: 14 | 15 | 1. The origin of this software must not be misrepresented; you must not 16 | claim that you wrote the original software. If you use this software 17 | in a product, an acknowledgment in the product documentation would be 18 | appreciated but is not required. 19 | 2. Altered source versions must be plainly marked as such, and must not be 20 | misrepresented as being the original software. 21 | 3. This notice may not be removed or altered from any source distribution. 22 | 23 | Borut Razem 24 | borut.razem@siol.net 25 | */ 26 | 27 | #include "dbuf.h" 28 | #include 29 | #include 30 | #include 31 | 32 | /* 33 | * Assure that the buffer is large enough to hold 34 | * current length + size bytes; enlarge it if necessary. 35 | * 36 | * Intended for internal use. 37 | */ 38 | 39 | int _dbuf_expand(struct dbuf_s *dbuf, size_t size) { 40 | assert(dbuf->alloc != 0); 41 | assert(dbuf->buf != NULL); 42 | 43 | if (dbuf->len + size > dbuf->alloc) { 44 | /* new_allocated_size = current_allocated_size * 2^n */ 45 | /* can this be optimized? */ 46 | do { 47 | dbuf->alloc += dbuf->alloc; 48 | } while (dbuf->len + size > dbuf->alloc); 49 | 50 | if ((dbuf->buf = realloc(dbuf->buf, dbuf->alloc)) == NULL) 51 | return 0; 52 | } 53 | 54 | return 1; 55 | } 56 | 57 | /* 58 | * Initialize the dbuf structure and 59 | * allocate buffer to hold size bytes. 60 | */ 61 | 62 | int dbuf_init(struct dbuf_s *dbuf, size_t size) { 63 | assert(size != 0); 64 | 65 | if (size == 0) 66 | size = 1; 67 | 68 | dbuf->len = 0; 69 | dbuf->alloc = size; 70 | return ((dbuf->buf = malloc(dbuf->alloc)) != NULL); 71 | } 72 | 73 | /* 74 | * Test if dbuf is initialized. 75 | * NOTE: the dbuf structure should be set 76 | * to all zeroes at definition: 77 | * struct dbuf_s dbuf = { 0 }; 78 | * 79 | * See: dbuf_init() 80 | */ 81 | 82 | int dbuf_is_initialized(struct dbuf_s *dbuf) { 83 | if (dbuf->buf == NULL) { 84 | assert(dbuf->alloc == 0); 85 | assert(dbuf->len == 0); 86 | return 0; 87 | } else { 88 | assert(dbuf->alloc != 0); 89 | assert(dbuf->len >= 0 && dbuf->len <= dbuf->alloc); 90 | return 1; 91 | } 92 | } 93 | 94 | /* 95 | * Allocate new dbuf structure on the heap 96 | * and initialize it. 97 | * 98 | * See: dbuf_delete() 99 | */ 100 | 101 | struct dbuf_s *dbuf_new(size_t size) { 102 | struct dbuf_s *dbuf; 103 | 104 | dbuf = (struct dbuf_s *)malloc(sizeof(struct dbuf_s)); 105 | if (dbuf != NULL) { 106 | if (dbuf_init(dbuf, size) == 0) { 107 | free(dbuf); 108 | return NULL; 109 | } 110 | } 111 | return dbuf; 112 | } 113 | 114 | /* 115 | * Set the buffer size. Buffer size can be only decreased. 116 | */ 117 | 118 | int dbuf_set_length(struct dbuf_s *dbuf, size_t len) { 119 | if (!dbuf_is_initialized(dbuf)) 120 | dbuf_init(dbuf, len ? len : 1); 121 | 122 | assert(dbuf != NULL); 123 | assert(dbuf->alloc != 0); 124 | assert(len <= dbuf->len); 125 | 126 | if (len <= dbuf->len) { 127 | dbuf->len = len; 128 | return 1; 129 | } 130 | 131 | return 0; 132 | } 133 | 134 | /* 135 | * Append the buf to the end of the buffer. 136 | */ 137 | 138 | int dbuf_append(struct dbuf_s *dbuf, const void *buf, size_t len) { 139 | assert(dbuf != NULL); 140 | assert(dbuf->alloc != 0); 141 | assert(dbuf->buf != NULL); 142 | 143 | if (_dbuf_expand(dbuf, len) != 0) { 144 | memcpy(&(((char *)dbuf->buf)[dbuf->len]), buf, len); 145 | dbuf->len += len; 146 | return 1; 147 | } 148 | 149 | return 0; 150 | } 151 | 152 | /* 153 | * Prepend the buf to the beginning of the buffer. 154 | */ 155 | 156 | int dbuf_prepend(struct dbuf_s *dbuf, const void *buf, size_t len) { 157 | assert(dbuf); 158 | assert(dbuf->alloc); 159 | assert(dbuf->buf); 160 | 161 | if (_dbuf_expand(dbuf, len) != 0) { 162 | memmove(&(((char *)dbuf->buf)[len]), dbuf->buf, dbuf->len); 163 | memcpy(dbuf->buf, buf, len); 164 | dbuf->len += len; 165 | return 1; 166 | } 167 | 168 | return 0; 169 | } 170 | 171 | /* 172 | * Add '\0' character at the end of the buffer without 173 | * count it in the dbuf->len. 174 | */ 175 | 176 | const char *dbuf_c_str(struct dbuf_s *dbuf) { 177 | assert(dbuf != NULL); 178 | assert(dbuf->alloc != 0); 179 | assert(dbuf->buf != NULL); 180 | 181 | if (_dbuf_expand(dbuf, 1) != 0) { 182 | ((char *)dbuf->buf)[dbuf->len] = '\0'; 183 | return dbuf->buf; 184 | } 185 | 186 | return NULL; 187 | } 188 | 189 | /* 190 | * Get the buffer pointer. 191 | */ 192 | 193 | const void *dbuf_get_buf(struct dbuf_s *dbuf) { 194 | assert(dbuf != NULL); 195 | assert(dbuf->alloc != 0); 196 | assert(dbuf->buf != NULL); 197 | 198 | return dbuf->buf; 199 | } 200 | 201 | /* 202 | * Get the buffer length. 203 | */ 204 | 205 | size_t dbuf_get_length(struct dbuf_s *dbuf) { 206 | assert(dbuf != NULL); 207 | assert(dbuf->alloc != 0); 208 | assert(dbuf->buf != NULL); 209 | 210 | return dbuf->len; 211 | } 212 | 213 | /* 214 | * Trim the allocated buffer to required size 215 | */ 216 | 217 | int dbuf_trim(struct dbuf_s *dbuf) { 218 | void *buf; 219 | 220 | assert(dbuf != NULL); 221 | assert(dbuf->alloc != 0); 222 | assert(dbuf->buf != NULL); 223 | 224 | buf = realloc(dbuf->buf, dbuf->len); 225 | 226 | if (buf != NULL) { 227 | dbuf->alloc = dbuf->len; 228 | dbuf->buf = buf; 229 | } 230 | 231 | return buf != NULL; 232 | } 233 | 234 | /* 235 | * Detach the buffer from dbuf structure. 236 | * The dbuf structure can be reused by 237 | * reinitializing it. 238 | * 239 | * See: dbuf_init() 240 | */ 241 | 242 | void *dbuf_detach(struct dbuf_s *dbuf) { 243 | void *ret; 244 | 245 | assert(dbuf != NULL); 246 | assert(dbuf->alloc != 0); 247 | assert(dbuf->buf != NULL); 248 | 249 | ret = dbuf->buf; 250 | dbuf->buf = NULL; 251 | dbuf->len = 0; 252 | dbuf->alloc = 0; 253 | 254 | return ret; 255 | } 256 | 257 | /* 258 | * Add '\0' character at the end of the buffer without 259 | * count it in the dbuf->len and detach the buffer from dbuf structure. 260 | * The dbuf structure can be reused by reinitializing it. 261 | * 262 | * See: dbuf_init() 263 | */ 264 | 265 | char *dbuf_detach_c_str(struct dbuf_s *dbuf) { 266 | dbuf_c_str(dbuf); 267 | return dbuf_detach(dbuf); 268 | } 269 | 270 | /* 271 | * Destroy the dbuf structure and 272 | * free the buffer 273 | */ 274 | 275 | void dbuf_destroy(struct dbuf_s *dbuf) { free(dbuf_detach(dbuf)); } 276 | 277 | /* 278 | * Delete dbuf structure on the heap: 279 | * destroy it and free the allocated space. 280 | * The user's responsablity is not to use 281 | * the pointer any more: the best think to do 282 | * is to set the pointer to NULL value. 283 | * 284 | * See dbuf_new() 285 | */ 286 | 287 | void dbuf_delete(struct dbuf_s *dbuf) { 288 | dbuf_destroy(dbuf); 289 | free(dbuf); 290 | } 291 | 292 | /* 293 | * Free detached buffer. 294 | * 295 | * See dbuf_detach() 296 | */ 297 | 298 | void dbuf_free(const void *buf) { free((void *)buf); } 299 | -------------------------------------------------------------------------------- /src/util/dbuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | dbuf.h - Dynamic buffer interface 3 | version 1.4.0, 2011-03-27 4 | 5 | Copyright (c) 2002-2011 Borut Razem 6 | 7 | This software is provided 'as-is', without any express or implied 8 | warranty. In no event will the authors be held liable for any damages 9 | arising from the use of this software. 10 | 11 | Permission is granted to anyone to use this software for any purpose, 12 | including commercial applications, and to alter it and redistribute it 13 | freely, subject to the following restrictions: 14 | 15 | 1. The origin of this software must not be misrepresented; you must not 16 | claim that you wrote the original software. If you use this software 17 | in a product, an acknowledgment in the product documentation would be 18 | appreciated but is not required. 19 | 2. Altered source versions must be plainly marked as such, and must not be 20 | misrepresented as being the original software. 21 | 3. This notice may not be removed or altered from any source distribution. 22 | 23 | Borut Razem 24 | borut.razem@siol.net 25 | */ 26 | 27 | #ifndef __DBUF_H 28 | #define __DBUF_H 29 | 30 | #include 31 | 32 | struct dbuf_s { 33 | size_t alloc; /* size of allocated buffer in bytes */ 34 | size_t len; /* actual length of the buffer in bytes */ 35 | void *buf; /* pointer to the buffer, allocated on heap */ 36 | }; 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | int _dbuf_expand(struct dbuf_s *dbuf, size_t size); 43 | struct dbuf_s *dbuf_new(size_t size); 44 | int dbuf_init(struct dbuf_s *dbuf, size_t size); 45 | int dbuf_is_initialized(struct dbuf_s *dbuf); 46 | int dbuf_set_length(struct dbuf_s *dbuf, size_t size); 47 | int dbuf_append(struct dbuf_s *dbuf, const void *buf, size_t len); 48 | const void *dbuf_get_buf(struct dbuf_s *dbuf); 49 | size_t dbuf_get_length(struct dbuf_s *dbuf); 50 | int dbuf_prepend(struct dbuf_s *dbuf, const void *buf, size_t len); 51 | const char *dbuf_c_str(struct dbuf_s *dbuf); 52 | int dbuf_trim(struct dbuf_s *dbuf); 53 | void *dbuf_detach(struct dbuf_s *dbuf); 54 | char *dbuf_detach_c_str(struct dbuf_s *dbuf); 55 | void dbuf_destroy(struct dbuf_s *dbuf); 56 | void dbuf_delete(struct dbuf_s *dbuf); 57 | void dbuf_free(const void *buf); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif /* __DBUF_H */ 64 | -------------------------------------------------------------------------------- /src/util/dbuf_string.c: -------------------------------------------------------------------------------- 1 | /* 2 | dbuf_string.c - Append formatted string to the dynamic buffer 3 | version 1.2.2, March 20th, 2012 4 | 5 | Copyright (c) 2002-2012 Borut Razem 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2, or (at your option) 10 | any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, 20 | Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #include "dbuf_string.h" 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | /* 30 | * Append string to the end of the buffer. 31 | * The buffer is null terminated. 32 | */ 33 | 34 | int dbuf_append_str(struct dbuf_s *dbuf, const char *str) { 35 | size_t len; 36 | assert(str != NULL); 37 | 38 | len = strlen(str); 39 | if (dbuf_append(dbuf, str, len + 1)) { 40 | --dbuf->len; 41 | return 1; 42 | } else 43 | return 0; 44 | } 45 | 46 | /* 47 | * Prepend string to the beginning of the buffer. 48 | * The buffer is null terminated. 49 | */ 50 | 51 | int dbuf_prepend_str(struct dbuf_s *dbuf, const char *str) { 52 | size_t len; 53 | assert(str != NULL); 54 | 55 | len = strlen(str); 56 | return (dbuf_prepend(dbuf, str, len)); 57 | } 58 | 59 | /* 60 | * Append single character to the end of the buffer. 61 | * The buffer is null terminated. 62 | */ 63 | 64 | int dbuf_append_char(struct dbuf_s *dbuf, char chr) { 65 | char buf[2]; 66 | buf[0] = chr; 67 | buf[1] = '\0'; 68 | if (dbuf_append(dbuf, buf, 2)) { 69 | --dbuf->len; 70 | return 1; 71 | } else 72 | return 0; 73 | } 74 | 75 | /* 76 | * Prepend single character to the end of the buffer. 77 | * The buffer is null terminated. 78 | */ 79 | 80 | int dbuf_prepend_char(struct dbuf_s *dbuf, char chr) { 81 | char buf[2]; 82 | buf[0] = chr; 83 | buf[1] = '\0'; 84 | return (dbuf_prepend_str(dbuf, buf)); 85 | } 86 | 87 | /* 88 | * Calculate length of the resulting formatted string. 89 | * 90 | * Borrowed from vasprintf.c 91 | */ 92 | 93 | static int calc_result_length(const char *format, va_list args) { 94 | const char *p = format; 95 | /* Add one to make sure that it is never zero, which might cause malloc 96 | to return NULL. */ 97 | int total_width = strlen(format) + 1; 98 | va_list ap; 99 | 100 | #ifdef va_copy 101 | va_copy(ap, args); 102 | #else 103 | memcpy(&ap, &args, sizeof(va_list)); 104 | #endif 105 | 106 | while (*p != '\0') { 107 | if (*p++ == '%') { 108 | while (strchr("-+ #0", *p)) 109 | ++p; 110 | if (*p == '*') { 111 | ++p; 112 | total_width += abs(va_arg(ap, int)); 113 | } else 114 | total_width += strtoul(p, (char **)&p, 10); 115 | if (*p == '.') { 116 | ++p; 117 | if (*p == '*') { 118 | ++p; 119 | total_width += abs(va_arg(ap, int)); 120 | } else 121 | total_width += strtoul(p, (char **)&p, 10); 122 | } 123 | while (strchr("hlL", *p)) 124 | ++p; 125 | /* Should be big enough for any format specifier except %s and floats. */ 126 | total_width += 30; 127 | switch (*p) { 128 | case 'd': 129 | case 'i': 130 | case 'o': 131 | case 'u': 132 | case 'x': 133 | case 'X': 134 | case 'c': 135 | (void)va_arg(ap, int); 136 | break; 137 | case 'f': 138 | case 'e': 139 | case 'E': 140 | case 'g': 141 | case 'G': 142 | (void)va_arg(ap, double); 143 | /* Since an ieee double can have an exponent of 307, we'll 144 | make the buffer wide enough to cover the gross case. */ 145 | total_width += 307; 146 | break; 147 | case 's': 148 | total_width += strlen(va_arg(ap, char *)); 149 | break; 150 | case 'p': 151 | case 'n': 152 | (void)va_arg(ap, char *); 153 | break; 154 | } 155 | p++; 156 | } 157 | } 158 | #ifdef va_copy 159 | va_end(ap); 160 | #endif 161 | return total_width; 162 | } 163 | 164 | /* 165 | * Append the formatted string to the end of the buffer. 166 | * The buffer is null terminated. 167 | */ 168 | 169 | int dbuf_vprintf(struct dbuf_s *dbuf, const char *format, va_list args) { 170 | int size = calc_result_length(format, args); 171 | 172 | assert(dbuf != NULL); 173 | assert(dbuf->alloc != 0); 174 | assert(dbuf->buf != NULL); 175 | 176 | if (0 != _dbuf_expand(dbuf, size)) { 177 | int len = vsprintf(&(((char *)dbuf->buf)[dbuf->len]), format, args); 178 | 179 | if (len >= 0) { 180 | /* if written length is greater then the calculated one, 181 | we have a buffer overrun! */ 182 | assert(len <= size); 183 | dbuf->len += len; 184 | } 185 | return len; 186 | } 187 | 188 | return 0; 189 | } 190 | 191 | /* 192 | * Append the formatted string to the end of the buffer. 193 | * The buffer is null terminated. 194 | */ 195 | 196 | int dbuf_printf(struct dbuf_s *dbuf, const char *format, ...) { 197 | va_list arg; 198 | int len; 199 | 200 | va_start(arg, format); 201 | len = dbuf_vprintf(dbuf, format, arg); 202 | va_end(arg); 203 | 204 | return len; 205 | } 206 | 207 | /* 208 | * Append line from file to the dynamic buffer 209 | * The buffer is null terminated. 210 | */ 211 | 212 | size_t dbuf_getline(struct dbuf_s *dbuf, FILE *infp) { 213 | int c; 214 | char chr; 215 | 216 | while ((c = getc(infp)) != '\n' && c != EOF) { 217 | chr = c; 218 | 219 | dbuf_append(dbuf, &chr, 1); 220 | } 221 | 222 | /* add trailing NL */ 223 | if (c == '\n') { 224 | chr = c; 225 | 226 | dbuf_append(dbuf, &chr, 1); 227 | } 228 | 229 | /* terminate the line without increasing the length */ 230 | if (0 != _dbuf_expand(dbuf, 1)) 231 | ((char *)dbuf->buf)[dbuf->len] = '\0'; 232 | 233 | return dbuf_get_length(dbuf); 234 | } 235 | 236 | /* 237 | * Remove trailing newline from the string. 238 | * The buffer is null terminated. 239 | * It returns the total number of characters removed. 240 | */ 241 | 242 | size_t dbuf_chomp(struct dbuf_s *dbuf) { 243 | size_t i = dbuf->len; 244 | size_t ret; 245 | 246 | if (i != 0 && '\n' == ((char *)dbuf->buf)[i - 1]) { 247 | --i; 248 | if (i != 0 && '\r' == ((char *)dbuf->buf)[i - 1]) { 249 | --i; 250 | } 251 | } 252 | 253 | ret = dbuf->len - i; 254 | dbuf->len = i; 255 | 256 | /* terminate the line without increasing the length */ 257 | if (_dbuf_expand(dbuf, 1) != 0) 258 | ((char *)dbuf->buf)[dbuf->len] = '\0'; 259 | 260 | return ret; 261 | } 262 | 263 | /* 264 | * Write dynamic buffer to the file. 265 | */ 266 | 267 | void dbuf_write(struct dbuf_s *dbuf, FILE *dest) { 268 | fwrite(dbuf_get_buf(dbuf), 1, dbuf_get_length(dbuf), dest); 269 | } 270 | 271 | /* 272 | * Write dynamic buffer to the file and destroy it. 273 | */ 274 | 275 | void dbuf_write_and_destroy(struct dbuf_s *dbuf, FILE *dest) { 276 | dbuf_write(dbuf, dest); 277 | 278 | dbuf_destroy(dbuf); 279 | } 280 | -------------------------------------------------------------------------------- /src/util/dbuf_string.h: -------------------------------------------------------------------------------- 1 | /* 2 | dbuf_string.h - Append formatted string to the dynamic buffer 3 | version 1.2.2, March 20th, 2012 4 | 5 | Copyright (c) 2002-2012 Borut Razem 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2, or (at your option) 10 | any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, 20 | Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #ifndef __DBUF_STRING_H 24 | #define __DBUF_STRING_H 25 | 26 | #include "dbuf.h" 27 | #include 28 | #include 29 | 30 | /* Attribute `nonnull' was valid as of gcc 3.3. */ 31 | #ifndef ATTRIBUTE_NONNULL 32 | #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) 33 | #define ATTRIBUTE_NONNULL(m) __attribute__((__nonnull__(m))) 34 | #else 35 | #define ATTRIBUTE_NONNULL(m) 36 | #endif /* GNUC >= 3.3 */ 37 | #endif /* ATTRIBUTE_NONNULL */ 38 | 39 | /* The __-protected variants of `format' and `printf' attributes 40 | are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ 41 | #ifndef ATTRIBUTE_PRINTF 42 | #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) 43 | #define ATTRIBUTE_PRINTF(m, n) \ 44 | __attribute__((__format__(__printf__, m, n))) ATTRIBUTE_NONNULL(m) 45 | #else 46 | #define ATTRIBUTE_PRINTF(m, n) 47 | #endif /* GNUC >= 2.7 */ 48 | #endif /* ATTRIBUTE_PRINTF */ 49 | 50 | #ifdef __cplusplus 51 | extern "C" { 52 | #endif 53 | 54 | int dbuf_append_str(struct dbuf_s *dbuf, const char *str); 55 | int dbuf_prepend_str(struct dbuf_s *dbuf, const char *str); 56 | int dbuf_append_char(struct dbuf_s *dbuf, char chr); 57 | int dbuf_prepend_char(struct dbuf_s *dbuf, char chr); 58 | int dbuf_vprintf(struct dbuf_s *dbuf, const char *format, va_list args); 59 | int dbuf_printf(struct dbuf_s *dbuf, const char *format, ...) 60 | ATTRIBUTE_PRINTF(2, 3); 61 | size_t dbuf_getline(struct dbuf_s *dbuf, FILE *infp); 62 | size_t dbuf_chomp(struct dbuf_s *dbuf); 63 | void dbuf_write(struct dbuf_s *dbuf, FILE *dest); 64 | void dbuf_write_and_destroy(struct dbuf_s *dbuf, FILE *dest); 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | 70 | #endif /* __DBUF_STRING_H */ 71 | -------------------------------------------------------------------------------- /src/util/newalloc.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | newalloc.h - SDCC Memory allocation functions 3 | 4 | These functions are wrappers for the standard malloc, realloc and free 5 | functions. 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | -------------------------------------------------------------------------*/ 21 | 22 | #if !defined(_NewAlloc_H) 23 | 24 | #define _NewAlloc_H 25 | 26 | #include 27 | 28 | typedef struct _allocTrace { 29 | int num; 30 | int max; 31 | void **palloced; 32 | } allocTrace; 33 | 34 | /* 35 | ------------------------------------------------------------------------------- 36 | Clear_realloc - Reallocate a memory block and clear any memory added with 37 | out of memory error detection 38 | 39 | ------------------------------------------------------------------------------- 40 | */ 41 | 42 | void *Clear_realloc(void *OldPtr, size_t OldSize, size_t NewSize); 43 | 44 | /* 45 | ------------------------------------------------------------------------------- 46 | Safe_realloc - Reallocate a memory block with out of memory error detection 47 | 48 | ------------------------------------------------------------------------------- 49 | */ 50 | 51 | void *Safe_realloc(void *OldPtr, size_t NewSize); 52 | 53 | /* 54 | ------------------------------------------------------------------------------- 55 | Safe_calloc - Allocate a block of memory from the application heap, clearing 56 | all data to zero and checking for out or memory errors. 57 | 58 | ------------------------------------------------------------------------------- 59 | */ 60 | 61 | void *Safe_calloc(size_t Elements, size_t Size); 62 | 63 | /* 64 | ------------------------------------------------------------------------------- 65 | Safe_malloc - Allocate a block of memory from the application heap 66 | and checking for out or memory errors. 67 | 68 | ------------------------------------------------------------------------------- 69 | */ 70 | 71 | void *Safe_malloc(size_t Size); 72 | 73 | /** Replacement for Safe_malloc that also zeros memory. To make it 74 | * interchangable. 75 | */ 76 | void *Safe_alloc(size_t Size); 77 | 78 | /** Function to make the replacements complete. 79 | */ 80 | void Safe_free(void *p); 81 | 82 | /** Creates a copy of a string with specified length in a safe way. 83 | */ 84 | char *Safe_strndup(const char *sz, size_t len); 85 | 86 | /** Creates a copy of a string in a safe way. 87 | */ 88 | char *Safe_strdup(const char *sz); 89 | 90 | /** Logs the allocated memory 'p' in the given trace for batch freeing 91 | later using freeTrace. 92 | */ 93 | void *traceAlloc(allocTrace *ptrace, void *p); 94 | 95 | /** Frees all the memory logged in the trace and resets the trace. 96 | */ 97 | void freeTrace(allocTrace *ptrace); 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/util/system.h: -------------------------------------------------------------------------------- 1 | /* 2 | system.h - includes, required by findme.c 3 | 4 | Copyright (c) 2004 Borut Razem 5 | 6 | This software is provided 'as-is', without any express or implied 7 | warranty. In no event will the authors be held liable for any damages 8 | arising from the use of this software. 9 | 10 | Permission is granted to anyone to use this software for any purpose, 11 | including commercial applications, and to alter it and redistribute it 12 | freely, subject to the following restrictions: 13 | 14 | 1. The origin of this software must not be misrepresented; you must not 15 | claim that you wrote the original software. If you use this software 16 | in a product, an acknowledgment in the product documentation would be 17 | appreciated but is not required. 18 | 2. Altered source versions must be plainly marked as such, and must not be 19 | misrepresented as being the original software. 20 | 3. This notice may not be removed or altered from any source distribution. 21 | 22 | Borut Razem 23 | borut.razem@siol.net 24 | */ 25 | 26 | #ifndef _SYSTEM_H 27 | #define _SYSTEM_H 28 | 29 | /* findme.c is compiled only on *nix, so includes are *nix specific */ 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #define xstrdup(_str) strdup(_str) 36 | 37 | #endif /* _SYSTEM_H */ 38 | -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | #ifndef KCC_VERSION_H_ 2 | #define KCC_VERSION_H_ 3 | 4 | // TODO: generate this with CMake from Git 5 | 6 | #define KCC_VERSION_HI 4 7 | #define KCC_VERSION_LO 0 8 | #define KCC_VERSION_P 4 9 | #define KCC_VERSION_STR "4.0.4" 10 | 11 | #endif 12 | --------------------------------------------------------------------------------