Compare commits

...

265 Commits

Author SHA1 Message Date
Pavel R. 7adbc171f6 changed types to strict (nil disallowed) in lcode.c
3 years ago
Pavel R. 072d2c37f0 Fixed possibility to initialize empty strings (and booleans)
3 years ago
Pavel R. 21fd437e89 added missing optional types opcodes to JIT interface
3 years ago
annelin 73de201165 added new (optional) types to lparser.c (no idea what does it affect)
3 years ago
annelin be65484feb Removed RAVI_DEFER_STATEMENT define (there are no reasons to disable it)
3 years ago
annelin 7d376acf62 Added `debug.settype(typ, metatable)` function
3 years ago
Pavel R. 3995761bf1 Add README.md
3 years ago
Pavel R. 5359ca1d5f - Added boolean type
3 years ago
Dibyendu Majumdar d022074ae6 Update Lua 5.4.3 defer patch - minor change to remove some leftover stuff
3 years ago
Dibyendu Majumdar cf3be2e688
Update README.rst
3 years ago
Dibyendu Majumdar bbf2c29077 Lua 5.4.3 defer statement patch
3 years ago
Dibyendu Majumdar 2c81edafa0 issue #169 Sync with upstream project
3 years ago
Dibyendu Majumdar b073242254 issue #198 Sync with upstream project
3 years ago
Dibyendu Majumdar 6eb43324dd issue #169 Add GNUInstallDirs
3 years ago
Dibyendu Majumdar 4bfc061a2a issue #169 Apply upstream fixes
3 years ago
Dibyendu Majumdar 3efaddee6b issue #222 Lua 5.4 change for bitwise ops
3 years ago
Dibyendu Majumdar d5e324fd53 issue #217 fix the ravicomp compiler to use the same typecodes as Ravi
3 years ago
Dibyendu Majumdar e3d8203bd9 Refactor
3 years ago
Dibyendu Majumdar 53ec0c19b3
Merge pull request #218 from XmiliaH/bump-binary-version
3 years ago
XmiliaH 5ca801596a Bump binary version & smaller sizes for stripped binaries
3 years ago
Dibyendu Majumdar 58980db5cb issue #217 define ravitype_t in terms of the new values
3 years ago
Dibyendu Majumdar 347ae985bc
Merge pull request #213 from XmiliaH/type-maps
3 years ago
Dibyendu Majumdar 063a55604e
Merge branch 'new_type_info' into type-maps
3 years ago
Dibyendu Majumdar 8e815bd67a issue #215 adapt fix by XmiliaH from pull request
3 years ago
Dibyendu Majumdar 658f04c3d8 issue #215 adapt fix by XmiliaH from pull request
3 years ago
Dibyendu Majumdar 8fd3a1bbab issue #214 since we haven't implemented boolean type annotation fully, the parser will no longer recognize the :boolean annotation.
3 years ago
Dibyendu Majumdar b5afdfaa46 issue #215 The top level check v->ravi_type != vartype is not correct as it means we miss out checking scenario where v->k == VINDEXED.
3 years ago
Dibyendu Majumdar 88ccaf34a0 Reformat
3 years ago
Dibyendu Majumdar 5c30d255c7 some improvements to type checking via XmiliaH
3 years ago
Dibyendu Majumdar 248c730c43 refactoring via XmiliaH
3 years ago
Dibyendu Majumdar 4a20693671 refactoring via XmiliaH
3 years ago
Dibyendu Majumdar cb6943a1eb tests updated
3 years ago
XmiliaH 837dc959cf
Merge branch 'master' into type-maps
3 years ago
Dibyendu Majumdar 754fcefc26
Merge pull request #212 from XmiliaH/some-improvements
3 years ago
XmiliaH b4359b9391 Cleanup and Fixes
3 years ago
XmiliaH a9537957d5 Remove old ravi_type_t from jit
3 years ago
XmiliaH 435480f4db Better deduction for not
3 years ago
XmiliaH 62ab591343 Fix concat
3 years ago
XmiliaH f80e4d5442 Fix concat
3 years ago
XmiliaH 7789f4f32d Finish type maps
3 years ago
XmiliaH c0122cd816 FIx tests
3 years ago
XmiliaH 58cdc8d7dc RAVI_TSTRINGs can be nil
3 years ago
XmiliaH 6af3d804a4 First part for type maps
3 years ago
XmiliaH 871b76fea2 Format changed code
3 years ago
XmiliaH 0b43c94a4d Use the right enum for opcodes
3 years ago
XmiliaH e85634270f Add back that len of table is int and fix tests.
3 years ago
XmiliaH 4cce67ec13 Improve type deduction
3 years ago
Dibyendu Majumdar a2ec53624d issue #211 since the up-value carries the type of the local variable, we can safely infer that the result of a get on array is a primitive type
3 years ago
Dibyendu Majumdar 9bceadd099 issue #211 since the up-value carries the type of the local variable, we can safely infer that the result of a get on array is a primitive type
3 years ago
Dibyendu Majumdar 25dbc31393 issue #211 since the up-value carries the type of the local variable, we can safely infer that the result of a get on array is a primitive type
3 years ago
Dibyendu Majumdar 2c5b958d04 issue #211 since the up-value carries the type of the local variable, we can safely infer that the result of a get on array is a primitive type
3 years ago
Dibyendu Majumdar b0a5b01142 issue #211 The type of update index op is not known.
3 years ago
Dibyendu Majumdar 170fd797a2 It seems that we don't really need this - must be the bug was elsewhere
3 years ago
Dibyendu Majumdar b2cc7c30c5 issue #210 tests
3 years ago
Dibyendu Majumdar 2decef927a issue #210 tests
3 years ago
Dibyendu Majumdar 486145900b issue #208 check for overflow when resizing array
3 years ago
Dibyendu Majumdar a3b933aa43 issue #208 check for overflow when resizing array
3 years ago
Dibyendu Majumdar 1e8597de7d issue #210 fix a test
3 years ago
Dibyendu Majumdar 9ced7e2bc0 issue #210 bug in recognizing the type change when an expression of VINDEXED type gets resolved
3 years ago
Dibyendu Majumdar fe7c76fff5 issue #207 add test
3 years ago
Dibyendu Majumdar ad4fc4e2d2 issue #207 check size more carefully when creating a slice
3 years ago
Dibyendu Majumdar 2c44bdd68b issue #208 add test
3 years ago
Dibyendu Majumdar 8bd404f62e issue #208 check for size overflow when creating integer/number array
3 years ago
Dibyendu Majumdar 4342fc7630 issue #210 #209 tests
3 years ago
Dibyendu Majumdar 927ddbf6a0 issue #210 LEN on any value other than array or table should be any type
3 years ago
Dibyendu Majumdar b549302d70 issue #209 BNOT on any value other than integer should result in any type
3 years ago
Dibyendu Majumdar 56a59a1f31 issue #169 apply latest upstream changes
3 years ago
Dibyendu Majumdar 773ebd9d32 issue #169 Update MIR sources - includes a memory leak bug fix
3 years ago
Dibyendu Majumdar def4d76ac9 Remove cmake branch from build.yml
3 years ago
Dibyendu Majumdar ef24ca67cb Merge branch 'master' of https://github.com/dibyendumajumdar/ravi
3 years ago
Dibyendu Majumdar 77cd6b9527 Update copyright notices
3 years ago
Dibyendu Majumdar 61a8ac889f Update docs
3 years ago
Dibyendu Majumdar 102c8bee8b Update copyright notices
3 years ago
Dibyendu Majumdar 3e05644f51 issue #198 Cleanup
3 years ago
Dibyendu Majumdar f7f59eed0f issue #198 Cleanup
3 years ago
Dibyendu Majumdar 2aeeea4dd3 issue #198 Include Ravi Compiler
3 years ago
Dibyendu Majumdar 31774723ff Merge branch 'cmake'
3 years ago
Dibyendu Majumdar cc0c098011 CMake refactoring
3 years ago
Dibyendu Majumdar f072326ea4 CMake build refactoring
3 years ago
Dibyendu Majumdar 66615703a6 Merge branch 'master' of https://github.com/dibyendumajumdar/ravi
3 years ago
Dibyendu Majumdar ef30fb2065
Update build.yml
3 years ago
Dibyendu Majumdar 2335973259
Update build.yml
3 years ago
Dibyendu Majumdar fae2a2bf77 issue #186 leftover cleanup
3 years ago
Dibyendu Majumdar 08c05100cf issue #203 leftover cleanup
3 years ago
Dibyendu Majumdar 3b09a22e96 issue #204 Code reorg
3 years ago
Dibyendu Majumdar 1f1d8cb428 issue #198 Add tests
3 years ago
Dibyendu Majumdar 9083492dcb issue #198 Add a test
3 years ago
Dibyendu Majumdar e6890743f0 issue #169 Update MIR
3 years ago
Dibyendu Majumdar 9cc59144ad issue #195 lstrlib
3 years ago
Dibyendu Majumdar f27792f050 issue #195 strings tests part 7
3 years ago
Dibyendu Majumdar df748ee844 issue #195 strings tests part 6
3 years ago
Dibyendu Majumdar ed90926c8d issue #195 strings tests part 5
3 years ago
Dibyendu Majumdar 1fb5b08491 issue #195 strings tests part 4
3 years ago
Dibyendu Majumdar facb56e0c1 issue #195 strings tests part 3
3 years ago
Dibyendu Majumdar 9a86f11bc3 issue #195 strings tests part 2
3 years ago
Dibyendu Majumdar 92fd0e3faf issue #195 strings tests part 1
3 years ago
Dibyendu Majumdar 54fc5277d6 issue #195 vararg tests part 2
3 years ago
Dibyendu Majumdar c11122376e issue #195 vararg tests part 1
3 years ago
Dibyendu Majumdar 36639d863a issue #196 reformat
3 years ago
Dibyendu Majumdar 71644f5450 issue #196 use a macro for slices
3 years ago
Dibyendu Majumdar b717be20e0 Fix a missing check
3 years ago
Dibyendu Majumdar 249f22c215 issue #196 Another test restored to 5.3 version.
3 years ago
Dibyendu Majumdar 2f76a1e869 issue #196 GC upvalue/thread cycle test reverted to 5.3 version due to difference in behaviour in Lua 5.4 (as up-values are not reference counted anymore).
3 years ago
Dibyendu Majumdar 4acc325c97 issue #196 Fix test case
3 years ago
Dibyendu Majumdar ec2d27a7dc issue #196 Fix test case
3 years ago
Dibyendu Majumdar 7320131275 Merge branch 'master' of https://github.com/dibyendumajumdar/ravi
3 years ago
Dibyendu Majumdar f9c4b5dbec issue #203 Removing LLVM support, see llvm branch for archived version
3 years ago
Dibyendu Majumdar 0c3277ad4a
issue #203 Doc update
3 years ago
Dibyendu Majumdar d6422fe2e3
Update .travis.yml
3 years ago
Dibyendu Majumdar 66511033fd issue #203 Removing LLVM support, see llvm branch for archived version
3 years ago
Dibyendu Majumdar 05f365352c issue #169 Fix issue on ARM64
3 years ago
Dibyendu Majumdar 219d44c2ba issue #196 Revise upval barrier code - TBC
3 years ago
Dibyendu Majumdar e4a240be77 add assertions
3 years ago
Dibyendu Majumdar 2ace67282d issue #196 Undo a change that was not needed
3 years ago
Dibyendu Majumdar 6909d79f61 Merge branch 'master' of https://github.com/dibyendumajumdar/ravi
3 years ago
Dibyendu Majumdar 16ea0643cd issue #202 Prepare for testing on different archs
3 years ago
Dibyendu Majumdar a83afe2d02
Update build.yml
3 years ago
Dibyendu Majumdar d5668379b1
Update build.yml
3 years ago
Dibyendu Majumdar 849819e891
Update build.yml
3 years ago
Dibyendu Majumdar 53ff35455a issue #198 Updated interface to the compiler lib
3 years ago
Dibyendu Majumdar f9acba8142 issue #169 MIR update
3 years ago
Dibyendu Majumdar 389c98ee35
Merge pull request #200 from dibyendumajumdar/lua542-gc
3 years ago
Dibyendu Majumdar e9cb48e15c issue #196 Update GC code from Lua 5.4.2
3 years ago
Dibyendu Majumdar f346122073 issue #196 Update GC code from Lua 5.4.2
3 years ago
Dibyendu Majumdar 001dceb996 issue #198 Initial support for AOT compiled code
3 years ago
Dibyendu Majumdar 0f6a4084ae issue #198 Refactor
3 years ago
Dibyendu Majumdar 95ac6123a9 issue #198 Refactored api that puts all of the codegen at the compiler end, making the way for an AOT solution
3 years ago
Dibyendu Majumdar 8d6e403f30 issue #198 Refactored api that puts all of the codegen at the compiler end, making the way for an AOT solution
3 years ago
Dibyendu Majumdar bb218051ba Add support for codespaces
4 years ago
Dibyendu Majumdar bc4142428c issue #198 add expected results for the tests
4 years ago
Dibyendu Majumdar 86c2020411 issue #198 more tests
4 years ago
Dibyendu Majumdar 5a0c3600fc issue #198 add test
4 years ago
Dibyendu Majumdar a54f156304 issue #198 add test
4 years ago
Dibyendu Majumdar 8cec4cc827 issue #198 More tests
4 years ago
Dibyendu Majumdar a82d42b847 issue #169 MIR update
4 years ago
Dibyendu Majumdar a3bf9dc10e issue #198 add another test for sieve - but using while loop
4 years ago
Dibyendu Majumdar ea6c408c97 issue #198 tests for farray opcodes
4 years ago
Dibyendu Majumdar 487624cee9 issue #198 tests for iarray opcodes
4 years ago
Dibyendu Majumdar e361bd7387 issue #198 add luaD_growstack to the list of linked functions in the JIT
4 years ago
Dibyendu Majumdar 69840eacdb issue #198 Tests for op_call instruction - couple fail due to missing support for multiret in return
4 years ago
Dibyendu Majumdar d0b3ed989b issue #169 Enable MIR on Windows
4 years ago
Dibyendu Majumdar f6378c97b4 issue #169 Apply upstream changes
4 years ago
Dibyendu Majumdar 7f94078e8e issue #169 update MIR sources from upstream
4 years ago
Dibyendu Majumdar 174cfa0168 issue #198 add tests for op_loadglobal, op_storeglobal
4 years ago
Dibyendu Majumdar 523f07ba57 issue #198 initialize the _ENV upvalue
4 years ago
Dibyendu Majumdar 71bb74f773 Merge branch 'ravi-compiler'
4 years ago
Dibyendu Majumdar 6b273f7468 issue #198 Make the MIR portion of the compiler optional so that we can just get the C codegen
4 years ago
Dibyendu Majumdar a3940b0120 Add link to the VSCode debugger
4 years ago
Dibyendu Majumdar b1f36a56e1 Merge branch 'ravi-compiler' of https://github.com/dibyendumajumdar/ravi into ravi-compiler
4 years ago
Dibyendu Majumdar 6daf1a5529 Add link to the VSCode debugger
4 years ago
Dibyendu Majumdar 4819f38a80 issue #198 Test cases for op_mov, op_br, op_cbr
4 years ago
Dibyendu Majumdar 4f7cab694c issue #198 Test case for op_mov
4 years ago
Dibyendu Majumdar d65beddb75 issue #198 Test case for op_ret
4 years ago
Dibyendu Majumdar 45f823b604 issue #198 Missing initializer for proto->upvalues[i].usertype when usertype is NULL
4 years ago
Dibyendu Majumdar a45eaa8a24 issue #198 Cmake build failing to find c2mir header
4 years ago
Dibyendu Majumdar 902f5c1653 Comments
4 years ago
Dibyendu Majumdar 48617fda44 issue #198 WIP add api functions for setting some proto attributes
4 years ago
Dibyendu Majumdar fba87f24f1 issue #198 WIP add api for error reporting and generating debug messages
4 years ago
Dibyendu Majumdar 90a26a4b88 issue #198 WIP add api for marking a proto as var arg
4 years ago
Dibyendu Majumdar 0f698f354c issue #198 WIP add api for adding an upvalue. Hook up the compiler library.
4 years ago
Dibyendu Majumdar 7515ef9d89 Merge branch 'master' into ravi-compiler
4 years ago
Dibyendu Majumdar 2a6c5575e3 issue #198 WIP revise the api for compiling C code using MIR
4 years ago
Dibyendu Majumdar 98c96c11eb issue #198 WIP flesh out some more api functions
4 years ago
Dibyendu Majumdar 2cab1f104a issue #198 WIP flesh out some more api functions
4 years ago
Dibyendu Majumdar be67d117c2 Merge branch 'master' into ravi-compiler
4 years ago
Dibyendu Majumdar 430f9a532b issue #169 preparation for ravicomp integration
4 years ago
Dibyendu Majumdar e20df095df issue #169 Fix builds failure
4 years ago
Dibyendu Majumdar 90f54987eb issue #169 Update MIR to latest version
4 years ago
Dibyendu Majumdar cde0a39bc2 issue #169 Refactor the c2mir invocation so that we can reuse this when integrating with ravicomp library.
4 years ago
Dibyendu Majumdar 16d59f65ee issue #169 Add include directories of MIR to help CLion find them
4 years ago
Dibyendu Majumdar 534abc7525 issue #169 fix memory leak
4 years ago
Dibyendu Majumdar 02a7796f77 issue #198 WIP
4 years ago
Dibyendu Majumdar 34c6b33a2f issue #198 WIP add interface to RaviCompiler project
4 years ago
Dibyendu Majumdar 0d22f81b2a Merge branch 'master' of https://github.com/dibyendumajumdar/ravi
4 years ago
Dibyendu Majumdar ee056a1bd6 Comment added aboit upvalues
4 years ago
Dibyendu Majumdar 40e020916a
Update README.rst
4 years ago
Dibyendu Majumdar 57f6fc82f7
Update README.rst
4 years ago
Dibyendu Majumdar c4535d5d9f
Update README.rst
4 years ago
Dibyendu Majumdar 940a80d9bb On returning from a function the results are copied to the registers starting at at the function's reference in CallInfo->func
4 years ago
Dibyendu Majumdar 4d348e0609 Update readme / intro
4 years ago
Dibyendu Majumdar f76b4690f0 Initial patch to implement 'defer' statement in Lua 5.4
4 years ago
Dibyendu Majumdar 42cfa54e9e Initial patch to implement 'defer' statement in Lua 5.4
4 years ago
Dibyendu Majumdar 81555acc72 Update docs to correctly state the default garbage collector.
4 years ago
Dibyendu Majumdar 7e219f76bd Lua 5.3 patch that implements 'defer' statement
4 years ago
Dibyendu Majumdar 8b854b0a02 Lua 5.3 patch that implements 'defer' statement
4 years ago
Dibyendu Majumdar 920cd2dab8 issue #196 test case for the gen GC bug
4 years ago
Dibyendu Majumdar b73322ad16 issue #157 Detail
4 years ago
Dibyendu Majumdar 844b15683b issue #196 When an object aged OLD1 is finalized, it is moved from the list 'finobj' to the *beginning* of the list 'allgc'. So, this part of the
4 years ago
Dibyendu Majumdar 63bf14b43c issue #169 Merge latest MIR code from upstream
4 years ago
Dibyendu Majumdar 73d6bc1c07 issue #195 Some improvements to Makefile build - based on Lua 5.4 build improvements
4 years ago
Dibyendu Majumdar c42ac0e9fa issue #196 don't make generational GC the default yet - various issues reported on Lua mailing list.
4 years ago
Dibyendu Majumdar d26e3626b9 issue #182 ASAN support must be explicitly enabled as not all installations have asan installed
4 years ago
Dibyendu Majumdar f8a680ed82 Merge branch 'master' of https://github.com/dibyendumajumdar/ravi
4 years ago
Dibyendu Majumdar 4bbcb908ec issue #157 fix build error on windows
4 years ago
Dibyendu Majumdar 7f63b9fae7 issue #182 add asan support if available
4 years ago
Dibyendu Majumdar 3a75ee9eb7 Merge branch 'master' of https://github.com/dibyendumajumdar/ravi
4 years ago
Dibyendu Majumdar cdd6fbfeaa issue #182: remove commented lines
4 years ago
Dibyendu Majumdar 73c2c6426f issue #163 Maintain optionality of defer statement
4 years ago
Dibyendu Majumdar b63005fd3f issue #163 Couple of more tests for coroutines and deferred functions, plus some changes in ldo.c back-ported from Lua 5.4
4 years ago
Dibyendu Majumdar e832dcc32f issue #163 Fix issue with handling of deferred functions when a Lua thread is closed.
4 years ago
Dibyendu Majumdar d8a60ddd23 issue #163 Split out defer tests to a separate file. Also backport a few tests from Lua 5.4
4 years ago
Dibyendu Majumdar bf2f55eece issue #163 Do not generate TAILCALL opcode if a defer closure is in scope; back-ported from Lua 5.4.
4 years ago
Dibyendu Majumdar 9c745caafe issue #157 Doc updates
4 years ago
Dibyendu Majumdar 2934cbe5c0 issue #157 Add Ravi api functions to return JIT name and options
4 years ago
Dibyendu Majumdar 7dd5c1fdf0 issue #157 cleanup
4 years ago
Dibyendu Majumdar 9e2a4f4645 issue #163 Fix bug in OP_RETURN in interpreter and MIR JIT backend; we need to reload RA after call to luaF_close() as stack may been reallocated
4 years ago
Dibyendu Majumdar e483fe40ee
Update ravi-reference.rst
4 years ago
Dibyendu Majumdar 7e26dc8d0f issue #195 number and integer comparisons
4 years ago
Dibyendu Majumdar 0e41a51114 issue #195 number and integer conversions
4 years ago
Dibyendu Majumdar f884782a60 issue #195 backport luaO_pushvfstring
4 years ago
Dibyendu Majumdar 2861754b3c issue #195 backport luaO_pushvfstring
4 years ago
Dibyendu Majumdar 22d84e74d0 issue #195 backport luaO_pushvfstring
4 years ago
Dibyendu Majumdar f547edd330 issue #195 lexer / utf8 improvements from Lua 5.4
4 years ago
Dibyendu Majumdar d4992e8d08 Revert "issue #195 Misc updates from Lua 5.4"
4 years ago
Dibyendu Majumdar 4795374610 issue #195 Misc updates from Lua 5.4
4 years ago
Dibyendu Majumdar 93c0a0c61e issue #196 doc updates
4 years ago
Dibyendu Majumdar 4ccc2759e8
Add information regarding Lua 5.4
4 years ago
Dibyendu Majumdar 062550b84d issue #196 backport generational GC from Lua 5.4
4 years ago
Dibyendu Majumdar f4752a513f issue #195: move upvalue struct to lobject.h as in Lua 5.4
4 years ago
Dibyendu Majumdar e0881115e4 issue #195: lua tests update
4 years ago
Dibyendu Majumdar 2eb4daf7ff issue #192 when searching for values in table use raw key comparison; back ported from Lua 5.4
4 years ago
Dibyendu Majumdar d2a295688f issue #195 lua 5.4 object.h layout for easier comparison
4 years ago
Dibyendu Majumdar d2b9810a06 issue #193 Lua 5.4 string library improvements back-ported
4 years ago
Dibyendu Majumdar a2e0c2fc3d issue #191 #193 backport random number generator from Lua 5.4
4 years ago
Dibyendu Majumdar bf5aa3e3f6 issue #169 update MIR code from upstream
4 years ago
Dibyendu Majumdar 4d6f9dd9f2 issue #99 test case
4 years ago
Dibyendu Majumdar cf7f8ed380 issue #157 remove redundant test script
4 years ago
Dibyendu Majumdar ff91fbfc8d issue #169 details
4 years ago
Dibyendu Majumdar 3cf60d2972 Fix travis build
4 years ago
Dibyendu Majumdar 18ff6c1f36 issue #157 Long overdue reorg of tests, much more needs to be done, but this is a start
4 years ago
Dibyendu Majumdar 5f286815ed issue #169 Update to latest MIR code
4 years ago
Dibyendu Majumdar 76f9bbdffb issue #99 Merge splitting out of the RaviArray structure from Table
4 years ago
Dibyendu Majumdar a8ee5a60e1 issue #99 LLVM JIT updates to support RaviArray breakout from Table structure
4 years ago
Dibyendu Majumdar 0d2b3161e3
Delete FUNDING.yml
4 years ago
Dibyendu Majumdar f3886accbe issue #99 remove blank
4 years ago
Dibyendu Majumdar e16310f742 issue #99 Fix missing field in GCUnion
4 years ago
Dibyendu Majumdar 4b34875605 issue #99 Use dedicated structure for Ravi array types
4 years ago
Dibyendu Majumdar eb3d9ca72d Merge branch 'master' of https://github.com/dibyendumajumdar/ravi
4 years ago
Dibyendu Majumdar a5759bbb25 issue #188
4 years ago
Dibyendu Majumdar 71e5bd8d8c issue #169 MIR update
4 years ago
Dibyendu Majumdar 6f7313594c issue #188 update docs
4 years ago
Dibyendu Majumdar 83e0a739b0 issue #188 add missing symbol
4 years ago
Dibyendu Majumdar 23141174d4 issue #169 Update to latest MIR codebase and set default opt level to 2
4 years ago
Dibyendu Majumdar 6500e11c01 issue #184
4 years ago
Dibyendu Majumdar 59f92f04df issue #184 first pass revision of OP_TEST and OP_TESTSET
4 years ago
Dibyendu Majumdar b317b19c3c issue #184 first pass revision of OP_TEST and OP_TESTSET
4 years ago
Dibyendu Majumdar 0ff5baa1a5 issue #184 first pass revision of OP_TEST and OP_TESTSET
4 years ago
Dibyendu Majumdar 9202468bb7 issue #188 Fix missing symbol registrations
4 years ago
Dibyendu Majumdar 89b9451437 issue #188
4 years ago
Dibyendu Majumdar 9db31dabd8 issue #187
4 years ago
Dibyendu Majumdar 2edf9f6936 issue #187
4 years ago
Dibyendu Majumdar d39da2757e
issue #187
4 years ago
Dibyendu Majumdar 9b8f89dad0
issue #187
4 years ago
Dibyendu Majumdar edcec3a4cd
issue #187
4 years ago
Dibyendu Majumdar 5d0b594135
issue #187
4 years ago
Dibyendu Majumdar 10ca66a4fd
issue #187
4 years ago
Dibyendu Majumdar f5cc3fdfcf issue #175
4 years ago
Dibyendu Majumdar 4e53c74180 issue #175
4 years ago
Dibyendu Majumdar 4cc6fcf8b0 issue #186
4 years ago
Dibyendu Majumdar 3253283648 issue #186
4 years ago
Dibyendu Majumdar bcc094d953 issue #186
4 years ago
Dibyendu Majumdar 0e1815b3e5 issue #98
4 years ago
Dibyendu Majumdar bfdb4937b3 issue #98
4 years ago
Dibyendu Majumdar 352f03ad61 issue #186
4 years ago
Dibyendu Majumdar 5834e4c78f issue #98 removing new parser code as migrated to ravi-compiler project
4 years ago

@ -0,0 +1,7 @@
# [Choice] Debian / Ubuntu version: debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
ARG VARIANT=buster
FROM mcr.microsoft.com/vscode/devcontainers/cpp:dev-${VARIANT}
# [Optional] Uncomment this section to install additional packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>

@ -0,0 +1,12 @@
# [Choice] Debian / Ubuntu version: debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
ARG VARIANT=buster
FROM mcr.microsoft.com/vscode/devcontainers/base:${VARIANT}
# Install needed packages. Use a separate RUN statement to add your own dependencies.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install build-essential cmake cppcheck valgrind clang lldb llvm gdb \
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>

@ -0,0 +1,28 @@
{
"name": "C++",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
"args": { "VARIANT": "debian-10" }
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-vscode.cpptools"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "gcc -v",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}

@ -1,8 +0,0 @@
# These are supported funding model platforms
github: dibyendumajumdar # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
custom: # Replace with a single custom sponsorship URL

@ -0,0 +1,48 @@
name: build
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: sudo apt-get install -y libreadline-dev
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Configure CMake
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash
working-directory: ${{runner.workspace}}/build
# Note the current convention is to use the -S and -B options here to specify source
# and build directories, but this is only available with CMake 3.13 and higher.
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash
# Execute the build. You can specify a specific target with "--target <NAME>"
run: cmake --build . --config $BUILD_TYPE
- name: Test
shell: bash
run: cd tests && sh run_tests.sh ${{runner.workspace}}/build/ravi

@ -3,24 +3,18 @@ os:
- linux
arch:
- amd64
- arm64
compiler:
- gcc
cache: ccache
dist: bionic
dist: focal
addons:
apt:
packages:
- g++
- gcc
- ccache
install:
- curl https://releases.llvm.org/6.0.1/clang+llvm-6.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz | tar -xJf -
script:
- mkdir $TRAVIS_BUILD_DIR/build
- cd $TRAVIS_BUILD_DIR/build && cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_DIR=$TRAVIS_BUILD_DIR/clang+llvm-6.0.1-x86_64-linux-gnu-ubuntu-16.04/lib/cmake/llvm -G "Unix Makefiles" -DLLVM_JIT=ON ..
- cd $TRAVIS_BUILD_DIR/build && make
- cd $TRAVIS_BUILD_DIR/lua-tests && sh ./run_travis_tests.sh $TRAVIS_BUILD_DIR/build/ravi
- mkdir $TRAVIS_BUILD_DIR/buildmir
- cd $TRAVIS_BUILD_DIR/buildmir && cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" -DMIR_JIT=ON ..
- cd $TRAVIS_BUILD_DIR/buildmir && cmake -DCMAKE_BUILD_TYPE=Debug -DLTESTS=ON -DMIR_JIT=ON -G "Unix Makefiles" ..
- cd $TRAVIS_BUILD_DIR/buildmir && make
- cd $TRAVIS_BUILD_DIR/lua-tests && sh ./run_travis_tests.sh $TRAVIS_BUILD_DIR/buildmir/ravi
- cd $TRAVIS_BUILD_DIR/tests && sh ./run_tests.sh $TRAVIS_BUILD_DIR/buildmir/ravi

@ -1,39 +1,22 @@
cmake_minimum_required(VERSION 3.12)
project(Ravi VERSION 1.0.4 LANGUAGES C CXX)
project(Ravi VERSION 1.0.4 LANGUAGES C)
# Get access to CMake helpers
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
# By default MIR JIT backend is automatically enabled. To disable user must specify
# NO_JIT=ON
option(LLVM_JIT "Controls whether LLVM JIT compilation will be enabled, default is OFF" OFF)
option(OMR_JIT "Controls whether NanoJIT compilation will be enabled, default is OFF" OFF)
option(NO_JIT "Controls whether JIT should be disabled, default is OFF" OFF)
option(STATIC_BUILD "Build static version of Ravi, default is OFF" OFF)
option(COMPUTED_GOTO "Controls whether the interpreter switch will use computed gotos on gcc/clang, default is ON" ON)
option(LTESTS "Controls whether ltests are enabled in Debug mode; note requires Debug build" ON)
option(ASAN "Controls whether address sanitizer should be enabled" OFF)
option(RAVICOMP "Controls whether to link in RaviComp" ON)
if (LLVM_JIT AND OMR_JIT)
message(FATAL_ERROR
"LLVM_JIT and OMR_JIT cannot be set to ON at the same time")
endif ()
# By default on X86_64 non-Windows platforms we enable MIR JIT
if (NOT WIN32
AND NOT LLVM_JIT
AND NOT OMR_JIT
AND NOT NO_JIT
AND CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
# By we enable MIR JIT
if (NOT NO_JIT)
set(MIR_JIT ON)
endif ()
if (MIR_JIT)
if (MSVC OR WIN32)
message(FATAL_ERROR "MIR_JIT is not supported when using MSVC and/or WIN32")
endif ()
if (NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)"))
message(FATAL_ERROR "MIR_JIT is only supported on X86-64 platforms")
endif ()
set(LLVM_JIT OFF)
set(OMR_JIT OFF)
set(STATIC_BUILD OFF) # Because we need to expose the symbols in the library
endif ()
@ -52,47 +35,19 @@ endif ()
include_directories("${PROJECT_SOURCE_DIR}/include")
# define the Lua core source files
set(RAVI_AST_SOURCES src/ravi_ast_parse.c src/ravi_ast_print.c src/ravi_ast_typecheck.c)
set(LUA_CORE_SRCS src/lapi.c src/lcode.c src/lctype.c src/ldebug.c src/ldo.c src/ldump.c
src/lfunc.c src/lgc.c src/llex.c src/lmem.c src/lobject.c src/lopcodes.c
src/lparser.c src/lstate.c src/lstring.c src/ltable.c src/ltm.c src/lundump.c
src/lvm.c src/lzio.c src/ravi_jit.c src/ltests.c src/ravi_profile.c
src/ravi_membuf.c src/ravi_jitshared.c src/bit.c src/ravi_alloc.c
${RAVI_AST_SOURCES})
src/ravi_membuf.c src/ravi_jitshared.c src/bit.c src/ravi_alloc.c)
# define the Lua library source files
set(LUA_LIB_SRCS src/lauxlib.c src/lbaselib.c src/lbitlib.c src/lcorolib.c src/ldblib.c src/liolib.c
src/lmathlib.c src/loslib.c src/ltablib.c src/lstrlib.c src/loadlib.c src/linit.c src/lutf8lib.c)
set(LUA_HEADERS include/lua.h include/luaconf.h include/lualib.h include/lauxlib.h)
# LLVM code gen
set(LLVM_JIT_SRCS src/ravi_llvmjit.cpp src/ravi_llvmtypes.cpp
src/ravi_llvmcodegen.cpp src/ravi_llvmforprep.cpp src/ravi_llvmcomp.cpp
src/ravi_llvmreturn.cpp src/ravi_llvmload.cpp src/ravi_llvmforloop.cpp
src/ravi_llvmarith1.cpp src/ravi_llvmcall.cpp src/ravi_llvmtable.cpp
src/ravi_llvmarith2.cpp src/ravi_llvmtforcall.cpp src/ravi_llvmrest.cpp)
# MIR sources
set(MIR_HEADERS mir/mir.h mir/mir-gen.h mir/mir-varr.h mir/mir-dlist.h mir/mir-htab.h
mir/mir-hash.h mir/mir-bitmap.h)
set(MIR_SRCS mir/mir.c mir/mir-gen.c)
set(C2MIR_SRCS mir/c2mir/c2mir.c)
# OMR code gen
set(OMR_JIT_SRCS src/ravi_omrjit.c src/ravi_omrjitapi.c)
# MIR code gen
set(MIR_JIT_SRCS src/ravi_mirjit.c)
set(NO_JIT_SRCS src/ravi_nojit.c)
# Common stuff we need even if we don't use dmrC.
set(DMR_C_HEADERS_COMMON dmr_c/src/allocate.h dmr_c/src/port.h dmr_c/src/ptrlist.h)
set(DMR_C_SRCS_COMMON dmr_c/src/allocate.c dmr_c/src/ptrlist.c)
# dmrC Optional sources
set(RAVI_C_SYMBOL_PARSER src/ravi_dmrc_parsesymbols.c)
set(DMR_C_SRCS_OPT dmr_c/src/builtin.c dmr_c/src/char.c dmr_c/src/expression.c dmr_c/src/evaluate.c
dmr_c/src/expand.c dmr_c/src/inline.c dmr_c/src/lib.c dmr_c/src/linearize.c
dmr_c/src/liveness.c dmr_c/src/parse.c dmr_c/src/target.c dmr_c/src/tokenize.c
dmr_c/src/pre-process.c dmr_c/src/scope.c dmr_c/src/show-parse.c dmr_c/src/symbol.c
dmr_c/src/walksymbol.c)
set(DMR_C_HEADERS_OPT dmr_c/src/char.h dmr_c/src/expression.h dmr_c/src/flow.h dmr_c/src/ident-list.h
dmr_c/src/linearize.h dmr_c/src/lib.h dmr_c/src/parse.h dmr_c/src/scope.h dmr_c/src/symbol.h
dmr_c/src/target.h dmr_c/src/token.h dmr_c/src/walksymbol.h)
set(LUA_CMD_SRCS src/lua.c)
set(RAVICOMP_SRCS src/ravi_complib.c)
file(GLOB RAVI_HEADERS "${PROJECT_SOURCE_DIR}/include/*.h")
if (COMPUTED_GOTO AND NOT MSVC)
@ -106,127 +61,35 @@ endif ()
include(CheckCCompilerFlag)
check_c_compiler_flag("-march=native" COMPILER_OPT_ARCH_NATIVE_SUPPORTED)
if (COMPILER_OPT_ARCH_NATIVE_SUPPORTED AND NOT CMAKE_C_FLAGS MATCHES "-march=")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")
endif()
check_c_compiler_flag("-fno-common" COMPILER_OPT_NO_COMMON_SUPPORTED)
if (COMPILER_OPT_NO_COMMON_SUPPORTED AND NOT CMAKE_C_FLAGS MATCHES "-fno-common")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-common")
endif()
check_c_compiler_flag("-fno-stack-protector" COMPILER_OPT_NO_STACK_PROTECTOR_SUPPORTED)
if (COMPILER_OPT_NO_STACK_PROTECTOR_SUPPORTED AND NOT CMAKE_C_FLAGS MATCHES "-fno-stack-protector")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-stack-protector")
endif()
set(EMBEDDED_DMRC ON)
if (LLVM_JIT)
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
message(STATUS "LLVM Definitions ${LLVM_DEFINITIONS}")
message(STATUS "LLVMJIT enabled")
set(JIT_SRCS ${LLVM_JIT_SRCS})
if (NOT MSVC)
set_source_files_properties(${LLVM_JIT_SRCS} PROPERTIES
COMPILE_FLAGS "-fno-rtti -fno-exceptions ${LLVM_DEFINITIONS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")
endif ()
if (ASAN)
set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
check_c_compiler_flag("-fsanitize=address" COMPILER_ASAN_SUPPORTED)
if (COMPILER_ASAN_SUPPORTED AND NOT CMAKE_C_FLAGS_DEBUG MATCHES "-fsanitize=address")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address")
endif ()
set_property(
SOURCE ${LLVM_JIT_SRCS}
APPEND
PROPERTY INCLUDE_DIRECTORIES ${LLVM_INCLUDE_DIRS}
)
set(DMR_C_JIT_SRCS
dmr_c/llvm-backend/sparse-llvm.c
)
set(DMR_C_JIT_HEADERS
dmr_c/llvm-backend/dmr_c.h
)
set(DMR_C_HEADERS ${DMR_C_HEADERS_OPT} ${DMR_C_HEADERS_COMMON})
set(DMR_C_SRCS ${DMR_C_SRCS_OPT} ${DMR_C_SRCS_COMMON} ${RAVI_C_SYMBOL_PARSER})
set_property(SOURCE ${DMR_C_JIT_SRCS} src/ravi_llvmcodegen.cpp ${RAVI_C_SYMBOL_PARSER}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/llvm-backend")
set_property(SOURCE ${DMR_C_SRCS} ${DMR_C_JIT_SRCS} ${RAVI_AST_SOURCES}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/src")
set_property(
SOURCE ${RAVI_C_SYMBOL_PARSER} ${DMR_C_JIT_SRCS}
APPEND
PROPERTY INCLUDE_DIRECTORIES ${LLVM_INCLUDE_DIRS})
# FIXME get rid of this dependency
set_property(
SOURCE ${LUA_CMD_SRCS}
APPEND
PROPERTY INCLUDE_DIRECTORIES ${LLVM_INCLUDE_DIRS})
elseif (OMR_JIT)
find_package(OMRJIT REQUIRED)
message(STATUS "OMRJIT enabled")
set(JIT_SRCS ${OMR_JIT_SRCS})
set(DMR_C_JIT_SRCS
dmr_c/omrjit-backend/sparse-omrjit.c
)
set(DMR_C_JIT_HEADERS
dmr_c/omrjit-backend/dmr_c.h
)
set(DMR_C_HEADERS ${DMR_C_HEADERS_OPT} ${DMR_C_HEADERS_COMMON})
set(DMR_C_SRCS ${DMR_C_SRCS_OPT} ${DMR_C_SRCS_COMMON} ${RAVI_C_SYMBOL_PARSER})
endif ()
set_property(SOURCE ${DMR_C_JIT_SRCS} ${RAVI_C_SYMBOL_PARSER} ${OMR_JIT_SRCS}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/omrjit-backend")
set_property(SOURCE ${DMR_C_SRCS} ${DMR_C_JIT_SRCS} ${RAVI_AST_SOURCES}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/src")
set_property(SOURCE ${DMR_C_JIT_SRCS} ${OMR_JIT_SRCS} ${RAVI_C_SYMBOL_PARSER}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${OMRJIT_INCLUDE_DIRS}"
)
if (MIR_JIT)
message(STATUS "MIRJIT enabled")
add_subdirectory(mir)
set(MIRJIT_LIBRARIES c2mir)
set(JIT_SRCS ${MIR_JIT_SRCS})
else ()
# Omit all dmrC stuff except for what we need for the parser
set(DMR_C_HEADERS ${DMR_C_HEADERS_COMMON})
set(DMR_C_SRCS ${DMR_C_SRCS_COMMON})
set(EMBEDDED_DMRC OFF)
set_property(SOURCE ${DMR_C_SRCS_COMMON} ${RAVI_AST_SOURCES}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/src")
if (MIR_JIT)
message(STATUS "MIRJIT enabled")
set(JIT_SRCS ${MIR_SRCS} ${C2MIR_SRCS} ${MIR_JIT_SRCS})
set_property(SOURCE ${MIR_SRCS} ${C2MIR_SRCS} ${MIR_JIT_SRCS}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/mir;${CMAKE_SOURCE_DIR}/mir/c2mir")
set_property(SOURCE ${MIR_SRCS} ${C2MIR_SRCS} ${MIR_JIT_SRCS}
APPEND
PROPERTY COMPILE_DEFINITIONS "x86_64;MIR_IO;MIR_SCAN")
else()
set(JIT_SRCS ${NO_JIT_SRCS})
endif ()
set(JIT_SRCS ${NO_JIT_SRCS})
endif ()
# Additional stuff for dmrC
if (CMAKE_COMPILER_IS_GNUCC AND EMBEDDED_DMRC)
execute_process(COMMAND ${CMAKE_C_COMPILER} --print-file-name=
OUTPUT_VARIABLE GCC_BASE OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-multiarch
OUTPUT_VARIABLE MULTIARCH_TRIPLET ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
set_source_files_properties(dmr_c/src/lib.c PROPERTIES COMPILE_FLAGS "-DGCC_BASE=${GCC_BASE} -DMULTIARCH_TRIPLET=${MULTIARCH_TRIPLET}")
message(STATUS "GCC_BASE_DIR : " ${GCC_BASE})
message(STATUS "MULTIARCH_TRIPLET : " ${MULTIARCH_TRIPLET})
if (RAVICOMP)
set(ADDON_SRCS ${RAVICOMP_SRCS})
add_subdirectory(ravicomp)
set(RAVICOMP_LIBRARIES ravicomp)
endif ()
# IDE stuff
if (MSVC OR APPLE)
source_group("dmrC Headers" FILES ${DMR_C_HEADERS} ${DMR_C_JIT_HEADERS})
source_group("dmrC Source Files" FILES ${DMR_C_SRCS} ${DMR_C_JIT_SRCS})
source_group("Ravi Headers" FILES ${RAVI_HEADERS})
source_group("Ravi Source Files" FILES ${LUA_CORE_SRCS} ${LUA_LIB_SRCS} ${JIT_SRCS})
source_group("Ravi Source Files" FILES ${LUA_CORE_SRCS} ${LUA_LIB_SRCS} ${JIT_SRCS} ${ADDON_SRCS})
endif ()
# Misc setup
@ -241,63 +104,6 @@ elseif (NOT WIN32)
set(EXTRA_LIBRARIES m dl readline)
endif ()
# Enable minimal required LLVM components so that the
# the size of the resulting binary is manageable
if (LLVM_JIT)
if (${LLVM_PACKAGE_VERSION} VERSION_LESS "3.8")
set(LLVM_EXTRA_LIBS ipa)
endif ()
if (NOT ${LLVM_PACKAGE_VERSION} VERSION_LESS "5.0.0")
set(LLVM_EXTRA_LIBS orcjit)
endif ()
message(STATUS "SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
set(LLVM_LIBS_PROCESSOR
X86CodeGen
X86AsmParser
X86Disassembler
X86Desc
X86Info
X86Utils
)
if (${LLVM_PACKAGE_VERSION} VERSION_LESS "9.0.0")
list(APPEND LLVM_LIBS_PROCESSOR X86AsmPrinter)
endif ()
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
set(LLVM_LIBS_PROCESSOR
ARMCodeGen
ARMAsmParser
ARMDisassembler
ARMAsmPrinter
ARMDesc
ARMInfo
)
endif ()
llvm_map_components_to_libnames(LLVM_LIBS
Analysis
AsmParser
AsmPrinter
BitReader
Core
CodeGen
ExecutionEngine
InstCombine
${LLVM_EXTRA_LIBS}
ipo
MC
MCJIT
MCParser
Object
RuntimeDyld
ScalarOpts
Support
Target
TransformUtils
${LLVM_LIBS_PROCESSOR}
)
message(STATUS "LLVM_LIBS ${LLVM_LIBS}")
endif ()
set(LIBRAVI_NAME libravi)
#Main library
@ -306,10 +112,8 @@ add_library(${LIBRAVI_NAME} ${LIBRAVI_BUILD_TYPE}
${LUA_LIB_SRCS}
${LUA_CORE_SRCS}
${JIT_SRCS}
${DMR_C_HEADERS}
${DMR_C_SRCS}
${DMR_C_JIT_SRCS})
target_link_libraries(${LIBRAVI_NAME} ${EXTRA_LIBRARIES} ${LLVM_LIBS} ${OMRJIT_LIBRARIES} ${MIRJIT_LIBRARIES})
${ADDON_SRCS})
target_link_libraries(${LIBRAVI_NAME} LINK_PUBLIC ${EXTRA_LIBRARIES} ${MIRJIT_LIBRARIES} ${RAVICOMP_LIBRARIES})
# Main Ravi executable
add_executable(ravi ${LUA_CMD_SRCS})
@ -320,9 +124,6 @@ set(NOJIT_RAVI_SRCS
${RAVI_HEADERS}
${LUA_LIB_SRCS}
${LUA_CORE_SRCS}
${DMR_C_HEADERS}
${DMR_C_SRCS}
${DMR_C_JIT_SRCS}
${NO_JIT_SRCS})
set(RAVI_STATICEXEC_TARGET ravi_s)
@ -349,19 +150,7 @@ if (NOT LTESTS)
PROPERTY COMPILE_DEFINITIONS NO_LUA_DEBUG)
set(NO_LUA_DEBUG 1)
endif ()
if (LLVM_JIT)
set_property(
TARGET ${LIBRAVI_NAME} ravi
APPEND
PROPERTY COMPILE_DEFINITIONS "USE_LLVM=1")
set(USE_LLVM 1)
elseif (OMR_JIT)
set_property(
TARGET ${LIBRAVI_NAME} ravi
APPEND
PROPERTY COMPILE_DEFINITIONS "USE_OMRJIT=1")
set(USE_OMRJIT 1)
elseif (MIR_JIT)
if (MIR_JIT)
set_property(
TARGET ${LIBRAVI_NAME} ravi
APPEND
@ -381,11 +170,12 @@ if (NOT STATIC_BUILD)
else ()
set_target_properties(${LIBRAVI_NAME} PROPERTIES PREFIX "")
endif ()
if (EMBEDDED_DMRC)
if (RAVICOMP)
set_property(
TARGET ${LIBRAVI_NAME} ravi
TARGET ${LIBRAVI_NAME}
APPEND
PROPERTY COMPILE_DEFINITIONS "USE_DMR_C=1")
PROPERTY COMPILE_DEFINITIONS "USE_RAVICOMP=1")
set(USE_RAVICOMP 1)
endif ()
if (APPLE)
set_property(
@ -398,8 +188,6 @@ elseif (UNIX)
APPEND
PROPERTY COMPILE_DEFINITIONS "LUA_USE_LINUX=1")
endif ()
set_property(TARGET ${LIBRAVI_NAME} PROPERTY CXX_STANDARD 14)
set_property(TARGET ${LIBRAVI_NAME} PROPERTY CXX_EXTENSIONS OFF)
include(GNUInstallDirs)
configure_file(ravi-config.h.in ravi-config.h @ONLY)

@ -6,7 +6,7 @@
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
# Your platform. See PLATS for possible values.
PLAT= none
PLAT= guess
# Where to install. The installation starts in the src and doc directories,
# so take care if INSTALL_TOP is not an absolute path. See the local target.
@ -38,7 +38,7 @@ RM= rm -f
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
# Convenience platforms targets.
PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
PLATS= guess aix bsd c89 freebsd generic linux linux-noreadline macosx mingw posix solaris
# What to install.
TO_BIN= ravi

@ -0,0 +1,195 @@
Ravi Programming Language
=========================
![image](https://travis-ci.org/dibyendumajumdar/ravi.svg?branch=master%0A%20:target:%20https://travis-ci.org/dibyendumajumdar/ravi)
Ravi is a dialect of [Lua](http://www.lua.org/) with limited optional
static typing and features [MIR](https://github.com/vnmakarov/mir)
powered JIT compilers. The name Ravi comes from the Sanskrit word for
the Sun. Interestingly a precursor to Lua was
[Sol](http://www.lua.org/history.html) which had support for static
types; Sol means the Sun in Portugese.
Lua is perfect as a small embeddable dynamic language so why a
derivative? Ravi extends Lua with static typing for improved performance
when JIT compilation is enabled. However, the static typing is optional
and therefore Lua programs are also valid Ravi programs.
There are other attempts to add static typing to Lua - e.g. [Typed
Lua](https://github.com/andremm/typedlua) but these efforts are mostly
about adding static type checks in the language while leaving the VM
unmodified. The Typed Lua effort is very similar to the approach taken
by Typescript in the JavaScript world. The static typing is to aid
programming in the large - the code is eventually translated to standard
Lua and executed in the unmodified Lua VM.
My motivation is somewhat different - I want to enhance the VM to
support more efficient operations when types are known. Type information
can be exploited by JIT compilation technology to improve performance.
At the same time, I want to keep the language safe and therefore usable
by non-expert programmers.
Of course there is the fantastic [LuaJIT](http://luajit.org)
implementation. Ravi has a different goal compared to LuaJIT. Ravi
prioritizes ease of maintenance and support, language safety, and
compatibility with Lua 5.3, over maximum performance. For more detailed
comparison please refer to the documentation links below.
Features
--------
- Optional static typing - for details [see the reference
manual](https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-reference.html).
- Type specific bytecodes to improve performance
- Compatibility with Lua 5.3 (see Compatibility section below)
- Generational GC from Lua 5.4
- `defer` statement for releasing resources
- Compact JIT backend [MIR](https://github.com/vnmakarov/mir).
- A [distribution with
batteries](https://github.com/dibyendumajumdar/Suravi).
- A [Visual Studio Code debugger
extension](https://marketplace.visualstudio.com/items?itemName=ravilang.ravi-debug)
- interpreted mode debugger.
Documentation
-------------
- For the Lua extensions in Ravi see the [Reference
Manual](https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-reference.html).
- [MIR JIT Build
instructions](https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-mir-instructions.html).
- Also see [Ravi
Documentation](http://the-ravi-programming-language.readthedocs.org/en/latest/index.html).
- and the slides I presented at the [Lua 2015
Workshop](http://www.lua.org/wshop15.html).
Lua Goodies
-----------
- [An Introduction to
Lua](http://the-ravi-programming-language.readthedocs.io/en/latest/lua-introduction.html)
attempts to provide a quick overview of Lua for folks coming from
other languages.
- [Lua 5.3 Bytecode
Reference](http://the-ravi-programming-language.readthedocs.io/en/latest/lua_bytecode_reference.html)
is my attempt to bring up to date the [Lua 5.1 Bytecode
Reference](http://luaforge.net/docman/83/98/ANoFrillsIntroToLua51VMInstructions.pdf).
- A [patch for Lua
5.3](https://github.com/dibyendumajumdar/ravi/blob/master/patches/defer_statement_for_Lua_5_3.patch)
implements the 'defer' statement.
- A [patch for Lua
5.4.[0-2]](https://github.com/dibyendumajumdar/ravi/blob/master/patches/defer_statement_for_Lua_5_4.patch)
implements the 'defer' statement.
- Updated [patch for Lua
5.4.3](https://github.com/dibyendumajumdar/ravi/blob/master/patches/defer_statement_patch_for_Lua_5_4_3.patch)
implements the 'defer' statement.
Lua 5.4 Position Statement
--------------------------
Lua 5.4 relationship to Ravi is as follows:
- Generational GC - back-ported to Ravi.
- New random number generator - back-ported to Ravi.
- Multiple user values can be associated with userdata - under
consideration.
- `<const>` variables - not planned.
- `<close>` variables - Ravi has `'defer'` statement which is the
better option in my opinion, hence no plans to support `<close>`
variables.
- Interpreter performance improvements - these are beneficial to Lua
interpreter but not to the JIT backends, hence not much point in
back-porting.
- Table implementation changes - under consideration.
- String to number coercion is now part of string library metamethods
- back-ported to Ravi.
- utf8 library accepts codepoints up to 2\^31 - back-ported to Ravi.
- Removal of compatibility layers for 5.1, and 5.2 - not implemented
as Ravi continues to provide these layers as per Lua 5.3.
Compatibility with Lua 5.3
--------------------------
Ravi should be able to run all Lua 5.3 programs in interpreted mode, but
following should be noted:
- Ravi supports optional typing and enhanced types such as arrays (see
the documentation). Programs using these features cannot be run by
standard Lua. However all types in Ravi can be passed to Lua
functions; operations on Ravi arrays within Lua code will be subject
to restrictions as described in the section above on arrays.
- Values crossing from Lua to Ravi will be subjected to typechecks
should these values be assigned to typed variables.
- Upvalues cannot subvert the static typing of local variables (issue
\#26) when types are annotated.
- Certain Lua limits are reduced due to changed byte code structure.
These are described below.
- Ravi uses an extended bytecode which means it is not compatible with
Lua 5.x bytecode.
- Ravi incorporates the new Generational GC from Lua 5.4, hence the GC
interface has changed.
Limit name Lua value Ravi value
------------------ -------------- --------------
MAXUPVAL 255 125
LUAI\_MAXCCALLS 200 125
MAXREGS 255 125
MAXVARS 200 125
MAXARGLINE 250 120
When JIT compilation is enabled there are following additional
constraints:
- Ravi will only execute JITed code from the main Lua thread; any
secondary threads (coroutines) execute in interpreter mode.
- In JITed code tailcalls are implemented as regular calls so unlike
the interpreter VM which supports infinite tail recursion JIT
compiled code only supports tail recursion to a depth of about 110
(issue \#17)
- Debug api and hooks are not supported in JIT mode
History
-------
- 2015
: - Implemented JIT compilation using LLVM
- Implemented [libgccjit based alternative
JIT](https://github.com/dibyendumajumdar/ravi/tree/gccjit-ravi534)
(now discontinued)
- 2016
: - Implemented debugger for Ravi and Lua 5.3 for [Visual Studio
Code](https://github.com/dibyendumajumdar/ravi/tree/master/vscode-debugger)
- 2017
: - Embedded C compiler using dmrC project (C JIT compiler) (now
discontinued)
- Additional type-annotations
- 2018
: - Implemented [Eclipse OMR JIT
backend](https://github.com/dibyendumajumdar/ravi/tree/omrjit)
(now discontinued)
- Created [Ravi with
batteries](https://github.com/dibyendumajumdar/Suravi).
- 2019
: - New language feature - defer statement
- New JIT backend [MIR](https://github.com/vnmakarov/mir).
- 2020
: - [New parser / type checker /
compiler](https://github.com/dibyendumajumdar/ravi-compiler)
- Generational GC back-ported from Lua 5.4
- Support for [LLVM
backend](https://github.com/dibyendumajumdar/ravi/tree/llvm)
archived
- 2021 (Plan)
: - Integrated AOT and JIT compilation support
- Ravi 1.0 release
License
-------
MIT License

@ -1,109 +0,0 @@
=========================
Ravi Programming Language
=========================
.. image:: https://travis-ci.org/dibyendumajumdar/ravi.svg?branch=master
:target: https://travis-ci.org/dibyendumajumdar/ravi
Ravi is a derivative/dialect of `Lua 5.3 <http://www.lua.org/>`_ with limited optional static typing and
features `MIR <https://github.com/vnmakarov/mir>`_, `LLVM <http://www.llvm.org/>`_ and `Eclipse OMR <https://github.com/dibyendumajumdar/nj>`_
powered JIT compilers. The name Ravi comes from the Sanskrit word for the Sun.
Interestingly a precursor to Lua was `Sol <http://www.lua.org/history.html>`_ which had support for
static types; Sol means the Sun in Portugese.
Lua is perfect as a small embeddable dynamic language so why a derivative? Ravi extends Lua with
static typing for improved performance when JIT compilation is enabled. However, the static typing is
optional and therefore Lua programs are also valid Ravi programs.
There are other attempts to add static typing to Lua - e.g. `Typed Lua <https://github.com/andremm/typedlua>`_ but
these efforts are mostly about adding static type checks in the language while leaving the VM unmodified.
The Typed Lua effort is very similar to the approach taken by Typescript in the JavaScript world.
The static typing is to aid programming in the large - the code is eventually translated to standard Lua
and executed in the unmodified Lua VM.
My motivation is somewhat different - I want to enhance the VM to support more efficient operations when types are
known. Type information can be exploited by JIT compilation technology to improve performance. At the same time,
I want to keep the language safe and therefore usable by non-expert programmers.
Of course there is the fantastic `LuaJIT <http://luajit.org>`_ implementation. Ravi has a different goal compared to
LuaJIT. Ravi prioritizes ease of maintenance and support, language safety, and compatibility with Lua 5.3,
over maximum performance. For more detailed comparison please refer to the documentation links below.
Features
========
* Optional static typing - for details `see the reference manual <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-reference.html>`_.
* Type specific bytecodes to improve performance
* Compatibility with Lua 5.3 (see Compatibility section below)
* New! JIT backend `MIR <https://github.com/vnmakarov/mir>`_; only Linux and x86-64 supported for now.
* `LLVM <http://www.llvm.org/>`_ powered JIT compiler
* `Eclipse OMR <https://github.com/dibyendumajumdar/nj>`_ powered JIT compiler
* A `distribution with batteries <https://github.com/dibyendumajumdar/Suravi>`_.
Documentation
=============
* For the Lua extensions in Ravi see the `Reference Manual <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-reference.html>`_.
* `MIR JIT Build instructions <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-mir-instructions.html>`_.
* `OMR JIT Build instructions <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-omr-instructions.html>`_.
* `LLVM JIT Build instructions <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-llvm-instructions.html>`_.
* Also see `Ravi Documentation <http://the-ravi-programming-language.readthedocs.org/en/latest/index.html>`_.
* and the slides I presented at the `Lua 2015 Workshop <http://www.lua.org/wshop15.html>`_.
Lua Goodies
===========
* `An Introduction to Lua <http://the-ravi-programming-language.readthedocs.io/en/latest/lua-introduction.html>`_ attempts to provide a quick overview of Lua for folks coming from other languages.
* `Lua 5.3 Bytecode Reference <http://the-ravi-programming-language.readthedocs.io/en/latest/lua_bytecode_reference.html>`_ is my attempt to bring up to date the `Lua 5.1 Bytecode Reference <http://luaforge.net/docman/83/98/ANoFrillsIntroToLua51VMInstructions.pdf>`_.
* A `patch for Lua 5.3 <http://lua-users.org/lists/lua-l/2020-01/msg00004.html>`_ implements the 'defer' statement.
Compatibility with Lua
======================
Ravi should be able to run all Lua 5.3 programs in interpreted mode, but following should be noted:
* Ravi supports optional typing and enhanced types such as arrays (described above). Programs using these features cannot be run by standard Lua. However all types in Ravi can be passed to Lua functions; operations on Ravi arrays within Lua code will be subject to restrictions as described in the section above on arrays.
* Values crossing from Lua to Ravi will be subjected to typechecks should these values be assigned to typed variables.
* Upvalues cannot subvert the static typing of local variables (issue #26) when types are annotated.
* Certain Lua limits are reduced due to changed byte code structure. These are described below.
* Ravi uses an extended bytecode which means it is not compatible with Lua 5.3 bytecode.
+-----------------+-------------+-------------+
| Limit name | Lua value | Ravi value |
+=================+=============+=============+
| MAXUPVAL | 255 | 125 |
+-----------------+-------------+-------------+
| LUAI_MAXCCALLS | 200 | 125 |
+-----------------+-------------+-------------+
| MAXREGS | 255 | 125 |
+-----------------+-------------+-------------+
| MAXVARS | 200 | 125 |
+-----------------+-------------+-------------+
| MAXARGLINE | 250 | 120 |
+-----------------+-------------+-------------+
When JIT compilation is enabled there are following additional constraints:
* Ravi will only execute JITed code from the main Lua thread; any secondary threads (coroutines) execute in interpreter mode.
* In JITed code tailcalls are implemented as regular calls so unlike the interpreter VM which supports infinite tail recursion JIT compiled code only supports tail recursion to a depth of about 110 (issue #17)
History
=======
* 2015
- Implemented JIT compilation using LLVM
- Implemented libgccjit based alternative JIT (now discontinued)
* 2016
- Implemented debugger for Ravi and Lua 5.3 for `Visual Studio Code <https://github.com/dibyendumajumdar/ravi/tree/master/vscode-debugger>`_
* 2017
- Embedded C compiler using dmrC project (C JIT compiler)
- Additional type-annotations
* 2018
- Implemented Eclipse OMR JIT backend
- Created `Ravi with batteries <https://github.com/dibyendumajumdar/Suravi>`_.
* 2019
- `New parser, type checker for Ravi <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-new-parser-codegenerator.html>`_ - work in progress
- New language feature - `defer` statement
- New JIT backend `MIR <https://github.com/vnmakarov/mir>`_.
* 2020 (Plan)
- `New optimizing byte code generator based on new parser / type checker <https://github.com/dibyendumajumdar/ravi-compiler>`_
- Ravi 1.0 release
License
=======
MIT License

@ -5,4 +5,4 @@ The scripts here are unsupported - these are just my personal
build scripts.
The unix LLVM debug builds enable 'ltests' and address sanitizer.
The debug builds enable 'ltests' and address sanitizer.

@ -1,5 +0,0 @@
mkdir llvm32
cd llvm32
rem cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM37_32\share\llvm\cmake -DBUILD_STATIC=OFF ..
cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM39_32\lib\cmake\llvm -DSTATIC_BUILD=OFF ..
cd ..

@ -1,5 +0,0 @@
mkdir llvm32
cd llvm32
rem cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM37_32\share\llvm\cmake ..
cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM39\lib\cmake\llvm -DSTATIC_BUILD=ON ..
cd ..

@ -1,5 +0,0 @@
mkdir llvm32d
cd llvm32d
rem cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM37_32\share\llvm\cmake ..
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM39D_32\lib\cmake\llvm -DSTATIC_BUILD=ON ..
cd ..

@ -1,6 +0,0 @@
mkdir llvm64d
cd llvm64d
rem cmake -DCMAKE_INSTALL_PREFIX=c:\ravi64llvmd -G "Visual Studio 14 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\LLVM37debug\share\llvm\cmake ..
rem cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=c:\d\ravi64llvmd -G "Visual Studio 15 2017 Win64" -DLLVM_JIT=ON -DEMBEDDED_DMRC=ON -DLLVM_DIR=c:\d\LLVM39D64\lib\cmake\llvm ..
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm501d\lib\cmake\llvm ..
cd ..

@ -1,7 +0,0 @@
mkdir llvm64
cd llvm64
rem pre LLVM 3.9
rem cmake -DCMAKE_INSTALL_PREFIX=c:\ravi -G "Visual Studio 14 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\LLVM37\share\llvm\cmake ..
rem cmake -DCMAKE_INSTALL_PREFIX=c:\ravi -G "Visual Studio 15 2017 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\d\LLVM40_64\lib\cmake\llvm ..
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DSTATIC_BUILD=ON -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm601r\lib\cmake\llvm ..
cd ..

@ -1,5 +0,0 @@
rmdir /s llvm8
mkdir llvm8
cd llvm8
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm801\lib\cmake\llvm ..
cd ..

@ -1,5 +0,0 @@
rmdir /s llvm9d
mkdir llvm9d
cd llvm9d
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm900\lib\cmake\llvm ..
cd ..

@ -1,6 +0,0 @@
rmdir /s llvm9r
mkdir llvm9r
cd llvm9r
rem cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm900r\lib\cmake\llvm ..
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 16 2019" -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm900r\lib\cmake\llvm ..
cd ..

@ -1,4 +1,4 @@
mkdir nojit64a
cd nojit64a
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -DCMAKE_BUILD_TYPE=Debug -DLTESTS=ON -G "Visual Studio 15 2017 Win64" ..
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -DCMAKE_BUILD_TYPE=Debug -DLTESTS=ON ..
cd ..

@ -1,4 +0,0 @@
mkdir omrjit
cd omrjit
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Debug -DOMR_JIT=ON ..
cd ..

@ -1,4 +0,0 @@
mkdir xcodellvm
cd xcodellvm
#cmake -DCMAKE_BUILD_TYPE=Debug -G Xcode -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
cmake -DCMAKE_BUILD_TYPE=Debug -G Xcode -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..

@ -1,5 +0,0 @@
mkdir buildllvmd
cd buildllvmd
#cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
#cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DLTESTS=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DLTESTS=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravillvm -DLLVM_DIR=$HOME/Software/llvm600/lib/cmake/llvm ..

@ -1,6 +0,0 @@
rm -rf buildllvm
mkdir buildllvm
cd buildllvm
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
cmake -DCMAKE_BUILD_TYPE=Release -DSTATIC_BUILD=ON -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/Software/ravi -DLLVM_DIR=$HOME/Software/llvm801/lib/cmake/llvm ..

@ -1,3 +0,0 @@
mkdir omrjit
cd omrjit
cmake -DCMAKE_BUILD_TYPE=Release -DOMR_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi ..

@ -1,16 +0,0 @@
find_path(MIRJIT_INCLUDE_DIR c2mir.h
PATHS
c:/Software/mir/include/mir
~/Software/mir/include/mir
NO_DEFAULT_PATH
)
find_library(MIRJIT_LIBRARY
NAMES libc2mir.a
PATHS
c:/Software/mir/lib
~/Software/mir/lib
)
set( MIRJIT_INCLUDE_DIRS "${MIRJIT_INCLUDE_DIR}" )
set( MIRJIT_LIBRARIES "${MIRJIT_LIBRARY}" )

@ -1,16 +0,0 @@
find_path(OMRJIT_INCLUDE_DIR nj_api.h
PATHS
c:/Software/omr/include/nj
~/Software/omr/include/nj
NO_DEFAULT_PATH
)
find_library(OMRJIT_LIBRARY
NAMES nj libnj libnj.dylib
PATHS
c:/Software/omr/lib
~/Software/omr/lib
)
set( OMRJIT_INCLUDE_DIRS "${OMRJIT_INCLUDE_DIR}" )
set( OMRJIT_LIBRARIES "${OMRJIT_LIBRARY}" )

@ -1,8 +0,0 @@
# dmr_C is a C Parser and JIT compiler
Ravi includes a copy of the [dmr_C](https://github.com/dibyendumajumdar/dmr_c) project. See the project for more details regarding dmr_C.
## Goals
* Use dmr_C to translate code to JIT backend such as OMR JIT, NanoJIT or LLVM.
* Expose dmr_C features such as C parser, and compiler to users so that they can also compile chunks of C code when necessary

@ -1,44 +0,0 @@
/**
* This is a backend code generator for dmr_C that uses
* the LLVM JIT engine.
*
* Copyright (C) 2017 Dibyendu Majumdar
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef DMR_C_H
#define DMR_C_H
#include <llvm-c/Core.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
extern bool dmrC_llvmcompile(int argc, char **argv, LLVMModuleRef module,
const char *inputbuffer);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -1,28 +0,0 @@
/**
* This header is used when no backend is used
*
* Copyright (C) 2017 Dibyendu Majumdar
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef DMR_C_H
#define DMR_C_H
#endif

@ -1,42 +0,0 @@
/**
* This is a backend code generator for dmr_C that uses
* the JIT engine OMR JIT (https://github.com/dibyendumajumdar/nj).
*
* Copyright (C) 2018 Dibyendu Majumdar
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef DMR_C_H
#define DMR_C_H
#include <nj_api.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
bool dmrC_omrcompile(int argc, char **argv, JIT_ContextRef context,
const char *inputbuffer);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -1,67 +0,0 @@
The code is organised as follows:
## Pointer Linked List
This is implemented in:
* ptrlist.h
* ptrlist.c
## Memory allocation
* allocate.h
* allocate.c
## Tokenizer
This is implemented in:
* token.h
* tokenize.c
The tokenizer depends on declarations in symbol.h and target.h
## Parser
The C parser parses code as well as evaluates constant expressions and as far as I can tell it will also perform
inlining of functions. The evaluation code is reused by the pre-processor so the C parser is lower level than the
pre-processor.
The parser implementation is in following:
* symbol.h
* symbol.c
* scope.h
* scope.c
* parse.h
* parse.c
* char.c
* char.h
* expression.h
* expression.c
* expand.c
* evaluate.c
* inline.c
* ident-list.h
* show-parse.c
## Pre-processor
The pre-processor depends upon the parser functions to evaluate expressions. It is implemented in:
* pre-process.c
## Linearizer
This component transforms the parsed representation to a linear form (SSA I believe). The implementation is in:
* linearize.h
* linearize.c
* flow.h
* flow.c
* cse.c
* liveness.c
* memops.c
* simplify.c
* unssa.c

@ -1,215 +0,0 @@
/*
* allocate.c - simple space-efficient blob allocator.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003-2004 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Simple allocator for data that doesn't get partially free'd.
* The tokenizer and parser allocate a _lot_ of small data structures
* (often just two-three bytes for things like small integers),
* and since they all depend on each other you can't free them
* individually _anyway_. So do something that is very space-
* efficient: allocate larger "blobs", and give out individual
* small bits and pieces of it with no maintenance overhead.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <allocate.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *dmrC_blob_alloc(size_t size) {
void *ptr;
ptr = malloc(size);
if (ptr != NULL)
memset(ptr, 0, size);
return ptr;
}
void dmrC_blob_free(void *addr, size_t size) {
(void)size;
free(addr);
}
void dmrC_allocator_init(struct allocator *A, const char *name, size_t size,
unsigned int alignment, unsigned int chunking) {
A->name_ = name;
A->blobs_ = NULL;
A->size_ = size;
A->alignment_ = alignment;
A->chunking_ = chunking;
A->freelist_ = NULL;
A->allocations = 0;
A->total_bytes = 0;
A->useful_bytes = 0;
}
void *dmrC_allocator_allocate(struct allocator *A, size_t extra) {
size_t size = extra + A->size_;
size_t alignment = A->alignment_;
struct allocation_blob *blob = A->blobs_;
void *retval;
assert(size <= A->chunking_);
/*
* NOTE! The freelist only works with things that are
* (a) sufficiently aligned
* (b) use a constant size
* Don't try to free allocators that don't follow
* these rules.
*/
if (A->freelist_) {
void **p = (void **)A->freelist_;
retval = p;
A->freelist_ = *p;
memset(retval, 0, size);
return retval;
}
A->allocations++;
A->useful_bytes += size;
size = (size + alignment - 1) & ~(alignment - 1);
if (!blob || blob->left < size) {
size_t offset, chunking = A->chunking_;
struct allocation_blob *newblob =
(struct allocation_blob *)dmrC_blob_alloc(chunking);
if (!newblob) {
fprintf(stderr, "out of memory\n");
abort();
}
A->total_bytes += chunking;
newblob->next = blob;
blob = newblob;
A->blobs_ = newblob;
offset = offsetof(struct allocation_blob, data);
offset = (offset + alignment - 1) & ~(alignment - 1);
blob->left = chunking - offset;
blob->offset = offset - offsetof(struct allocation_blob, data);
}
retval = blob->data + blob->offset;
blob->offset += size;
blob->left -= size;
return retval;
}
void dmrC_allocator_free(struct allocator *A, void *entry) {
void **p = (void **)entry;
*p = A->freelist_;
A->freelist_ = p;
}
void dmrC_allocator_show_allocations(struct allocator *A) {
fprintf(stderr, "%s: %d allocations, %d bytes (%d total bytes, "
"%6.2f%% usage, %6.2f average size)\n",
A->name_, (int)A->allocations, (int)A->useful_bytes,
(int)A->total_bytes, 100 * (double)A->useful_bytes / A->total_bytes,
(double)A->useful_bytes / A->allocations);
}
void dmrC_allocator_drop_all_allocations(struct allocator *A) {
struct allocation_blob *blob = A->blobs_;
A->blobs_ = NULL;
A->allocations = 0;
A->total_bytes = 0;
A->useful_bytes = 0;
A->freelist_ = NULL;
while (blob) {
struct allocation_blob *next = blob->next;
dmrC_blob_free(blob, A->chunking_);
blob = next;
}
}
void dmrC_allocator_destroy(struct allocator *A) {
dmrC_allocator_drop_all_allocations(A);
A->blobs_ = NULL;
A->allocations = 0;
A->total_bytes = 0;
A->useful_bytes = 0;
A->freelist_ = NULL;
}
void dmrC_allocator_transfer(struct allocator *A, struct allocator *transfer_to) {
assert(transfer_to->blobs_ == NULL);
assert(transfer_to->freelist_ == NULL);
transfer_to->blobs_ = A->blobs_;
transfer_to->allocations = A->allocations;
transfer_to->total_bytes = A->total_bytes;
transfer_to->useful_bytes = A->useful_bytes;
transfer_to->freelist_ = A->freelist_;
transfer_to->alignment_ = A->alignment_;
transfer_to->chunking_ = A->chunking_;
transfer_to->size_ = A->size_;
A->blobs_ = NULL;
A->allocations = 0;
A->total_bytes = 0;
A->useful_bytes = 0;
A->freelist_ = NULL;
}
struct foo {
int a, b;
};
int dmrC_test_allocator() {
struct allocator alloc;
dmrC_allocator_init(&alloc, "foo", sizeof(struct foo), __alignof__(struct foo),
sizeof(struct allocation_blob) + sizeof(struct foo) * 2);
struct foo *t1 = (struct foo *)dmrC_allocator_allocate(&alloc, 0);
if (t1 == NULL)
return 1;
if (alloc.alignment_ != __alignof__(struct foo))
return 1;
if (alloc.allocations != 1)
return 1;
if (alloc.freelist_ != NULL)
return 1;
struct foo *t2 = (struct foo *)dmrC_allocator_allocate(&alloc, 0);
if (t2 != t1 + 1)
return 1;
//dmrC_allocator_show_allocations(&alloc);
dmrC_allocator_free(&alloc, t1);
dmrC_allocator_free(&alloc, t2);
struct foo *t3 = (struct foo *)dmrC_allocator_allocate(&alloc, 0);
if (t3 != t2)
return 1;
struct foo *t4 = (struct foo *)dmrC_allocator_allocate(&alloc, 0);
if (t4 != t1)
return 1;
struct foo *t5 = (struct foo *)dmrC_allocator_allocate(&alloc, 0);
(void)t5;
if (alloc.total_bytes !=
(sizeof(struct allocation_blob) + sizeof(struct foo) * 2) * 2)
return 1;
struct allocator alloc2;
memset(&alloc2, 0, sizeof alloc2);
struct allocation_blob *saved = alloc.blobs_;
dmrC_allocator_transfer(&alloc, &alloc2);
if (alloc.blobs_ != NULL)
return 1;
if (alloc2.blobs_ != saved)
return 1;
dmrC_allocator_destroy(&alloc2);
printf("allocator tests okay\n");
return 0;
}

@ -1,100 +0,0 @@
#ifndef DMR_C_ALLOCATOR_H
#define DMR_C_ALLOCATOR_H
/*
* allocate.c - simple space-efficient blob allocator.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003-2004 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Simple allocator for data that doesn't get partially free'd.
* The tokenizer and parser allocate a _lot_ of small data structures
* (often just two-three bytes for things like small integers),
* and since they all depend on each other you can't free them
* individually _anyway_. So do something that is very space-
* efficient: allocate larger "blobs", and give out individual
* small bits and pieces of it with no maintenance overhead.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <port.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
struct allocation_blob {
struct allocation_blob *next;
size_t left, offset;
unsigned char data[];
};
/*
* Our "blob" allocator works on chunks that are multiples
* of this size (the underlying allocator may be a mmap that
* cannot handle smaller chunks, for example, so trying to
* allocate blobs that aren't aligned is not going to work).
*/
#define CHUNK 32768
struct allocator {
const char *name_;
struct allocation_blob *blobs_;
size_t size_;
unsigned int alignment_;
unsigned int chunking_;
void *freelist_;
size_t allocations, total_bytes, useful_bytes;
};
extern void dmrC_allocator_init(struct allocator *A, const char *name, size_t size,
unsigned int alignment, unsigned int chunking);
extern void *dmrC_allocator_allocate(struct allocator *A, size_t extra);
extern void dmrC_allocator_free(struct allocator *A, void *entry);
extern void dmrC_allocator_show_allocations(struct allocator *A);
extern void dmrC_allocator_drop_all_allocations(struct allocator *A);
extern void dmrC_allocator_destroy(struct allocator *A);
extern void dmrC_allocator_transfer(struct allocator *A,
struct allocator *transfer_to);
extern int dmrC_test_allocator();
#ifdef __cplusplus
}
#endif
#endif

@ -1,249 +0,0 @@
/*
* builtin evaluation & expansion.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003-2004 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <port.h>
#include <lib.h>
#include <expression.h>
#include <expand.h>
#include <symbol.h>
static int evaluate_to_integer(struct dmr_C *C, struct expression *expr)
{
expr->ctype = &C->S->int_ctype;
return 1;
}
static int evaluate_expect(struct dmr_C *C, struct expression *expr)
{
/* Should we evaluate it to return the type of the first argument? */
expr->ctype = &C->S->int_ctype;
return 1;
}
static int arguments_choose(struct dmr_C *C, struct expression *expr)
{
struct expression_list *arglist = expr->args;
struct expression *arg;
int i = 0;
FOR_EACH_PTR (arglist, arg) {
if (!dmrC_evaluate_expression(C, arg))
return 0;
i++;
} END_FOR_EACH_PTR(arg);
if (i < 3) {
dmrC_sparse_error(C, expr->pos,
"not enough arguments for __builtin_choose_expr");
return 0;
} if (i > 3) {
dmrC_sparse_error(C, expr->pos,
"too many arguments for __builtin_choose_expr");
return 0;
}
return 1;
}
static int evaluate_choose(struct dmr_C *C, struct expression *expr)
{
struct expression_list *list = expr->args;
struct expression *arg, *args[3];
int n = 0;
/* there will be exactly 3; we'd already verified that */
FOR_EACH_PTR(list, arg) {
args[n++] = arg;
} END_FOR_EACH_PTR(arg);
*expr = dmrC_get_expression_value(C, args[0]) ? *args[1] : *args[2];
return 1;
}
static int expand_expect(struct dmr_C *C, struct expression *expr, int cost)
{
struct expression *arg = dmrC_first_expression(expr->args);
(void)C;
(void)cost;
if (arg)
*expr = *arg;
return 0;
}
/*
* __builtin_warning() has type "int" and always returns 1,
* so that you can use it in conditionals or whatever
*/
static int expand_warning(struct dmr_C *C, struct expression *expr, int cost)
{
struct expression *arg;
struct expression_list *arglist = expr->args;
(void)cost;
FOR_EACH_PTR (arglist, arg) {
/*
* Constant strings get printed out as a warning. By the
* time we get here, the EXPR_STRING has been fully
* evaluated, so by now it's an anonymous symbol with a
* string initializer.
*
* Just for the heck of it, allow any constant string
* symbol.
*/
if (arg->type == EXPR_SYMBOL) {
struct symbol *sym = arg->symbol;
if (sym->initializer && sym->initializer->type == EXPR_STRING) {
struct string *string = sym->initializer->string;
dmrC_warning(C, expr->pos, "%*s", string->length-1, string->data);
}
continue;
}
/*
* Any other argument is a conditional. If it's
* non-constant, or it is false, we exit and do
* not print any warning.
*/
if (arg->type != EXPR_VALUE)
goto out;
if (!arg->value)
goto out;
} END_FOR_EACH_PTR(arg);
out:
expr->type = EXPR_VALUE;
expr->value = 1;
expr->taint = 0;
return 0;
}
/* The arguments are constant if the cost of all of them is zero */
static int expand_constant_p(struct dmr_C *C, struct expression *expr, int cost)
{
(void) C;
expr->type = EXPR_VALUE;
expr->value = !cost;
expr->taint = 0;
return 0;
}
/* The arguments are safe, if their cost is less than SIDE_EFFECTS */
static int expand_safe_p(struct dmr_C *C, struct expression *expr, int cost)
{
(void) C;
expr->type = EXPR_VALUE;
expr->value = (cost < SIDE_EFFECTS);
expr->taint = 0;
return 0;
}
static struct symbol_op constant_p_op = {
.evaluate = evaluate_to_integer,
.expand = expand_constant_p
};
static struct symbol_op safe_p_op = {
.evaluate = evaluate_to_integer,
.expand = expand_safe_p
};
static struct symbol_op warning_op = {
.evaluate = evaluate_to_integer,
.expand = expand_warning
};
static struct symbol_op expect_op = {
.evaluate = evaluate_expect,
.expand = expand_expect
};
static struct symbol_op choose_op = {
.evaluate = evaluate_choose,
.args = arguments_choose,
};
/* The argument is constant and valid if the cost is zero */
static int expand_bswap(struct dmr_C *C, struct expression *expr, int cost)
{
struct expression *arg;
long long val;
if (cost)
return cost;
/* the arguments number & type have already been checked */
arg = dmrC_first_expression(expr->args);
val = dmrC_get_expression_value_silent(C, arg);
switch (expr->ctype->bit_size) {
case 16: expr->value = __builtin_bswap16((uint16_t)val); break;
case 32: expr->value = __builtin_bswap32((uint32_t)val); break;
case 64: expr->value = __builtin_bswap64(val); break;
default: /* impossible error */
return SIDE_EFFECTS;
}
expr->type = EXPR_VALUE;
expr->taint = 0;
return 0;
}
static struct symbol_op bswap_op = {
.expand = expand_bswap,
};
/*
* Builtin functions
*/
static struct symbol builtin_fn_type = { .type = SYM_FN /* , .variadic =1 */ };
static struct sym_init {
const char *name;
struct symbol *base_type;
unsigned int modifiers;
struct symbol_op *op;
} builtins_table[] = {
{ "__builtin_constant_p", &builtin_fn_type, MOD_TOPLEVEL, &constant_p_op },
{ "__builtin_safe_p", &builtin_fn_type, MOD_TOPLEVEL, &safe_p_op },
{ "__builtin_warning", &builtin_fn_type, MOD_TOPLEVEL, &warning_op },
{ "__builtin_expect", &builtin_fn_type, MOD_TOPLEVEL, &expect_op },
{ "__builtin_choose_expr", &builtin_fn_type, MOD_TOPLEVEL, &choose_op },
{ "__builtin_bswap16", NULL, MOD_TOPLEVEL, &bswap_op },
{ "__builtin_bswap32", NULL, MOD_TOPLEVEL, &bswap_op },
{ "__builtin_bswap64", NULL, MOD_TOPLEVEL, &bswap_op },
{ NULL, NULL, 0, NULL }
};
void dmrC_init_builtins(struct dmr_C *C, int stream)
{
struct sym_init *ptr;
builtin_fn_type.variadic = 1;
for (ptr = builtins_table; ptr->name; ptr++) {
struct symbol *sym;
sym = dmrC_create_symbol(C->S, stream, ptr->name, SYM_NODE, NS_SYMBOL);
sym->ctype.base_type = ptr->base_type;
sym->ctype.modifiers = ptr->modifiers;
sym->op = ptr->op;
}
}

@ -1,181 +0,0 @@
/*
* sparse/char.c
*
* Copyright (C) 2003 Transmeta Corp.
* 2003-2004 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <string.h>
#include <port.h>
#include <target.h>
#include <lib.h>
#include <allocate.h>
#include <token.h>
#include <expression.h>
static const char *parse_escape(struct dmr_C *C, const char *p, unsigned *val, const char *end, int bits, struct position pos)
{
unsigned c = *p++;
unsigned d;
if (c != '\\') {
*val = c;
return p;
}
c = *p++;
switch (c) {
case 'a': c = '\a'; break;
case 'b': c = '\b'; break;
case 't': c = '\t'; break;
case 'n': c = '\n'; break;
case 'v': c = '\v'; break;
case 'f': c = '\f'; break;
case 'r': c = '\r'; break;
#ifndef _MSC_VER
case 'e': c = '\e'; break;
#endif
case 'x': {
unsigned mask = -(1U << (bits - 4));
for (c = 0; p < end; c = (c << 4) + d) {
d = dmrC_hexval(*p);
if (d > 16)
break;
p++;
if (c & mask) {
dmrC_warning(C, pos,
"hex escape sequence out of range");
mask = 0;
}
}
break;
}
case '0':case '1': case '2': case '3': case '4': case '5':
case '6': case '7': {
if (p + 2 < end)
end = p + 2;
c -= '0';
while (p < end && (d = *p - '0') < 8) {
c = (c << 3) + d;
p++;
}
if ((c & 0400) && bits < 9)
dmrC_warning(C, pos,
"octal escape sequence out of range");
break;
}
default: /* everything else is left as is */
dmrC_warning(C, pos, "unknown escape sequence: '\\%c'", c);
break;
case '\\':
case '\'':
case '"':
case '?':
break; /* those are legal, so no warnings */
}
*val = c & ~((~0U << (bits - 1)) << 1);
return p;
}
void dmrC_get_char_constant(struct dmr_C *C, struct token *token, unsigned long long *val)
{
const char *p = token->embedded, *end;
unsigned v;
int type = dmrC_token_type(token);
switch (type) {
case TOKEN_CHAR:
case TOKEN_WIDE_CHAR:
p = token->string->data;
end = p + token->string->length - 1;
break;
case TOKEN_CHAR_EMBEDDED_0:
case TOKEN_CHAR_EMBEDDED_1:
case TOKEN_CHAR_EMBEDDED_2:
case TOKEN_CHAR_EMBEDDED_3:
end = p + type - TOKEN_CHAR;
break;
default:
end = p + type - TOKEN_WIDE_CHAR;
}
p = parse_escape(C, p, &v, end,
type < TOKEN_WIDE_CHAR ? C->target->bits_in_char : C->target->bits_in_wchar, token->pos);
if (p != end)
dmrC_warning(C, token->pos,
"multi-character character constant");
*val = v;
}
struct token *dmrC_get_string_constant(struct dmr_C *C, struct token *token, struct expression *expr)
{
struct string *string = token->string;
struct token *next = token->next, *done = NULL;
int stringtype = dmrC_token_type(token);
int is_wide = stringtype == TOKEN_WIDE_STRING;
char buffer[MAX_STRING];
int len = 0;
int bits;
int esc_count = 0;
while (!done) {
switch (dmrC_token_type(next)) {
case TOKEN_WIDE_STRING:
is_wide = 1;
case TOKEN_STRING:
next = next->next;
break;
default:
done = next;
}
}
bits = is_wide ? C->target->bits_in_wchar : C->target->bits_in_char;
while (token != done) {
unsigned v;
const char *p = token->string->data;
const char *end = p + token->string->length - 1;
while (p < end) {
if (*p == '\\')
esc_count++;
p = parse_escape(C, p, &v, end, bits, token->pos);
if (len < MAX_STRING)
buffer[len] = v;
len++;
}
token = token->next;
}
if (len > MAX_STRING) {
dmrC_warning(C, token->pos, "trying to concatenate %d-character string (%d bytes max)", len, MAX_STRING);
len = MAX_STRING;
}
if (esc_count || len >= (int)string->length) {
if (string->immutable || len >= string->length) /* can't cannibalize */
string = (struct string *)dmrC_allocator_allocate(&C->string_allocator, len+1);
string->length = len+1;
memcpy(string->data, buffer, len);
string->data[len] = '\0';
}
expr->string = string;
expr->wide = is_wide;
return token;
}

@ -1,25 +0,0 @@
/*
* sparse/char.h
*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#ifndef DMR_C_CHAR_H
#define DMR_C_CHAR_H
#ifdef __cplusplus
extern "C" {
#endif
extern void dmrC_get_char_constant(struct dmr_C *C, struct token *, unsigned long long *);
extern struct token *dmrC_get_string_constant(struct dmr_C *C, struct token *, struct expression *);
#ifdef __cplusplus
}
#endif
#endif

@ -1,393 +0,0 @@
/*
* CSE - walk the linearized instruction flow, and
* see if we can simplify it and apply CSE on it.
*
* Copyright (C) 2004 Linus Torvalds
*/
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
#include <port.h>
#include <parse.h>
#include <expression.h>
#include <linearize.h>
#include <flow.h>
static int phi_compare(pseudo_t phi1, pseudo_t phi2)
{
const struct instruction *def1 = phi1->def;
const struct instruction *def2 = phi2->def;
if (def1->src1 != def2->src1)
return def1->src1 < def2->src1 ? -1 : 1;
if (def1->bb != def2->bb)
return def1->bb < def2->bb ? -1 : 1;
return 0;
}
static void clean_up_one_instruction(struct dmr_C *C, struct basic_block *bb, struct instruction *insn)
{
unsigned long hash;
if (!insn->bb)
return;
assert(insn->bb == bb);
C->L->repeat_phase |= dmrC_simplify_instruction(C, insn);
if (!insn->bb)
return;
hash = (insn->opcode << 3) + (insn->size >> 3);
switch (insn->opcode) {
case OP_SEL:
hash += dmrC_hashval(insn->src3);
/* Fall through */
/* Binary arithmetic */
case OP_ADD: case OP_SUB:
case OP_MULU: case OP_MULS:
case OP_DIVU: case OP_DIVS:
case OP_MODU: case OP_MODS:
case OP_SHL:
case OP_LSR: case OP_ASR:
case OP_AND: case OP_OR:
/* Binary logical */
case OP_XOR: case OP_AND_BOOL:
case OP_OR_BOOL:
/* Binary comparison */
case OP_SET_EQ: case OP_SET_NE:
case OP_SET_LE: case OP_SET_GE:
case OP_SET_LT: case OP_SET_GT:
case OP_SET_B: case OP_SET_A:
case OP_SET_BE: case OP_SET_AE:
hash += dmrC_hashval(insn->src2);
/* Fall through */
/* Unary */
case OP_NOT: case OP_NEG:
hash += dmrC_hashval(insn->src1);
break;
case OP_SETVAL:
hash += dmrC_hashval(insn->val);
break;
case OP_SYMADDR:
hash += dmrC_hashval(insn->symbol);
break;
case OP_CAST:
case OP_SCAST:
case OP_PTRCAST:
/*
* This is crap! Many "orig_types" are the
* same as far as casts go, we should generate
* some kind of "type hash" that is identical
* for identical casts
*/
hash += dmrC_hashval(insn->orig_type);
hash += dmrC_hashval(insn->src);
break;
/* Other */
case OP_PHI: {
pseudo_t phi;
FOR_EACH_PTR(insn->phi_list, phi) {
struct instruction *def;
if (phi == VOID_PSEUDO(C) || !phi->def)
continue;
def = phi->def;
hash += dmrC_hashval(def->src1);
hash += dmrC_hashval(def->bb);
} END_FOR_EACH_PTR(phi);
break;
}
default:
/*
* Nothing to do, don't even bother hashing them,
* we're not going to try to CSE them
*/
return;
}
hash += hash >> 16;
hash &= INSN_HASH_SIZE-1;
dmrC_add_instruction(C, C->L->insn_hash_table + hash, insn);
}
static void clean_up_insns(struct dmr_C *C, struct entrypoint *ep)
{
struct basic_block *bb;
FOR_EACH_PTR(ep->bbs, bb) {
struct instruction *insn;
FOR_EACH_PTR(bb->insns, insn) {
clean_up_one_instruction(C, bb, insn);
} END_FOR_EACH_PTR(insn);
} END_FOR_EACH_PTR(bb);
}
/* Compare two (sorted) phi-lists */
static int phi_list_compare(struct dmr_C *C, struct pseudo_list *l1, struct pseudo_list *l2)
{
pseudo_t phi1, phi2;
PREPARE_PTR_LIST(l1, phi1);
PREPARE_PTR_LIST(l2, phi2);
for (;;) {
int cmp;
while (phi1 && (phi1 == VOID_PSEUDO(C) || !phi1->def))
NEXT_PTR_LIST(phi1);
while (phi2 && (phi2 == VOID_PSEUDO(C) || !phi2->def))
NEXT_PTR_LIST(phi2);
if (!phi1)
return phi2 ? -1 : 0;
if (!phi2)
return phi1 ? 1 : 0;
cmp = phi_compare(phi1, phi2);
if (cmp)
return cmp;
NEXT_PTR_LIST(phi1);
NEXT_PTR_LIST(phi2);
}
/* Not reached, but we need to make the nesting come out right */
FINISH_PTR_LIST(phi2);
FINISH_PTR_LIST(phi1);
}
static int insn_compare(void *ud, const void *_i1, const void *_i2)
{
struct dmr_C *C = (struct dmr_C *) ud;
const struct instruction *i1 = _i1;
const struct instruction *i2 = _i2;
if (i1->opcode != i2->opcode)
return i1->opcode < i2->opcode ? -1 : 1;
switch (i1->opcode) {
/* commutative binop */
case OP_ADD:
case OP_MULU: case OP_MULS:
case OP_AND_BOOL: case OP_OR_BOOL:
case OP_AND: case OP_OR:
case OP_XOR:
case OP_SET_EQ: case OP_SET_NE:
if (i1->src1 == i2->src2 && i1->src2 == i2->src1)
return 0;
goto case_binops;
case OP_SEL:
if (i1->src3 != i2->src3)
return i1->src3 < i2->src3 ? -1 : 1;
/* Fall-through to binops */
/* Binary arithmetic */
case OP_SUB:
case OP_DIVU: case OP_DIVS:
case OP_MODU: case OP_MODS:
case OP_SHL:
case OP_LSR: case OP_ASR:
/* Binary comparison */
case OP_SET_LE: case OP_SET_GE:
case OP_SET_LT: case OP_SET_GT:
case OP_SET_B: case OP_SET_A:
case OP_SET_BE: case OP_SET_AE:
case_binops:
if (i1->src2 != i2->src2)
return i1->src2 < i2->src2 ? -1 : 1;
/* Fall through to unops */
/* Unary */
case OP_NOT: case OP_NEG:
if (i1->src1 != i2->src1)
return i1->src1 < i2->src1 ? -1 : 1;
break;
case OP_SYMADDR:
if (i1->symbol != i2->symbol)
return i1->symbol < i2->symbol ? -1 : 1;
break;
case OP_SETVAL:
if (i1->val != i2->val)
return i1->val < i2->val ? -1 : 1;
break;
/* Other */
case OP_PHI:
return phi_list_compare(C, i1->phi_list, i2->phi_list);
case OP_CAST:
case OP_SCAST:
case OP_PTRCAST:
/*
* This is crap! See the comments on hashing.
*/
if (i1->orig_type != i2->orig_type)
return i1->orig_type < i2->orig_type ? -1 : 1;
if (i1->src != i2->src)
return i1->src < i2->src ? -1 : 1;
break;
default:
dmrC_warning(C, i1->pos, "bad instruction on hash chain");
}
if (i1->size != i2->size)
return i1->size < i2->size ? -1 : 1;
return 0;
}
static void sort_instruction_list(struct dmr_C *C, struct instruction_list **list)
{
ptrlist_sort((struct ptr_list **)list, C, insn_compare);
}
static struct instruction * cse_one_instruction(struct dmr_C *C, struct instruction *insn, struct instruction *def)
{
dmrC_convert_instruction_target(C, insn, def->target);
dmrC_kill_instruction(C, insn);
C->L->repeat_phase |= REPEAT_CSE;
return def;
}
/*
* Does "bb1" dominate "bb2"?
*/
static int bb_dominates(struct entrypoint *ep, struct basic_block *bb1, struct basic_block *bb2, unsigned long generation)
{
struct basic_block *parent;
/* Nothing dominates the entrypoint.. */
if (bb2 == ep->entry->bb)
return 0;
FOR_EACH_PTR(bb2->parents, parent) {
if (parent == bb1)
continue;
if (parent->generation == generation)
continue;
parent->generation = generation;
if (!bb_dominates(ep, bb1, parent, generation))
return 0;
} END_FOR_EACH_PTR(parent);
return 1;
}
static struct basic_block *trivial_common_parent(struct basic_block *bb1, struct basic_block *bb2)
{
struct basic_block *parent;
if (dmrC_bb_list_size(bb1->parents) != 1)
return NULL;
parent = dmrC_first_basic_block(bb1->parents);
if (dmrC_bb_list_size(bb2->parents) != 1)
return NULL;
if (dmrC_first_basic_block(bb2->parents) != parent)
return NULL;
return parent;
}
static inline void remove_instruction(struct instruction_list **list, struct instruction *insn, int count)
{
ptrlist_remove((struct ptr_list **)list, insn, count);
}
static void add_instruction_to_end(struct dmr_C *C, struct instruction *insn, struct basic_block *bb)
{
struct instruction *br = dmrC_delete_last_instruction(&bb->insns);
insn->bb = bb;
dmrC_add_instruction(C, &bb->insns, insn);
dmrC_add_instruction(C, &bb->insns, br);
}
static struct instruction * try_to_cse(struct dmr_C *C, struct entrypoint *ep, struct instruction *i1, struct instruction *i2)
{
struct basic_block *b1, *b2, *common;
/*
* OK, i1 and i2 are the same instruction, modulo "target".
* We should now see if we can combine them.
*/
b1 = i1->bb;
b2 = i2->bb;
/*
* Currently we only handle the uninteresting degenerate case where
* the CSE is inside one basic-block.
*/
if (b1 == b2) {
struct instruction *insn;
FOR_EACH_PTR(b1->insns, insn) {
if (insn == i1)
return cse_one_instruction(C, i2, i1);
if (insn == i2)
return cse_one_instruction(C, i1, i2);
} END_FOR_EACH_PTR(insn);
dmrC_warning(C, b1->pos, "Whaa? unable to find CSE instructions");
return i1;
}
if (bb_dominates(ep, b1, b2, ++C->L->bb_generation))
return cse_one_instruction(C, i2, i1);
if (bb_dominates(ep, b2, b1, ++C->L->bb_generation))
return cse_one_instruction(C, i1, i2);
/* No direct dominance - but we could try to find a common ancestor.. */
common = trivial_common_parent(b1, b2);
if (common) {
i1 = cse_one_instruction(C, i2, i1);
remove_instruction(&b1->insns, i1, 1);
add_instruction_to_end(C, i1, common);
}
return i1;
}
void dmrC_cleanup_and_cse(struct dmr_C *C, struct entrypoint *ep)
{
int i;
dmrC_simplify_memops(C, ep);
repeat:
C->L->repeat_phase = 0;
clean_up_insns(C, ep);
if (C->L->repeat_phase & REPEAT_CFG_CLEANUP)
dmrC_kill_unreachable_bbs(C, ep);
for (i = 0; i < INSN_HASH_SIZE; i++) {
struct instruction_list **list = C->L->insn_hash_table + i;
if (*list) {
if (dmrC_instruction_list_size(*list) > 1) {
struct instruction *insn, *last;
sort_instruction_list(C, list);
last = NULL;
FOR_EACH_PTR(*list, insn) {
if (!insn->bb)
continue;
if (last) {
if (!insn_compare(C, last, insn))
insn = try_to_cse(C, ep, last, insn);
}
last = insn;
} END_FOR_EACH_PTR(insn);
}
ptrlist_remove_all((struct ptr_list **)list);
}
}
if (C->L->repeat_phase & REPEAT_SYMBOL_CLEANUP)
dmrC_simplify_memops(C, ep);
if (C->L->repeat_phase & REPEAT_CSE)
goto repeat;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,34 +0,0 @@
#ifndef EXPAND_H
#define EXPAND_H
/*
* sparse/expand.h
*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* Random cost numbers */
#define SIDE_EFFECTS 10000 /* The expression has side effects */
#define UNSAFE 100 /* The expression may be "infinitely costly" due to exceptions */
#define SELECT_COST 20 /* Cut-off for turning a conditional into a select */
#define BRANCH_COST 10 /* Cost of a conditional branch */
#endif

@ -1,930 +0,0 @@
/*
* sparse/expression.c
*
* Copyright (C) 2003 Transmeta Corp.
* 2003-2004 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This is the expression parsing part of parsing C.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <port.h>
#include <lib.h>
#include <allocate.h>
#include <token.h>
#include <parse.h>
#include <symbol.h>
#include <scope.h>
#include <expression.h>
#include <target.h>
#include <char.h>
static int match_oplist(int op, ...)
{
va_list args;
int nextop;
va_start(args, op);
do {
nextop = va_arg(args, int);
} while (nextop != 0 && nextop != op);
va_end(args);
return nextop != 0;
}
static struct token *comma_expression(struct dmr_C *C, struct token *, struct expression **);
struct token *dmrC_parens_expression(struct dmr_C *C, struct token *token, struct expression **expr, const char *where)
{
token = dmrC_expect_token(C, token, '(', where);
if (dmrC_match_op(token, '{')) {
struct expression *e = dmrC_alloc_expression(C, token->pos, EXPR_STATEMENT);
struct statement *stmt = dmrC_alloc_statement(C, token->pos, STMT_COMPOUND);
*expr = e;
e->statement = stmt;
dmrC_start_symbol_scope(C);
token = dmrC_compound_statement(C, token->next, stmt);
dmrC_end_symbol_scope(C);
token = dmrC_expect_token(C, token, '}', "at end of statement expression");
} else
token = dmrC_parse_expression(C, token, expr);
return dmrC_expect_token(C, token, ')', where);
}
/*
* Handle __func__, __FUNCTION__ and __PRETTY_FUNCTION__ token
* conversion
*/
static struct symbol *handle_func(struct dmr_C *C, struct token *token)
{
struct ident *ident = token->ident;
struct symbol *decl, *array;
struct string *string;
int len;
if (ident != C->S->__func___ident &&
ident != C->S->__FUNCTION___ident &&
ident != C->S->__PRETTY_FUNCTION___ident)
return NULL;
if (!C->current_fn || !C->current_fn->ident)
return NULL;
/* OK, it's one of ours */
array = dmrC_alloc_symbol(C->S, token->pos, SYM_ARRAY);
array->ctype.base_type = &C->S->char_ctype;
array->ctype.alignment = 1;
array->endpos = token->pos;
decl = dmrC_alloc_symbol(C->S, token->pos, SYM_NODE);
decl->ctype.base_type = array;
decl->ctype.alignment = 1;
decl->ctype.modifiers = MOD_STATIC;
decl->endpos = token->pos;
/* function-scope, but in NS_SYMBOL */
dmrC_bind_symbol(C->S, decl, ident, NS_LABEL);
decl->ns = NS_SYMBOL;
len = C->current_fn->ident->len;
string = (struct string *)dmrC_allocator_allocate(&C->string_allocator, len + 1);
memcpy(string->data, C->current_fn->ident->name, len);
string->data[len] = 0;
string->length = len + 1;
decl->initializer = dmrC_alloc_expression(C, token->pos, EXPR_STRING);
decl->initializer->string = string;
decl->initializer->ctype = decl;
decl->array_size = dmrC_alloc_const_expression(C, token->pos, len + 1);
array->array_size = decl->array_size;
decl->bit_size = array->bit_size = dmrC_bytes_to_bits(C->target, len + 1);
return decl;
}
static struct token *parse_type(struct dmr_C *C, struct token *token, struct expression **tree)
{
struct symbol *sym;
*tree = dmrC_alloc_expression(C, token->pos, EXPR_TYPE);
(*tree)->flags = Int_const_expr; /* sic */
token = dmrC_typename(C, token, &sym, NULL);
if (sym->ident)
dmrC_sparse_error(C, token->pos,
"type expression should not include identifier "
"\"%s\"", sym->ident->name);
(*tree)->symbol = sym;
return token;
}
static struct token *builtin_types_compatible_p_expr(struct dmr_C *C, struct token *token,
struct expression **tree)
{
struct expression *expr = dmrC_alloc_expression(
C, token->pos, EXPR_COMPARE);
expr->flags = Int_const_expr;
expr->op = SPECIAL_EQUAL;
token = token->next;
if (!dmrC_match_op(token, '('))
return dmrC_expect_token(C, token, '(',
"after __builtin_types_compatible_p");
token = token->next;
token = parse_type(C, token, &expr->left);
if (!dmrC_match_op(token, ','))
return dmrC_expect_token(C, token, ',',
"in __builtin_types_compatible_p");
token = token->next;
token = parse_type(C, token, &expr->right);
if (!dmrC_match_op(token, ')'))
return dmrC_expect_token(C, token, ')',
"at end of __builtin_types_compatible_p");
token = token->next;
*tree = expr;
return token;
}
static struct token *builtin_offsetof_expr(struct dmr_C *C, struct token *token,
struct expression **tree)
{
struct expression *expr = NULL;
struct expression **p = &expr;
struct symbol *sym;
int op = '.';
token = token->next;
if (!dmrC_match_op(token, '('))
return dmrC_expect_token(C, token, '(', "after __builtin_offset");
token = token->next;
token = dmrC_typename(C, token, &sym, NULL);
if (sym->ident)
dmrC_sparse_error(C, token->pos,
"type expression should not include identifier "
"\"%s\"", sym->ident->name);
if (!dmrC_match_op(token, ','))
return dmrC_expect_token(C, token, ',', "in __builtin_offset");
while (1) {
struct expression *e;
switch (op) {
case ')':
expr->in = sym;
*tree = expr;
default:
return dmrC_expect_token(C, token, ')', "at end of __builtin_offset");
case SPECIAL_DEREFERENCE:
e = dmrC_alloc_expression(C, token->pos, EXPR_OFFSETOF);
e->flags = Int_const_expr;
e->op = '[';
*p = e;
p = &e->down;
/* fall through */
case '.':
token = token->next;
e = dmrC_alloc_expression(C, token->pos, EXPR_OFFSETOF);
e->flags = Int_const_expr;
e->op = '.';
if (dmrC_token_type(token) != TOKEN_IDENT) {
dmrC_sparse_error(C, token->pos, "Expected member name");
return token;
}
e->ident = token->ident;
token = token->next;
break;
case '[':
token = token->next;
e = dmrC_alloc_expression(C, token->pos, EXPR_OFFSETOF);
e->flags = Int_const_expr;
e->op = '[';
token = dmrC_parse_expression(C, token, &e->index);
token = dmrC_expect_token(C, token, ']',
"at end of array dereference");
if (!e->index)
return token;
}
*p = e;
p = &e->down;
op = dmrC_token_type(token) == TOKEN_SPECIAL ? token->special : 0;
}
}
#ifndef ULLONG_MAX
#define ULLONG_MAX (~0ULL)
#endif
static unsigned long long parse_num(const char *nptr, char **end)
{
if (nptr[0] == '0' && tolower((unsigned char)nptr[1]) == 'b')
return strtoull(&nptr[2], end, 2);
return strtoull(nptr, end, 0);
}
static void get_number_value(struct dmr_C *C, struct expression *expr, struct token *token)
{
const char *str = token->number;
unsigned long long value;
char *end;
int size = 0, want_unsigned = 0;
int overflow = 0, do_warn = 0;
int try_unsigned = 1;
int bits;
errno = 0;
value = parse_num(str, &end);
if (end == str)
goto Float;
if (value == ULLONG_MAX && errno == ERANGE)
overflow = 1;
while (1) {
char c = *end++;
if (!c) {
break;
} else if (c == 'u' || c == 'U') {
if (want_unsigned)
goto Enoint;
want_unsigned = 1;
} else if (c == 'l' || c == 'L') {
if (size)
goto Enoint;
size = 1;
if (*end == c) {
size = 2;
end++;
}
} else
goto Float;
}
if (overflow)
goto Eoverflow;
/* OK, it's a valid integer */
/* decimals can be unsigned only if directly specified as such */
if (str[0] != '0' && !want_unsigned)
try_unsigned = 0;
if (!size) {
bits = C->target->bits_in_int - 1;
if (!(value & (~1ULL << bits))) {
if (!(value & (1ULL << bits))) {
goto got_it;
} else if (try_unsigned) {
want_unsigned = 1;
goto got_it;
}
}
size = 1;
do_warn = 1;
}
if (size < 2) {
bits = C->target->bits_in_long - 1;
if (!(value & (~1ULL << bits))) {
if (!(value & (1ULL << bits))) {
goto got_it;
} else if (try_unsigned) {
want_unsigned = 1;
goto got_it;
}
do_warn |= 2;
}
size = 2;
do_warn |= 1;
}
bits = C->target->bits_in_longlong - 1;
if (value & (~1ULL << bits))
goto Eoverflow;
if (!(value & (1ULL << bits)))
goto got_it;
if (!try_unsigned)
dmrC_warning(C, expr->pos, "decimal constant %s is too big for long long",
dmrC_show_token(C, token));
want_unsigned = 1;
got_it:
if (do_warn)
dmrC_warning(C, expr->pos, "constant %s is so big it is%s%s%s",
dmrC_show_token(C, token),
want_unsigned ? " unsigned":"",
size > 0 ? " long":"",
size > 1 ? " long":"");
if (do_warn & 2)
dmrC_warning(C, expr->pos,
"decimal constant %s is between LONG_MAX and ULONG_MAX."
" For C99 that means long long, C90 compilers are very "
"likely to produce unsigned long (and a warning) here",
dmrC_show_token(C, token));
expr->type = EXPR_VALUE;
expr->flags = Int_const_expr;
expr->ctype = dmrC_ctype_integer(C, size, want_unsigned);
expr->value = value;
return;
Eoverflow:
dmrC_error_die(C, expr->pos, "constant %s is too big even for unsigned long long",
dmrC_show_token(C, token));
return;
Float:
expr->fvalue = dmrC_string_to_ld(str, &end);
if (str == end)
goto Enoint;
if (*end && end[1])
goto Enoint;
if (*end == 'f' || *end == 'F')
expr->ctype = &C->S->float_ctype;
else if (*end == 'l' || *end == 'L')
expr->ctype = &C->S->ldouble_ctype;
else if (!*end)
expr->ctype = &C->S->double_ctype;
else
goto Enoint;
expr->flags = Float_literal;
expr->type = EXPR_FVALUE;
return;
Enoint:
dmrC_error_die(C, expr->pos, "constant %s is not a valid number", dmrC_show_token(C, token));
}
struct token *dmrC_primary_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
struct expression *expr = NULL;
switch (dmrC_token_type(token)) {
case TOKEN_CHAR:
case TOKEN_CHAR_EMBEDDED_0:
case TOKEN_CHAR_EMBEDDED_1:
case TOKEN_CHAR_EMBEDDED_2:
case TOKEN_CHAR_EMBEDDED_3:
case TOKEN_WIDE_CHAR:
case TOKEN_WIDE_CHAR_EMBEDDED_0:
case TOKEN_WIDE_CHAR_EMBEDDED_1:
case TOKEN_WIDE_CHAR_EMBEDDED_2:
case TOKEN_WIDE_CHAR_EMBEDDED_3:
expr = dmrC_alloc_expression(C, token->pos, EXPR_VALUE);
expr->flags = Int_const_expr;
expr->ctype = dmrC_token_type(token) < TOKEN_WIDE_CHAR ? &C->S->int_ctype : &C->S->long_ctype;
dmrC_get_char_constant(C, token, &expr->value);
token = token->next;
break;
case TOKEN_NUMBER:
expr = dmrC_alloc_expression(C, token->pos, EXPR_VALUE);
get_number_value(C, expr, token); /* will see if it's an integer */
token = token->next;
break;
case TOKEN_ZERO_IDENT: {
expr = dmrC_alloc_expression(C, token->pos, EXPR_SYMBOL);
expr->flags = Int_const_expr;
expr->ctype = &C->S->int_ctype;
expr->symbol = &C->S->zero_int;
expr->symbol_name = token->ident;
token = token->next;
break;
}
case TOKEN_IDENT: {
struct symbol *sym = dmrC_lookup_symbol(token->ident, NS_SYMBOL | NS_TYPEDEF);
struct token *next = token->next;
if (!sym) {
sym = handle_func(C, token);
if (token->ident == C->S->__builtin_types_compatible_p_ident) {
token = builtin_types_compatible_p_expr(C, token, &expr);
break;
}
if (token->ident == C->S->__builtin_offsetof_ident) {
token = builtin_offsetof_expr(C, token, &expr);
break;
}
} else if (sym->enum_member) {
expr = dmrC_alloc_expression(C, token->pos, EXPR_VALUE);
*expr = *sym->initializer;
/* we want the right position reported, thus the copy */
expr->pos = token->pos;
expr->flags = Int_const_expr;
token = next;
break;
}
expr = dmrC_alloc_expression(C, token->pos, EXPR_SYMBOL);
/*
* We support types as real first-class citizens, with type
* comparisons etc:
*
* if (typeof(a) == int) ..
*/
if (sym && sym->ns == NS_TYPEDEF) {
dmrC_sparse_error(C, token->pos, "typename in expression");
sym = NULL;
}
expr->symbol_name = token->ident;
expr->symbol = sym;
token = next;
break;
}
case TOKEN_STRING:
case TOKEN_WIDE_STRING:
expr = dmrC_alloc_expression(C, token->pos, EXPR_STRING);
token = dmrC_get_string_constant(C, token, expr);
break;
case TOKEN_SPECIAL:
if (token->special == '(') {
expr = dmrC_alloc_expression(C, token->pos, EXPR_PREOP);
expr->op = '(';
token = dmrC_parens_expression(C, token, &expr->unop, "in expression");
if (expr->unop)
expr->flags = expr->unop->flags;
break;
}
if (token->special == '[' && dmrC_lookup_type(token->next)) {
expr = dmrC_alloc_expression(C, token->pos, EXPR_TYPE);
expr->flags = Int_const_expr; /* sic */
token = dmrC_typename(C, token->next, &expr->symbol, NULL);
token = dmrC_expect_token(C, token, ']', "in type expression");
break;
}
default:
;
}
*tree = expr;
return token;
}
static struct token *expression_list(struct dmr_C *C, struct token *token, struct expression_list **list)
{
while (!dmrC_match_op(token, ')')) {
struct expression *expr = NULL;
token = dmrC_assignment_expression(C, token, &expr);
if (!expr)
break;
dmrC_add_expression(C, list, expr);
if (!dmrC_match_op(token, ','))
break;
token = token->next;
}
return token;
}
/*
* extend to deal with the ambiguous C grammar for parsing
* a cast expressions followed by an initializer.
*/
static struct token *postfix_expression(struct dmr_C *C, struct token *token, struct expression **tree, struct expression *cast_init_expr)
{
struct expression *expr = cast_init_expr;
if (!expr)
token = dmrC_primary_expression(C, token, &expr);
while (expr && dmrC_token_type(token) == TOKEN_SPECIAL) {
switch (token->special) {
case '[': { /* Array dereference */
struct expression *deref = dmrC_alloc_expression(C, token->pos, EXPR_PREOP);
struct expression *add = dmrC_alloc_expression(C, token->pos, EXPR_BINOP);
deref->op = '*';
deref->unop = add;
add->op = '+';
add->left = expr;
token = dmrC_parse_expression(C, token->next, &add->right);
token = dmrC_expect_token(C, token, ']', "at end of array dereference");
expr = deref;
continue;
}
case SPECIAL_INCREMENT: /* Post-increment */
case SPECIAL_DECREMENT: { /* Post-decrement */
struct expression *post = dmrC_alloc_expression(C, token->pos, EXPR_POSTOP);
post->op = token->special;
post->unop = expr;
expr = post;
token = token->next;
continue;
}
case SPECIAL_DEREFERENCE: { /* Structure pointer member dereference */
/* "x->y" is just shorthand for "(*x).y" */
struct expression *inner = dmrC_alloc_expression(C, token->pos, EXPR_PREOP);
inner->op = '*';
inner->unop = expr;
expr = inner;
}
/* Fall through!! */
case '.': { /* Structure member dereference */
struct expression *deref = dmrC_alloc_expression(C, token->pos, EXPR_DEREF);
deref->op = '.';
deref->deref = expr;
token = token->next;
if (dmrC_token_type(token) != TOKEN_IDENT) {
dmrC_sparse_error(C, token->pos, "Expected member name");
break;
}
deref->member = token->ident;
token = token->next;
expr = deref;
continue;
}
case '(': { /* Function call */
struct expression *call = dmrC_alloc_expression(C, token->pos, EXPR_CALL);
call->op = '(';
call->fn = expr;
token = expression_list(C, token->next, &call->args);
token = dmrC_expect_token(C, token, ')', "in function call");
expr = call;
continue;
}
default:
break;
}
break;
}
*tree = expr;
return token;
}
static struct token *cast_expression(struct dmr_C *C, struct token *token, struct expression **tree);
static struct token *unary_expression(struct dmr_C *C, struct token *token, struct expression **tree);
static struct token *type_info_expression(struct dmr_C *C, struct token *token,
struct expression **tree, int type)
{
struct expression *expr = dmrC_alloc_expression(C, token->pos, type);
struct token *p;
*tree = expr;
expr->flags = Int_const_expr; /* XXX: VLA support will need that changed */
token = token->next;
if (!dmrC_match_op(token, '(') || !dmrC_lookup_type(token->next))
return unary_expression(C, token, &expr->cast_expression);
p = token;
token = dmrC_typename(C, token->next, &expr->cast_type, NULL);
if (!dmrC_match_op(token, ')')) {
static const char * error[] = {
[EXPR_SIZEOF] = "at end of sizeof",
[EXPR_ALIGNOF] = "at end of __alignof__",
[EXPR_PTRSIZEOF] = "at end of __sizeof_ptr__"
};
return dmrC_expect_token(C, token, ')', error[type]);
}
token = token->next;
/*
* C99 ambiguity: the typename might have been the beginning
* of a typed initializer expression..
*/
if (dmrC_match_op(token, '{')) {
struct expression *cast = dmrC_alloc_expression(C, p->pos, EXPR_CAST);
cast->cast_type = expr->cast_type;
expr->cast_type = NULL;
expr->cast_expression = cast;
token = dmrC_initializer(C, &cast->cast_expression, token);
token = postfix_expression(C, token, &expr->cast_expression, cast);
}
return token;
}
static struct token *unary_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
if (dmrC_token_type(token) == TOKEN_IDENT) {
struct ident *ident = token->ident;
if (ident->reserved) {
const struct {
struct ident *id;
int type;
} type_information[] = {
{ C->S->sizeof_ident, EXPR_SIZEOF },
{ C->S->__alignof___ident, EXPR_ALIGNOF },
{ C->S->__alignof_ident, EXPR_ALIGNOF },
{ C->S->_Alignof_ident, EXPR_ALIGNOF },
{ C->S->__sizeof_ptr___ident, EXPR_PTRSIZEOF },
};
int i;
for (i = 0; i < (int)ARRAY_SIZE(type_information); i++) {
if (ident == type_information[i].id)
return type_info_expression(C, token, tree, type_information[i].type);
}
}
}
if (dmrC_token_type(token) == TOKEN_SPECIAL) {
if (match_oplist(token->special,
SPECIAL_INCREMENT, SPECIAL_DECREMENT,
'&', '*', 0)) {
struct expression *unop;
struct expression *unary;
struct token *next;
next = cast_expression(C, token->next, &unop);
if (!unop) {
dmrC_sparse_error(C, token->pos, "Syntax error in unary expression");
*tree = NULL;
return next;
}
unary = dmrC_alloc_expression(C, token->pos, EXPR_PREOP);
unary->op = token->special;
unary->unop = unop;
*tree = unary;
return next;
}
/* possibly constant ones */
if (match_oplist(token->special, '+', '-', '~', '!', 0)) {
struct expression *unop;
struct expression *unary;
struct token *next;
next = cast_expression(C, token->next, &unop);
if (!unop) {
dmrC_sparse_error(C, token->pos, "Syntax error in unary expression");
*tree = NULL;
return next;
}
unary = dmrC_alloc_expression(C, token->pos, EXPR_PREOP);
unary->op = token->special;
unary->unop = unop;
unary->flags = unop->flags & Int_const_expr;
*tree = unary;
return next;
}
/* Gcc extension: &&label gives the address of a label */
if (dmrC_match_op(token, SPECIAL_LOGICAL_AND) &&
dmrC_token_type(token->next) == TOKEN_IDENT) {
struct expression *label = dmrC_alloc_expression(C, token->pos, EXPR_LABEL);
struct symbol *sym = dmrC_label_symbol(C, token->next);
if (!(sym->ctype.modifiers & MOD_ADDRESSABLE)) {
sym->ctype.modifiers |= MOD_ADDRESSABLE;
dmrC_add_symbol(C, &C->P->function_computed_target_list, sym);
}
label->label_symbol = sym;
*tree = label;
return token->next->next;
}
}
return postfix_expression(C, token, tree, NULL);
}
/*
* Ambiguity: a '(' can be either a cast-expression or
* a primary-expression depending on whether it is followed
* by a type or not.
*
* additional ambiguity: a "cast expression" followed by
* an initializer is really a postfix-expression.
*/
static struct token *cast_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
if (dmrC_match_op(token, '(')) {
struct token *next = token->next;
if (dmrC_lookup_type(next)) {
struct expression *cast = dmrC_alloc_expression(C, next->pos, EXPR_CAST);
struct expression *v;
struct symbol *sym;
int is_force;
token = dmrC_typename(C, next, &sym, &is_force);
cast->cast_type = sym;
token = dmrC_expect_token(C, token, ')', "at end of cast operator");
if (dmrC_match_op(token, '{')) {
if (is_force)
dmrC_warning(C, sym->pos,
"[force] in compound literal");
token = dmrC_initializer(C, &cast->cast_expression, token);
return postfix_expression(C, token, tree, cast);
}
*tree = cast;
if (is_force)
cast->type = EXPR_FORCE_CAST;
token = cast_expression(C, token, &v);
if (!v)
return token;
cast->cast_expression = v;
if (v->flags & Int_const_expr)
cast->flags = Int_const_expr;
else if (v->flags & Float_literal) /* and _not_ int */
cast->flags = Int_const_expr | Float_literal;
return token;
}
}
return unary_expression(C, token, tree);
}
/*
* Generic left-to-right binop parsing
*
* This _really_ needs to be inlined, because that makes the inner
* function call statically deterministic rather than a totally
* unpredictable indirect call. But gcc-3 is so "clever" that it
* doesn't do so by default even when you tell it to inline it.
*
* Making it a macro avoids the inlining problem, and also means
* that we can pass in the op-comparison as an expression rather
* than create a data structure for it.
*/
#define LR_BINOP_EXPRESSION(C, __token, tree, type, inner, compare) \
struct expression *left = NULL; \
struct token * next = inner(C, __token, &left); \
\
if (left) { \
while (dmrC_token_type(next) == TOKEN_SPECIAL) { \
struct expression *top, *right = NULL; \
int op = next->special; \
\
if (!(compare)) \
goto out; \
top = dmrC_alloc_expression(C, next->pos, type); \
next = inner(C, next->next, &right); \
if (!right) { \
dmrC_sparse_error(C, next->pos, "No right hand side of '%s'-expression", dmrC_show_special(C, op)); \
break; \
} \
top->flags = left->flags & right->flags \
& Int_const_expr; \
top->op = op; \
top->left = left; \
top->right = right; \
left = top; \
} \
} \
out: \
*tree = left; \
return next; \
static struct token *multiplicative_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_BINOP, cast_expression,
(op == '*') || (op == '/') || (op == '%')
);
}
static struct token *additive_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_BINOP, multiplicative_expression,
(op == '+') || (op == '-')
);
}
static struct token *shift_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_BINOP, additive_expression,
(op == SPECIAL_LEFTSHIFT) || (op == SPECIAL_RIGHTSHIFT)
);
}
static struct token *relational_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_COMPARE, shift_expression,
(op == '<') || (op == '>') ||
(op == SPECIAL_LTE) || (op == SPECIAL_GTE)
);
}
static struct token *equality_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_COMPARE, relational_expression,
(op == SPECIAL_EQUAL) || (op == SPECIAL_NOTEQUAL)
);
}
static struct token *bitwise_and_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_BINOP, equality_expression,
(op == '&')
);
}
static struct token *bitwise_xor_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_BINOP, bitwise_and_expression,
(op == '^')
);
}
static struct token *bitwise_or_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_BINOP, bitwise_xor_expression,
(op == '|')
);
}
static struct token *logical_and_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_LOGICAL, bitwise_or_expression,
(op == SPECIAL_LOGICAL_AND)
);
}
static struct token *logical_or_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_LOGICAL, logical_and_expression,
(op == SPECIAL_LOGICAL_OR)
);
}
struct token *dmrC_conditional_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
token = logical_or_expression(C, token, tree);
if (*tree && dmrC_match_op(token, '?')) {
struct expression *expr = dmrC_alloc_expression(C, token->pos, EXPR_CONDITIONAL);
expr->op = token->special;
expr->left = *tree;
*tree = expr;
token = dmrC_parse_expression(C, token->next, &expr->cond_true);
token = dmrC_expect_token(C, token, ':', "in conditional expression");
token = dmrC_conditional_expression(C, token, &expr->cond_false);
if (expr->left && expr->cond_false) {
int is_const = expr->left->flags &
expr->cond_false->flags &
Int_const_expr;
if (expr->cond_true)
is_const &= expr->cond_true->flags;
expr->flags = is_const;
}
}
return token;
}
struct token *dmrC_assignment_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
token = dmrC_conditional_expression(C, token, tree);
if (*tree && dmrC_token_type(token) == TOKEN_SPECIAL) {
static const int assignments[] = {
'=',
SPECIAL_ADD_ASSIGN, SPECIAL_SUB_ASSIGN,
SPECIAL_MUL_ASSIGN, SPECIAL_DIV_ASSIGN,
SPECIAL_MOD_ASSIGN, SPECIAL_SHL_ASSIGN,
SPECIAL_SHR_ASSIGN, SPECIAL_AND_ASSIGN,
SPECIAL_OR_ASSIGN, SPECIAL_XOR_ASSIGN };
int i, op = token->special;
for (i = 0; i < (int)ARRAY_SIZE(assignments); i++)
if (assignments[i] == op) {
struct expression * expr = dmrC_alloc_expression(C, token->pos, EXPR_ASSIGNMENT);
expr->left = *tree;
expr->op = op;
*tree = expr;
return dmrC_assignment_expression(C, token->next, &expr->right);
}
}
return token;
}
static struct token *comma_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
LR_BINOP_EXPRESSION(C,
token, tree, EXPR_COMMA, dmrC_assignment_expression,
(op == ',')
);
}
struct token *dmrC_parse_expression(struct dmr_C *C, struct token *token, struct expression **tree)
{
return comma_expression(C, token,tree);
}

@ -1,265 +0,0 @@
#ifndef DMR_C_EXPRESSION_H
#define DMR_C_EXPRESSION_H
/*
* sparse/expression.h
*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Declarations and helper functions for expression parsing.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <allocate.h>
#include <lib.h>
#include <symbol.h>
#ifdef __cplusplus
extern "C" {
#endif
enum expression_type {
EXPR_VALUE = 1,
EXPR_STRING,
EXPR_SYMBOL,
EXPR_TYPE,
EXPR_BINOP,
EXPR_ASSIGNMENT,
EXPR_LOGICAL,
EXPR_DEREF,
EXPR_PREOP,
EXPR_POSTOP,
EXPR_CAST,
EXPR_FORCE_CAST,
EXPR_IMPLIED_CAST,
EXPR_SIZEOF,
EXPR_ALIGNOF,
EXPR_PTRSIZEOF,
EXPR_CONDITIONAL,
EXPR_SELECT, // a "safe" conditional expression
EXPR_STATEMENT,
EXPR_CALL,
EXPR_COMMA,
EXPR_COMPARE,
EXPR_LABEL,
EXPR_INITIALIZER, // initializer list
EXPR_IDENTIFIER, // identifier in initializer
EXPR_INDEX, // index in initializer
EXPR_POS, // position in initializer
EXPR_FVALUE,
EXPR_SLICE,
EXPR_OFFSETOF,
};
enum {
Int_const_expr = 1,
Float_literal = 2,
}; /* for expr->flags */
enum {
Taint_comma = 1,
}; /* for expr->taint */
DECLARE_PTR_LIST(expression_list, struct expression);
struct expression {
enum expression_type type:8;
unsigned flags:8;
int op;
struct position pos;
struct symbol *ctype;
union {
// EXPR_VALUE
struct {
unsigned long long value;
unsigned taint;
};
// EXPR_FVALUE
long double fvalue;
// EXPR_STRING
struct {
int wide;
struct string *string;
};
// EXPR_UNOP, EXPR_PREOP and EXPR_POSTOP
struct /* unop */ {
struct expression *unop;
unsigned long op_value;
};
// EXPR_SYMBOL, EXPR_TYPE
struct /* symbol_arg */ {
struct symbol *symbol;
struct ident *symbol_name;
};
// EXPR_STATEMENT
struct statement *statement;
// EXPR_BINOP, EXPR_COMMA, EXPR_COMPARE, EXPR_LOGICAL and EXPR_ASSIGNMENT
struct /* binop_arg */ {
struct expression *left, *right;
};
// EXPR_DEREF
struct /* deref_arg */ {
struct expression *deref;
struct ident *member;
};
// EXPR_SLICE
struct /* slice */ {
struct expression *base;
unsigned r_bitpos, r_nrbits;
};
// EXPR_CAST and EXPR_SIZEOF
struct /* cast_arg */ {
struct symbol *cast_type;
struct expression *cast_expression;
};
// EXPR_CONDITIONAL
// EXPR_SELECT
struct /* conditional_expr */ {
struct expression *conditional, *cond_true, *cond_false;
};
// EXPR_CALL
struct /* call_expr */ {
struct expression *fn;
struct expression_list *args;
};
// EXPR_LABEL
struct /* label_expr */ {
struct symbol *label_symbol;
};
// EXPR_INITIALIZER
struct expression_list *expr_list;
// EXPR_IDENTIFIER
struct /* ident_expr */ {
int offset;
struct ident *expr_ident;
struct symbol *field;
struct expression *ident_expression;
};
// EXPR_INDEX
struct /* index_expr */ {
unsigned int idx_from, idx_to;
struct expression *idx_expression;
};
// EXPR_POS
struct /* initpos_expr */ {
unsigned int init_offset, init_nr;
struct expression *init_expr;
};
// EXPR_OFFSETOF
struct {
struct symbol *in;
struct expression *down;
union {
struct ident *ident;
struct expression *index;
};
};
};
};
long long dmrC_get_expression_value_silent(struct dmr_C *C, struct expression *expr);
extern struct symbol *dmrC_evaluate_expression(struct dmr_C *C, struct expression *);
long long dmrC_get_expression_value(struct dmr_C *C, struct expression *);
/* Constant expression values */
int dmrC_is_zero_constant(struct dmr_C *C, struct expression *);
int dmrC_expr_truth_value(struct dmr_C *C, struct expression *expr);
long long dmrC_const_expression_value(struct dmr_C *C, struct expression *);
/* Expression parsing */
struct token *dmrC_conditional_expression(struct dmr_C *C, struct token *token,
struct expression **tree);
struct token *dmrC_primary_expression(struct dmr_C *C, struct token *token, struct expression **tree);
struct token *dmrC_parens_expression(struct dmr_C *C, struct token *token, struct expression **expr,
const char *where);
struct token *dmrC_assignment_expression(struct dmr_C *C, struct token *token,
struct expression **tree);
extern void dmrC_evaluate_symbol_list(struct dmr_C *C, struct symbol_list *list);
extern struct symbol *dmrC_evaluate_statement(struct dmr_C *C, struct statement *stmt);
extern int dmrC_expand_symbol(struct dmr_C *C, struct symbol *);
static inline struct expression *dmrC_alloc_expression(struct dmr_C *C, struct position pos, int type)
{
struct expression *expr = (struct expression *)dmrC_allocator_allocate(&C->expression_allocator, 0);
expr->type = (enum expression_type)type;
expr->pos = pos;
return expr;
}
static inline struct expression *dmrC_alloc_const_expression(struct dmr_C *C, struct position pos,
int value)
{
struct expression *expr = (struct expression *)dmrC_allocator_allocate(&C->expression_allocator, 0);
expr->type = EXPR_VALUE;
expr->pos = pos;
expr->value = value;
expr->ctype = &C->S->int_ctype;
return expr;
}
/* Type name parsing */
struct token *dmrC_typename(struct dmr_C *C, struct token *, struct symbol **, int *);
static inline int dmrC_lookup_type(struct token *token)
{
if (token->pos.type == TOKEN_IDENT) {
struct symbol *sym = dmrC_lookup_symbol(
token->ident,
(enum namespace_type)(NS_SYMBOL | NS_TYPEDEF));
return sym && (sym->ns & NS_TYPEDEF);
}
return 0;
}
/* Statement parsing */
struct statement *dmrC_alloc_statement(struct dmr_C *C, struct position pos, int type);
struct token *dmrC_initializer(struct dmr_C *C, struct expression **tree, struct token *token);
struct token *dmrC_compound_statement(struct dmr_C *C, struct token *, struct statement *);
/* The preprocessor calls this 'dmrC_constant_expression()' */
#define dmrC_constant_expression(C, token, tree) dmrC_conditional_expression(C, token, tree)
/* Cast folding of constant values.. */
void dmrC_cast_value(struct dmr_C *C, struct expression *expr, struct symbol *newtype,
struct expression *old, struct symbol *oldtype);
static inline struct expression *dmrC_first_expression(struct expression_list *head)
{
return (struct expression *) ptrlist_first((struct ptr_list *)head);
}
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -1,46 +0,0 @@
#ifndef DMR_C_FLOW_H
#define DMR_C_FLOW_H
/*
* Flow - walk the linearized flowgraph, simplifying it as we
* go along.
*
* Copyright (C) 2004 Linus Torvalds
*/
#include <lib.h>
#ifdef __cplusplus
extern "C" {
#endif
struct entrypoint;
struct instruction;
extern int dmrC_simplify_flow(struct dmr_C *C, struct entrypoint *ep);
extern void dmrC_simplify_symbol_usage(struct dmr_C *C, struct entrypoint *ep);
extern void dmrC_simplify_memops(struct dmr_C *C, struct entrypoint *ep);
extern void dmrC_pack_basic_blocks(struct dmr_C *C, struct entrypoint *ep);
extern void dmrC_cleanup_and_cse(struct dmr_C *C, struct entrypoint *ep);
extern int dmrC_simplify_instruction(struct dmr_C *C, struct instruction *);
extern void dmrC_kill_use(struct dmr_C *C, pseudo_t *usep);
extern void dmrC_remove_use(struct dmr_C *C, pseudo_t *);
void dmrC_check_access(struct dmr_C *C, struct instruction *insn);
void dmrC_convert_load_instruction(struct dmr_C *C, struct instruction *, pseudo_t);
void dmrC_rewrite_load_instruction(struct dmr_C *C, struct instruction *, struct pseudo_list *);
int dmrC_dominates(struct dmr_C *C, pseudo_t pseudo, struct instruction *insn, struct instruction *dom, int local);
extern void dmrC_vrfy_flow(struct entrypoint *ep);
extern int dmrC_pseudo_in_list(struct pseudo_list *list, pseudo_t pseudo);
#ifdef __cplusplus
}
#endif
#endif

@ -1,207 +0,0 @@
GCC_ATTR(BELOW100)
GCC_ATTR(OS_Task)
GCC_ATTR(OS_main)
GCC_ATTR(OS_task)
GCC_ATTR(abi_tag)
GCC_ATTR(absdata)
GCC_ATTR(address)
GCC_ATTR(alias)
GCC_ATTR(aligned)
GCC_ATTR(alloc_align)
GCC_ATTR(alloc_size)
GCC_ATTR(altivec)
GCC_ATTR(always_inline)
GCC_ATTR(artificial)
GCC_ATTR(assume_aligned)
GCC_ATTR(bank_switch)
GCC_ATTR(based)
GCC_ATTR(below100)
GCC_ATTR(bnd_instrument)
GCC_ATTR(bnd_legacy)
GCC_ATTR(bnd_variable_size)
GCC_ATTR(break_handler)
GCC_ATTR(brk_interrupt)
GCC_ATTR(callee_pop_aggregate_return)
GCC_ATTR(cb)
GCC_ATTR(cdecl)
GCC_ATTR(cleanup)
GCC_ATTR(cmse_nonsecure_call)
GCC_ATTR(cmse_nonsecure_entry)
GCC_ATTR(cold)
GCC_ATTR(common)
GCC_ATTR(common_object)
GCC_ATTR(const)
GCC_ATTR(constructor)
GCC_ATTR(critical)
GCC_ATTR(default)
GCC_ATTR(deprecated)
GCC_ATTR(designated_init)
GCC_ATTR(destructor)
GCC_ATTR(disinterrupt)
GCC_ATTR(dllexport)
GCC_ATTR(dllimport)
GCC_ATTR(eightbit_data)
GCC_ATTR(either)
GCC_ATTR(error)
GCC_ATTR(exception)
GCC_ATTR(exception_handler)
GCC_ATTR(externally_visible)
GCC_ATTR(fallthrough)
GCC_ATTR(far)
GCC_ATTR(fast_interrupt)
GCC_ATTR(fastcall)
GCC_ATTR(flatten)
GCC_ATTR(force_align_arg_pointer)
GCC_ATTR(format)
GCC_ATTR(format_arg)
GCC_ATTR(forwarder_section)
GCC_ATTR(function_vector)
GCC_ATTR(gcc_struct)
GCC_ATTR(gnu_inline)
GCC_ATTR(hidden)
GCC_ATTR(hot)
GCC_ATTR(hotpatch)
GCC_ATTR(ifunc)
GCC_ATTR(init_priority)
GCC_ATTR(interfacearm)
GCC_ATTR(internal)
GCC_ATTR(interrupt)
GCC_ATTR(interrupt_handler)
GCC_ATTR(interrupt_thread)
GCC_ATTR(io)
GCC_ATTR(io_low)
GCC_ATTR(isr)
GCC_ATTR(keep_interrupts_masked)
GCC_ATTR(kernel)
GCC_ATTR(kspisusp)
GCC_ATTR(l1_data)
GCC_ATTR(l1_data_A)
GCC_ATTR(l1_data_B)
GCC_ATTR(l1_text)
GCC_ATTR(l2)
GCC_ATTR(leaf)
GCC_ATTR(long_call)
GCC_ATTR(longcall)
GCC_ATTR(lower)
GCC_ATTR(malloc)
GCC_ATTR(may_alias)
GCC_ATTR(maybe_unused)
GCC_ATTR(medium_call)
GCC_ATTR(micromips)
GCC_ATTR(mips16)
GCC_ATTR(mode)
GCC_ATTR(model)
GCC_ATTR(monitor)
GCC_ATTR(ms_abi)
GCC_ATTR(ms_hook_prologue)
GCC_ATTR(ms_struct)
GCC_ATTR(naked)
GCC_ATTR(near)
GCC_ATTR(nested)
GCC_ATTR(nested_ready)
GCC_ATTR(nesting)
GCC_ATTR(nmi)
GCC_ATTR(nmi_handler)
GCC_ATTR(no_address_safety_analysis)
GCC_ATTR(no_caller_saved_registers)
GCC_ATTR(no_gccisr)
GCC_ATTR(no_icf)
GCC_ATTR(no_instrument_function)
GCC_ATTR(no_profile_instrument_function)
GCC_ATTR(no_reorder)
GCC_ATTR(no_sanitize)
GCC_ATTR(no_sanitize_address)
GCC_ATTR(no_sanitize_thread)
GCC_ATTR(no_sanitize_undefined)
GCC_ATTR(no_split_stack)
GCC_ATTR(no_stack_limit)
GCC_ATTR(noclone)
GCC_ATTR(nocommon)
GCC_ATTR(nocompression)
GCC_ATTR(nodiscard)
GCC_ATTR(noinit)
GCC_ATTR(noinline)
GCC_ATTR(noipa)
GCC_ATTR(nomicromips)
GCC_ATTR(nomips16)
GCC_ATTR(nonnull)
GCC_ATTR(noplt)
GCC_ATTR(noreturn)
GCC_ATTR(nosave_low_regs)
GCC_ATTR(not_nested)
GCC_ATTR(nothrow)
GCC_ATTR(notshared)
GCC_ATTR(optimize)
GCC_ATTR(packed)
GCC_ATTR(partial_save)
GCC_ATTR(patchable_function_entry)
GCC_ATTR(pcs)
GCC_ATTR(persistent)
GCC_ATTR(progmem)
GCC_ATTR(protected)
GCC_ATTR(pure)
GCC_ATTR(reentrant)
GCC_ATTR(regparm)
GCC_ATTR(renesas)
GCC_ATTR(resbank)
GCC_ATTR(reset)
GCC_ATTR(returns_nonnull)
GCC_ATTR(returns_twice)
GCC_ATTR(s390_vector_bool)
GCC_ATTR(saddr)
GCC_ATTR(save_all)
GCC_ATTR(save_volatiles)
GCC_ATTR(saveall)
GCC_ATTR(scalar_storage_order)
GCC_ATTR(sda)
GCC_ATTR(section)
GCC_ATTR(selectany)
GCC_ATTR(sentinel)
GCC_ATTR(shared)
GCC_ATTR(short_call)
GCC_ATTR(shortcall)
GCC_ATTR(signal)
GCC_ATTR(simd)
GCC_ATTR(sp_switch)
GCC_ATTR(spu_vector)
GCC_ATTR(sseregparm)
GCC_ATTR(stack_protect)
GCC_ATTR(stdcall)
GCC_ATTR(syscall_linkage)
GCC_ATTR(sysv_abi)
GCC_ATTR(target)
GCC_ATTR(target_clones)
GCC_ATTR(tda)
GCC_ATTR(thiscall)
GCC_ATTR(tiny)
GCC_ATTR(tiny_data)
GCC_ATTR(tls_model)
GCC_ATTR(transaction_callable)
GCC_ATTR(transaction_may_cancel_outer)
GCC_ATTR(transaction_pure)
GCC_ATTR(transaction_safe)
GCC_ATTR(transaction_safe_dynamic)
GCC_ATTR(transaction_unsafe)
GCC_ATTR(transaction_wrap)
GCC_ATTR(transparent_union)
GCC_ATTR(trap_exit)
GCC_ATTR(trapa_handler)
GCC_ATTR(unused)
GCC_ATTR(upper)
GCC_ATTR(use_debug_exception_return)
GCC_ATTR(use_shadow_register_set)
GCC_ATTR(used)
GCC_ATTR(vector)
GCC_ATTR(vector_size)
GCC_ATTR(version_id)
GCC_ATTR(visibility)
GCC_ATTR(vliw)
GCC_ATTR(volatile)
GCC_ATTR(wakeup)
GCC_ATTR(warm)
GCC_ATTR(warn_unused)
GCC_ATTR(warn_unused_result)
GCC_ATTR(warning)
GCC_ATTR(weak)
GCC_ATTR(weakref)
GCC_ATTR(zda)

@ -1,140 +0,0 @@
#define IDENT(n) __IDENT(n## _ident, #n, 0)
#define IDENT_RESERVED(n) __IDENT(n## _ident, #n, 1)
/* Basic C reserved words.. */
IDENT_RESERVED(sizeof);
IDENT_RESERVED(if);
IDENT_RESERVED(else);
IDENT_RESERVED(return);
IDENT_RESERVED(switch);
IDENT_RESERVED(case);
IDENT_RESERVED(default);
IDENT_RESERVED(break);
IDENT_RESERVED(continue);
IDENT_RESERVED(for);
IDENT_RESERVED(while);
IDENT_RESERVED(do);
IDENT_RESERVED(goto);
/* C typenames. They get marked as reserved when initialized */
IDENT(struct);
IDENT(union);
IDENT(enum);
IDENT(__attribute); IDENT(__attribute__);
IDENT(volatile); IDENT(__volatile); IDENT(__volatile__);
IDENT(double);
/* C storage classes. They get marked as reserved when initialized */
IDENT(static);
/* C99 keywords */
IDENT(restrict); IDENT(__restrict); IDENT(__restrict__);
IDENT(_Bool);
IDENT_RESERVED(_Complex);
IDENT_RESERVED(_Imaginary);
/* C11 keywords */
IDENT(_Alignas);
IDENT_RESERVED(_Alignof);
IDENT_RESERVED(_Atomic);
IDENT_RESERVED(_Generic);
IDENT(_Noreturn);
IDENT_RESERVED(_Static_assert);
IDENT(_Thread_local);
/* Special case for L'\t' */
IDENT(L);
/* Extended gcc identifiers */
IDENT(asm); IDENT_RESERVED(__asm); IDENT_RESERVED(__asm__);
IDENT(alignof); IDENT_RESERVED(__alignof); IDENT_RESERVED(__alignof__);
IDENT_RESERVED(__sizeof_ptr__);
IDENT_RESERVED(__builtin_types_compatible_p);
IDENT_RESERVED(__builtin_offsetof);
IDENT_RESERVED(__label__);
/* Attribute names */
IDENT(packed); IDENT(__packed__);
IDENT(aligned); IDENT(__aligned__);
IDENT(nocast);
IDENT(noderef);
IDENT(safe);
IDENT(force);
IDENT(address_space);
IDENT(context);
IDENT(mode); IDENT(__mode__);
IDENT(QI); IDENT(__QI__);
IDENT(HI); IDENT(__HI__);
IDENT(SI); IDENT(__SI__);
IDENT(DI); IDENT(__DI__);
IDENT(word); IDENT(__word__);
IDENT(format); IDENT(__format__);
IDENT(section); IDENT(__section__);
IDENT(unused); IDENT(__unused__);
IDENT(const); IDENT(__const); IDENT(__const__);
IDENT(used); IDENT(__used__);
IDENT(warn_unused_result); IDENT(__warn_unused_result__);
IDENT(noinline); IDENT(__noinline__);
IDENT(deprecated); IDENT(__deprecated__);
IDENT(noreturn); IDENT(__noreturn__);
IDENT(regparm); IDENT(__regparm__);
IDENT(weak); IDENT(__weak__);
IDENT(no_instrument_function); IDENT(__no_instrument_function__);
IDENT(sentinel); IDENT(__sentinel__);
IDENT(alias); IDENT(__alias__);
IDENT(pure); IDENT(__pure__);
IDENT(always_inline); IDENT(__always_inline__);
IDENT(syscall_linkage); IDENT(__syscall_linkage__);
IDENT(visibility); IDENT(__visibility__);
IDENT(bitwise); IDENT(__bitwise__);
IDENT(model); IDENT(__model__);
IDENT(format_arg); IDENT(__format_arg__);
IDENT(nothrow); IDENT(__nothrow); IDENT(__nothrow__);
IDENT(__transparent_union__);
IDENT(malloc);
IDENT(__malloc__);
IDENT(nonnull); IDENT(__nonnull); IDENT(__nonnull__);
IDENT(constructor); IDENT(__constructor__);
IDENT(destructor); IDENT(__destructor__);
IDENT(cold); IDENT(__cold__);
IDENT(hot); IDENT(__hot__);
IDENT(cdecl); IDENT(__cdecl__);
IDENT(stdcall); IDENT(__stdcall__);
IDENT(fastcall); IDENT(__fastcall__);
IDENT(dllimport); IDENT(__dllimport__);
IDENT(dllexport); IDENT(__dllexport__);
IDENT(artificial); IDENT(__artificial__);
IDENT(leaf); IDENT(__leaf__);
IDENT(vector_size); IDENT(__vector_size__);
IDENT(error); IDENT(__error__);
/* Preprocessor idents. Direct use of __IDENT avoids mentioning the keyword
* itself by name, preventing these tokens from expanding when compiling
* sparse. */
IDENT(defined);
IDENT(once);
__IDENT(pragma_ident, "__pragma__", 0);
__IDENT(__VA_ARGS___ident, "__VA_ARGS__", 0);
__IDENT(__LINE___ident, "__LINE__", 0);
__IDENT(__FILE___ident, "__FILE__", 0);
__IDENT(__DATE___ident, "__DATE__", 0);
__IDENT(__TIME___ident, "__TIME__", 0);
__IDENT(__func___ident, "__func__", 0);
__IDENT(__FUNCTION___ident, "__FUNCTION__", 0);
__IDENT(__PRETTY_FUNCTION___ident, "__PRETTY_FUNCTION__", 0);
__IDENT(__COUNTER___ident, "__COUNTER__", 0);
/* Sparse commands */
IDENT_RESERVED(__context__);
IDENT_RESERVED(__range__);
/* Magic function names we recognize */
IDENT(memset); IDENT(memcpy);
IDENT(copy_to_user); IDENT(copy_from_user);
IDENT(main);
#undef __IDENT
#undef IDENT
#undef IDENT_RESERVED

@ -1,590 +0,0 @@
/*
* Sparse - a semantic source parser.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003-2004 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <stdlib.h>
#include <stdio.h>
#include <port.h>
#include <lib.h>
#include <allocate.h>
#include <token.h>
#include <parse.h>
#include <symbol.h>
#include <expression.h>
static struct expression * dup_expression(struct dmr_C *C, struct expression *expr)
{
struct expression *dup = dmrC_alloc_expression(C, expr->pos, expr->type);
*dup = *expr;
return dup;
}
static struct statement * dup_statement(struct dmr_C *C, struct statement *stmt)
{
struct statement *dup = dmrC_alloc_statement(C, stmt->pos, stmt->type);
*dup = *stmt;
return dup;
}
static struct symbol *copy_symbol(struct dmr_C *C, struct position pos, struct symbol *sym)
{
if (!sym)
return sym;
if (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN | MOD_TOPLEVEL | MOD_INLINE))
return sym;
if (!sym->replace) {
dmrC_warning(C, pos, "unreplaced symbol '%s'", dmrC_show_ident(C, sym->ident));
return sym;
}
return sym->replace;
}
static struct symbol_list *copy_symbol_list(struct dmr_C *C, struct symbol_list *src)
{
struct symbol_list *dst = NULL;
struct symbol *sym;
FOR_EACH_PTR(src, sym) {
struct symbol *newsym = copy_symbol(C, sym->pos, sym);
dmrC_add_symbol(C, &dst, newsym);
} END_FOR_EACH_PTR(sym);
return dst;
}
static struct expression * copy_expression(struct dmr_C *C, struct expression *expr)
{
if (!expr)
return NULL;
switch (expr->type) {
/*
* EXPR_SYMBOL is the interesting case, we may need to replace the
* symbol to the new copy.
*/
case EXPR_SYMBOL: {
struct symbol *sym = copy_symbol(C, expr->pos, expr->symbol);
if (sym == expr->symbol)
break;
expr = dup_expression(C, expr);
expr->symbol = sym;
break;
}
/* Atomics, never change, just return the expression directly */
case EXPR_VALUE:
case EXPR_STRING:
case EXPR_FVALUE:
case EXPR_TYPE:
break;
/* Unops: check if the subexpression is unique */
case EXPR_PREOP:
case EXPR_POSTOP: {
struct expression *unop = copy_expression(C, expr->unop);
if (expr->unop == unop)
break;
expr = dup_expression(C, expr);
expr->unop = unop;
break;
}
case EXPR_SLICE: {
struct expression *base = copy_expression(C, expr->base);
expr = dup_expression(C, expr);
expr->base = base;
break;
}
/* Binops: copy left/right expressions */
case EXPR_BINOP:
case EXPR_COMMA:
case EXPR_COMPARE:
case EXPR_LOGICAL: {
struct expression *left = copy_expression(C, expr->left);
struct expression *right = copy_expression(C, expr->right);
if (left == expr->left && right == expr->right)
break;
expr = dup_expression(C, expr);
expr->left = left;
expr->right = right;
break;
}
case EXPR_ASSIGNMENT: {
struct expression *left = copy_expression(C, expr->left);
struct expression *right = copy_expression(C, expr->right);
if (expr->op == '=' && left == expr->left && right == expr->right)
break;
expr = dup_expression(C, expr);
expr->left = left;
expr->right = right;
break;
}
/* Dereference */
case EXPR_DEREF: {
struct expression *deref = copy_expression(C, expr->deref);
expr = dup_expression(C, expr);
expr->deref = deref;
break;
}
/* Cast/sizeof/__alignof__ */
case EXPR_CAST:
if (expr->cast_expression->type == EXPR_INITIALIZER) {
struct expression *cast = expr->cast_expression;
struct symbol *sym = expr->cast_type;
expr = dup_expression(C, expr);
expr->cast_expression = copy_expression(C, cast);
expr->cast_type = dmrC_alloc_symbol(C->S, sym->pos, sym->type);
*expr->cast_type = *sym;
break;
}
case EXPR_FORCE_CAST:
case EXPR_IMPLIED_CAST:
case EXPR_SIZEOF:
case EXPR_PTRSIZEOF:
case EXPR_ALIGNOF: {
struct expression *cast = copy_expression(C, expr->cast_expression);
if (cast == expr->cast_expression)
break;
expr = dup_expression(C, expr);
expr->cast_expression = cast;
break;
}
/* Conditional expression */
case EXPR_SELECT:
case EXPR_CONDITIONAL: {
struct expression *cond = copy_expression(C, expr->conditional);
struct expression *truee = copy_expression(C, expr->cond_true);
struct expression *falsee = copy_expression(C, expr->cond_false);
if (cond == expr->conditional && truee == expr->cond_true && falsee == expr->cond_false)
break;
expr = dup_expression(C, expr);
expr->conditional = cond;
expr->cond_true = truee;
expr->cond_false = falsee;
break;
}
/* Statement expression */
case EXPR_STATEMENT: {
struct statement *stmt = dmrC_alloc_statement(C, expr->pos, STMT_COMPOUND);
dmrC_copy_statement(C, expr->statement, stmt);
expr = dup_expression(C, expr);
expr->statement = stmt;
break;
}
/* Call expression */
case EXPR_CALL: {
struct expression *fn = copy_expression(C, expr->fn);
struct expression_list *list = expr->args;
struct expression *arg;
expr = dup_expression(C, expr);
expr->fn = fn;
expr->args = NULL;
FOR_EACH_PTR(list, arg) {
dmrC_add_expression(C, &expr->args, copy_expression(C, arg));
} END_FOR_EACH_PTR(arg);
break;
}
/* Initializer list statement */
case EXPR_INITIALIZER: {
struct expression_list *list = expr->expr_list;
struct expression *entry;
expr = dup_expression(C, expr);
expr->expr_list = NULL;
FOR_EACH_PTR(list, entry) {
dmrC_add_expression(C, &expr->expr_list, copy_expression(C, entry));
} END_FOR_EACH_PTR(entry);
break;
}
/* Label in inline function - hmm. */
case EXPR_LABEL: {
struct symbol *label_symbol = copy_symbol(C, expr->pos, expr->label_symbol);
expr = dup_expression(C, expr);
expr->label_symbol = label_symbol;
break;
}
case EXPR_INDEX: {
struct expression *sub_expr = copy_expression(C, expr->idx_expression);
expr = dup_expression(C, expr);
expr->idx_expression = sub_expr;
break;
}
case EXPR_IDENTIFIER: {
struct expression *sub_expr = copy_expression(C, expr->ident_expression);
expr = dup_expression(C, expr);
expr->ident_expression = sub_expr;
break;
}
/* Position in initializer.. */
case EXPR_POS: {
struct expression *val = copy_expression(C, expr->init_expr);
expr = dup_expression(C, expr);
expr->init_expr = val;
break;
}
case EXPR_OFFSETOF: {
struct expression *val = copy_expression(C, expr->down);
if (expr->op == '.') {
if (expr->down != val) {
expr = dup_expression(C, expr);
expr->down = val;
}
} else {
struct expression *idx = copy_expression(C, expr->index);
if (expr->down != val || expr->index != idx) {
expr = dup_expression(C, expr);
expr->down = val;
expr->index = idx;
}
}
break;
}
default:
dmrC_warning(C, expr->pos, "trying to copy expression type %d", expr->type);
}
return expr;
}
static struct expression_list *copy_asm_constraints(struct dmr_C *C, struct expression_list *in)
{
struct expression_list *out = NULL;
struct expression *expr;
int state = 0;
FOR_EACH_PTR(in, expr) {
switch (state) {
case 0: /* identifier */
case 1: /* constraint */
state++;
dmrC_add_expression(C, &out, expr);
continue;
case 2: /* expression */
state = 0;
dmrC_add_expression(C, &out, copy_expression(C, expr));
continue;
}
} END_FOR_EACH_PTR(expr);
return out;
}
static void set_replace(struct symbol *old, struct symbol *news)
{
news->replace = old;
old->replace = news;
}
static void unset_replace(struct dmr_C *C, struct symbol *sym)
{
struct symbol *r = sym->replace;
if (!r) {
dmrC_warning(C, sym->pos, "symbol '%s' not replaced?", dmrC_show_ident(C, sym->ident));
return;
}
r->replace = NULL;
sym->replace = NULL;
}
static void unset_replace_list(struct dmr_C *C, struct symbol_list *list)
{
struct symbol *sym;
FOR_EACH_PTR(list, sym) {
unset_replace(C, sym);
} END_FOR_EACH_PTR(sym);
}
static struct statement *copy_one_statement(struct dmr_C *C, struct statement *stmt)
{
if (!stmt)
return NULL;
switch(stmt->type) {
case STMT_NONE:
break;
case STMT_DECLARATION: {
struct symbol *sym;
struct statement *newstmt = dup_statement(C, stmt);
newstmt->declaration = NULL;
FOR_EACH_PTR(stmt->declaration, sym) {
struct symbol *newsym = copy_symbol(C, stmt->pos, sym);
if (newsym != sym)
newsym->initializer = copy_expression(C, sym->initializer);
dmrC_add_symbol(C, &newstmt->declaration, newsym);
} END_FOR_EACH_PTR(sym);
stmt = newstmt;
break;
}
case STMT_CONTEXT:
case STMT_EXPRESSION: {
struct expression *expr = copy_expression(C, stmt->expression);
if (expr == stmt->expression)
break;
stmt = dup_statement(C, stmt);
stmt->expression = expr;
break;
}
case STMT_RANGE: {
struct expression *expr = copy_expression(C, stmt->range_expression);
if (expr == stmt->expression)
break;
stmt = dup_statement(C, stmt);
stmt->range_expression = expr;
break;
}
case STMT_COMPOUND: {
struct statement *newst = dmrC_alloc_statement(C, stmt->pos, STMT_COMPOUND);
dmrC_copy_statement(C, stmt, newst);
stmt = newst;
break;
}
case STMT_IF: {
struct expression *cond = stmt->if_conditional;
struct statement *trues = stmt->if_true;
struct statement *falses = stmt->if_false;
cond = copy_expression(C, cond);
trues = copy_one_statement(C, trues);
falses = copy_one_statement(C, falses);
if (stmt->if_conditional == cond &&
stmt->if_true == trues &&
stmt->if_false == falses)
break;
stmt = dup_statement(C, stmt);
stmt->if_conditional = cond;
stmt->if_true = trues;
stmt->if_false = falses;
break;
}
case STMT_RETURN: {
struct expression *retval = copy_expression(C, stmt->ret_value);
struct symbol *sym = copy_symbol(C, stmt->pos, stmt->ret_target);
stmt = dup_statement(C, stmt);
stmt->ret_value = retval;
stmt->ret_target = sym;
break;
}
case STMT_CASE: {
stmt = dup_statement(C, stmt);
stmt->case_label = copy_symbol(C, stmt->pos, stmt->case_label);
stmt->case_label->stmt = stmt;
stmt->case_expression = copy_expression(C, stmt->case_expression);
stmt->case_to = copy_expression(C, stmt->case_to);
stmt->case_statement = copy_one_statement(C, stmt->case_statement);
break;
}
case STMT_SWITCH: {
struct symbol *switch_break = copy_symbol(C, stmt->pos, stmt->switch_break);
struct symbol *switch_case = copy_symbol(C, stmt->pos, stmt->switch_case);
struct expression *expr = copy_expression(C, stmt->switch_expression);
struct statement *switch_stmt = copy_one_statement(C, stmt->switch_statement);
stmt = dup_statement(C, stmt);
switch_case->symbol_list = copy_symbol_list(C, switch_case->symbol_list);
stmt->switch_break = switch_break;
stmt->switch_case = switch_case;
stmt->switch_expression = expr;
stmt->switch_statement = switch_stmt;
break;
}
case STMT_ITERATOR: {
stmt = dup_statement(C, stmt);
stmt->iterator_break = copy_symbol(C, stmt->pos, stmt->iterator_break);
stmt->iterator_continue = copy_symbol(C, stmt->pos, stmt->iterator_continue);
stmt->iterator_syms = copy_symbol_list(C, stmt->iterator_syms);
stmt->iterator_pre_statement = copy_one_statement(C, stmt->iterator_pre_statement);
stmt->iterator_pre_condition = copy_expression(C, stmt->iterator_pre_condition);
stmt->iterator_statement = copy_one_statement(C, stmt->iterator_statement);
stmt->iterator_post_statement = copy_one_statement(C, stmt->iterator_post_statement);
stmt->iterator_post_condition = copy_expression(C, stmt->iterator_post_condition);
break;
}
case STMT_LABEL: {
stmt = dup_statement(C, stmt);
stmt->label_identifier = copy_symbol(C, stmt->pos, stmt->label_identifier);
stmt->label_statement = copy_one_statement(C, stmt->label_statement);
break;
}
case STMT_GOTO: {
stmt = dup_statement(C, stmt);
stmt->goto_label = copy_symbol(C, stmt->pos, stmt->goto_label);
stmt->goto_expression = copy_expression(C, stmt->goto_expression);
stmt->target_list = copy_symbol_list(C, stmt->target_list);
break;
}
case STMT_ASM: {
stmt = dup_statement(C, stmt);
stmt->asm_inputs = copy_asm_constraints(C, stmt->asm_inputs);
stmt->asm_outputs = copy_asm_constraints(C, stmt->asm_outputs);
/* no need to dup "clobbers", since they are all constant strings */
break;
}
default:
dmrC_warning(C, stmt->pos, "trying to copy statement type %d", stmt->type);
break;
}
return stmt;
}
/*
* Copy a statement tree from 'src' to 'dst', where both
* source and destination are of type STMT_COMPOUND.
*
* We do this for the tree-level inliner.
*
* This doesn't do the symbol replacement right: it's not
* re-entrant.
*/
void dmrC_copy_statement(struct dmr_C *C, struct statement *src, struct statement *dst)
{
struct statement *stmt;
FOR_EACH_PTR(src->stmts, stmt) {
dmrC_add_statement(C, &dst->stmts, copy_one_statement(C, stmt));
} END_FOR_EACH_PTR(stmt);
dst->args = copy_one_statement(C, src->args);
dst->ret = copy_symbol(C, src->pos, src->ret);
dst->inline_fn = src->inline_fn;
}
static struct symbol *create_copy_symbol(struct dmr_C *C, struct symbol *orig)
{
struct symbol *sym = orig;
if (orig) {
sym = dmrC_alloc_symbol(C->S, orig->pos, orig->type);
*sym = *orig;
sym->bb_target = NULL;
sym->pseudo = NULL;
set_replace(orig, sym);
orig = sym;
}
return orig;
}
static struct symbol_list *create_symbol_list(struct dmr_C *C, struct symbol_list *src)
{
struct symbol_list *dst = NULL;
struct symbol *sym;
FOR_EACH_PTR(src, sym) {
struct symbol *newsym = create_copy_symbol(C, sym);
dmrC_add_symbol(C, &dst, newsym);
} END_FOR_EACH_PTR(sym);
return dst;
}
int dmrC_inline_function(struct dmr_C *C, struct expression *expr, struct symbol *sym)
{
struct symbol_list * fn_symbol_list;
struct symbol *fn = sym->ctype.base_type;
struct expression_list *arg_list = expr->args;
struct statement *stmt = dmrC_alloc_statement(C, expr->pos, STMT_COMPOUND);
struct symbol_list *name_list, *arg_decl;
struct symbol *name;
struct expression *arg;
if (!fn->inline_stmt) {
dmrC_sparse_error(C, fn->pos, "marked inline, but without a definition");
return 0;
}
if (fn->expanding)
return 0;
fn->expanding = 1;
name_list = fn->arguments;
expr->type = EXPR_STATEMENT;
expr->statement = stmt;
expr->ctype = fn->ctype.base_type;
fn_symbol_list = create_symbol_list(C, sym->inline_symbol_list);
arg_decl = NULL;
PREPARE_PTR_LIST(name_list, name);
FOR_EACH_PTR(arg_list, arg) {
struct symbol *a = dmrC_alloc_symbol(C->S, arg->pos, SYM_NODE);
a->ctype.base_type = arg->ctype;
if (name) {
*a = *name;
set_replace(name, a);
dmrC_add_symbol(C, &fn_symbol_list, a);
}
a->initializer = arg;
dmrC_add_symbol(C, &arg_decl, a);
NEXT_PTR_LIST(name);
} END_FOR_EACH_PTR(arg);
FINISH_PTR_LIST(name);
dmrC_copy_statement(C, fn->inline_stmt, stmt);
if (arg_decl) {
struct statement *decl = dmrC_alloc_statement(C, expr->pos, STMT_DECLARATION);
decl->declaration = arg_decl;
stmt->args = decl;
}
stmt->inline_fn = sym;
unset_replace_list(C, fn_symbol_list);
dmrC_evaluate_statement(C, stmt);
fn->expanding = 0;
return 1;
}
void dmrC_uninline(struct dmr_C *C, struct symbol *sym)
{
struct symbol *fn = sym->ctype.base_type;
struct symbol_list *arg_list = fn->arguments;
struct symbol *p;
sym->symbol_list = create_symbol_list(C, sym->inline_symbol_list);
FOR_EACH_PTR(arg_list, p) {
p->replace = p;
} END_FOR_EACH_PTR(p);
fn->stmt = dmrC_alloc_statement(C, fn->pos, STMT_COMPOUND);
dmrC_copy_statement(C, fn->inline_stmt, fn->stmt);
unset_replace_list(C, sym->symbol_list);
unset_replace_list(C, arg_list);
}

File diff suppressed because it is too large Load Diff

@ -1,302 +0,0 @@
#ifndef DMR_LIB_H
#define DMR_LIB_H
/* This file is derived from lib.h in sparse */
#include <stddef.h>
#include <stdlib.h>
#include <time.h>
#include <setjmp.h>
/*
* Basic helper routine descriptions for 'sparse'.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
* 2004 Christopher Li
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
// Build options
#define NEW_SSA 0
#define SINGLE_STORE_SHORTCUT 1
#include <allocate.h>
#include <ptrlist.h>
#ifdef __cplusplus
extern "C" {
#endif
#define DO_STRINGIFY(x) #x
#define STRINGIFY(x) DO_STRINGIFY(x)
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
#define MAX_STRING 8191
extern unsigned int dmrC_hexval(unsigned int c);
struct position {
unsigned int type : 6,
stream : 14,
newline : 1,
whitespace : 1,
pos : 10;
unsigned int line : 31,
noexpand : 1;
};
struct ident;
struct token;
struct symbol;
struct statement;
struct expression;
struct basic_block;
struct entrypoint;
struct instruction;
struct multijmp;
struct pseudo;
struct string;
typedef struct pseudo *pseudo_t;
struct target_t;
struct global_symbols_t;
struct tokenizer_state_t;
struct linearizer_state_t;
struct warning {
const char *name;
int *flag;
};
enum standard {
STANDARD_C89,
STANDARD_C94,
STANDARD_C99,
STANDARD_C11,
STANDARD_GNU11,
STANDARD_GNU89,
STANDARD_GNU99,
};
enum {
WARNING_OFF,
WARNING_ON,
WARNING_FORCE_OFF
};
struct symbol_list;
struct statement_list;
struct expression_list;
struct basic_block_list;
struct instruction_list;
struct multijmp_list;
struct pseudo_list;
struct phi_map;
DECLARE_PTR_LIST(string_list, char);
#define ERROR_CURR_PHASE (1 << 0)
#define ERROR_PREV_PHASE (1 << 1)
struct dmr_C {
struct target_t *target;
struct global_symbols_t *S;
struct tokenizer_state_t *T;
struct parse_state_t *P;
struct linearizer_state_t *L;
void *User_data;
// memory allocators
struct allocator ptrlist_allocator;
struct allocator token_allocator;
struct allocator protected_token_allocator;
struct allocator byte_allocator;
struct allocator string_allocator;
struct allocator ident_allocator;
struct allocator scope_allocator;
struct allocator expression_allocator;
struct allocator statement_allocator;
int max_warnings;
int show_info;
int errors;
int die_if_error;
int once;
int preprocess_only;
int codegen;
int has_error;
jmp_buf jmpbuf;
const char *gcc_base_dir;
const char *multiarch_dir;
int verbose, optimize, optimize_size, preprocessing;
enum standard standard;
struct token *pre_buffer_begin;
struct token *pre_buffer_end;
int Waddress; // TODO
int Waddress_space;
int Wbitwise;
int Wcast_to_as;
int Wcast_truncate;
int Wcontext;
int Wdecl;
int Wdeclarationafterstatement;
int Wdefault_bitfield_sign;
int Wdesignated_init;
int Wdo_while;
int Wenum_mismatch;
int Wsparse_error;
int Winit_cstring;
int Wmemcpy_max_count; // TODO
int Wnon_pointer_null;
int Wold_initializer;
int Wone_bit_signed_bitfield;
int Woverride_init; //TODO
int Woverride_init_all; //TODO
int Woverride_init_whole_range; //TODO
int Wparen_string;
int Wptr_subtraction_blows;
int Wreturn_void;
int Wshadow;
int Wsizeof_bool;
int Wtautological_compare;
int Wtransparent_union;
int Wtypesign;
int Wundef;
int Wuninitialized;
int Wunknown_attribute;
int Wvla;
struct warning warnings[32];
struct warning debugs[2];
struct warning dumps[1];
#define CMDLINE_INCLUDE 20
int cmdline_include_nr;
char *cmdline_include[CMDLINE_INCLUDE];
int dump_macro_defs; // TODO
int dbg_entry;
int dbg_dead;
int fmem_report; // TODO
int fdump_linearize; // TODO
unsigned long long fmemcpy_max_count;
int arch_m64;
int arch_msize_long;
int arch_big_endian; // TODO
/* TODO is this the right place? */
struct scope *block_scope, *function_scope, *file_scope, *global_scope;
struct scope *builtin_scope;
/* Current parsing/evaluation function */
struct symbol *current_fn;
char modifier_string_buffer[100];
char typename_array[200];
struct ident_list *macros; // only needed for -dD
int false_nesting;
int counter_macro; // __COUNTER__ expansion
#define INCLUDEPATHS 300
const char *includepath[INCLUDEPATHS + 1];
const char **quote_includepath;
const char **angle_includepath;
const char **isys_includepath;
const char **sys_includepath;
const char **dirafter_includepath;
char date_buffer[12]; /* __DATE__: 3 + ' ' + 2 + ' ' + 4 + '\0' */
char preprocessor_buffer[MAX_STRING];
char preprocessor_mergebuffer[512];
char preprocessor_tokenseqbuffer[256];
time_t t;
char fullname[1024];
char output_file_name[1024];
};
/*
* Creates a new instance of dmr_C. Due to the way the parser and compiler works
* at present it is recommended that each dmr_C instance be used to process one set
* of inputs only. Destroy the dmr_C instance after use. This way all resources will
* be released.
*/
extern struct dmr_C *new_dmr_C();
extern void destroy_dmr_C(struct dmr_C *C);
/*
* Appends the provided formatted string to the "pre buffer" that is processed by
* dmrC_sparse_initialize(). The input is tokenized immediately and added to the "pre buffer"
* token stream.
*/
extern void dmrC_add_pre_buffer(struct dmr_C *, const char *fmt, ...) FORMAT_ATTR(2);
/*
* Declares a bunch of gcc built-ins into a "pre buffer" which is processed in
* dmrC_sparse_initialize(). The dmrC_add_pre_buffer() function is used to add input into the
* pre buffer.
*/
extern void dmrC_declare_builtin_functions(struct dmr_C *C);
extern void dmrC_create_builtin_stream(struct dmr_C *C);
extern void dmrC_dump_macro_definitions(struct dmr_C *C);
extern struct symbol_list * dmrC_sparse_initialize(struct dmr_C *C, int argc, char **argv, struct string_list **filelist);
extern struct symbol_list * dmrC_sparse_keep_tokens(struct dmr_C *C, char *filename);
extern struct symbol_list * dmrC_sparse(struct dmr_C *C, char *filename);
extern struct symbol_list * dmrC__sparse(struct dmr_C *C, char *filename);
extern struct symbol_list * dmrC_sparse_buffer(struct dmr_C *C, const char *name, char *buffer, int keep_tokens);
struct token *dmrC_skip_to_token(struct token *, int);
struct token *dmrC_expect_token(struct dmr_C *C, struct token *token, int op, const char *where);
extern void dmrC_die(struct dmr_C *, const char *, ...) FORMAT_ATTR(2) NORETURN_ATTR;
extern void dmrC_info(struct dmr_C *, struct position, const char *, ...)
FORMAT_ATTR(3);
extern void dmrC_warning(struct dmr_C *, struct position, const char *, ...)
FORMAT_ATTR(3);
extern void dmrC_sparse_error(struct dmr_C *, struct position, const char *, ...)
FORMAT_ATTR(3);
extern void dmrC_error_die(struct dmr_C *, struct position, const char *, ...)
FORMAT_ATTR(3) NORETURN_ATTR;
extern void dmrC_expression_error(struct dmr_C *, struct expression *, const char *,
...) FORMAT_ATTR(3);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -1,506 +0,0 @@
#ifndef DMR_C_LINEARIZE_H
#define DMR_C_LINEARIZE_H
/*
* Linearize - walk the parse tree and generate a linear version
* of it and the basic blocks.
*
* Copyright (C) 2004 Linus Torvalds
* Copyright (C) 2004 Christopher Li
*/
#include <lib.h>
#include <allocate.h>
#include <token.h>
#include <parse.h>
#include <symbol.h>
#ifdef __cplusplus
extern "C" {
#endif
struct instruction;
DECLARE_PTR_LIST(basic_block_list, struct basic_block);
DECLARE_PTR_LIST(instruction_list, struct instruction);
DECLARE_PTR_LIST(multijmp_list, struct multijmp);
DECLARE_PTR_LIST(pseudo_list, struct pseudo);
struct pseudo_user {
struct instruction *insn;
pseudo_t *userp;
};
DECLARE_PTR_LIST(pseudo_user_list, struct pseudo_user);
enum pseudo_type {
PSEUDO_VOID,
PSEUDO_REG,
PSEUDO_SYM,
PSEUDO_VAL,
PSEUDO_ARG,
PSEUDO_PHI,
};
/* Have you ever heard of "static single assignment" or SSA form?
struct pseudo represents one of those single-assignment variables.
Each one has a pointer to the symbol it represents (which may
have many pseudos referencing it). Each one also has a pointer
to the instruction that defines it.*/
struct pseudo {
int nr;
enum pseudo_type type;
int size; /* OP_SETVAL only */
struct pseudo_user_list *users; /* pseudo_user list */
struct ident *ident;
union {
struct symbol *sym; // PSEUDO_SYM, VAL & ARG
struct instruction *def; // PSEUDO_REG & PHI
long long value; // PSEUDO_VAL
};
DMRC_BACKEND_TYPE priv;
DMRC_BACKEND_TYPE priv2; /* FIXME - we use this to save ptr to allocated stack in PHI instructions (nanojit) */
};
struct linearizer_state_t {
struct allocator pseudo_allocator;
struct allocator pseudo_user_allocator;
struct allocator asm_constraint_allocator;
struct allocator asm_rules_allocator;
struct allocator multijmp_allocator;
struct allocator basic_block_allocator;
struct allocator entrypoint_allocator;
struct allocator instruction_allocator;
struct pseudo void_pseudo;
struct position current_pos;
int repeat_phase;
unsigned long bb_generation;
int liveness_changed;
struct pseudo_list **live_list;
struct pseudo_list *dead_list;
#define MAX_VAL_HASH 64
struct pseudo_list *prev[MAX_VAL_HASH]; /* from pseudo_t value_pseudo(long long val) in linearize.c */
int nr; /* pseudo number */
int bb_nr; /* basic block number */
char buffer[4096*4];
int n;
char pseudo_buffer[4][64];
#define INSN_HASH_SIZE 256
struct instruction_list *insn_hash_table[INSN_HASH_SIZE];
};
#define VOID_PSEUDO(C) (&C->L->void_pseudo)
struct multijmp {
struct basic_block *target;
long long begin, end;
};
struct asm_constraint {
pseudo_t pseudo;
const char *constraint;
const struct ident *ident;
};
DECLARE_PTR_LIST(asm_constraint_list, struct asm_constraint);
struct asm_rules {
struct asm_constraint_list *inputs; /* list of asm_constraint */
struct asm_constraint_list *outputs; /* list of asm_constraint */
struct asm_constraint_list *clobbers; /* list of asm_constraint */
};
struct instruction {
unsigned opcode:8,
size:24;
struct basic_block *bb;
struct position pos;
struct symbol *type;
union {
pseudo_t target;
pseudo_t cond; /* for branch and switch */
};
union {
struct /* entrypoint */ {
struct pseudo_list *arg_list; /* pseudo list */
};
struct /* branch */ {
struct basic_block *bb_true, *bb_false;
};
struct /* switch */ {
struct multijmp_list *multijmp_list;
};
struct /* phi_node */ {
struct pseudo_list *phi_list; /* pseudo list */
};
struct /* phi source */ {
pseudo_t phi_src;
struct instruction_list *phi_users; /* instruction list */
};
struct /* unops */ {
pseudo_t src;
struct symbol *orig_type; /* casts */
unsigned int offset; /* memops */
};
struct /* binops and sel */ {
pseudo_t src1, src2, src3;
};
struct /* slice */ {
pseudo_t base;
unsigned from, len;
};
struct /* setval */ {
pseudo_t symbol; /* Subtle: same offset as "src" !! */
struct expression *val;
};
struct /* call */ {
pseudo_t func;
struct pseudo_list *arguments; /* instruction list */
struct symbol *fntype;
};
struct /* context */ {
int increment;
int check;
struct expression *context_expr;
};
struct /* asm */ {
const char *string;
struct asm_rules *asm_rules;
};
};
};
enum opcode {
OP_BADOP,
/* Entry */
OP_ENTRY,
/* Terminator */
OP_TERMINATOR,
OP_RET = OP_TERMINATOR,
OP_BR,
OP_CBR,
OP_SWITCH,
OP_INVOKE,
OP_COMPUTEDGOTO,
OP_UNWIND,
OP_TERMINATOR_END = OP_UNWIND,
/* Binary */
OP_BINARY,
OP_ADD = OP_BINARY,
OP_SUB,
OP_MULU, OP_MULS,
OP_DIVU, OP_DIVS,
OP_MODU, OP_MODS,
OP_SHL,
OP_LSR, OP_ASR,
/* Logical */
OP_AND,
OP_OR,
OP_XOR,
OP_AND_BOOL,
OP_OR_BOOL,
OP_BINARY_END = OP_OR_BOOL,
/* Binary comparison */
OP_BINCMP,
OP_SET_EQ = OP_BINCMP,
OP_SET_NE,
OP_SET_LE,
OP_SET_GE,
OP_SET_LT,
OP_SET_GT,
OP_SET_B,
OP_SET_A,
OP_SET_BE,
OP_SET_AE,
OP_BINCMP_END = OP_SET_AE,
/* Uni */
OP_NOT,
OP_NEG,
/* Select - three input values */
OP_SEL,
/* Memory */
OP_MALLOC,
OP_FREE,
OP_ALLOCA,
OP_LOAD,
OP_STORE,
OP_SETVAL,
OP_SYMADDR,
OP_GET_ELEMENT_PTR,
/* Other */
OP_PHI,
OP_PHISOURCE,
OP_CAST,
OP_SCAST,
OP_FPCAST,
OP_PTRCAST,
OP_INLINED_CALL,
OP_CALL,
OP_VANEXT,
OP_VAARG,
OP_SLICE,
OP_SNOP,
OP_LNOP,
OP_NOP,
OP_DEATHNOTE,
OP_ASM,
/* Sparse tagging (line numbers, context, whatever) */
OP_CONTEXT,
OP_RANGE,
/* Needed to translate SSA back to normal form */
OP_COPY,
};
/*
A basic block represents a series of instructions with no branches.
Straight-line code. A branch only occurs at the end of a basic block,
and branches can only target the beginning of a basic block. Typically,
a conditional will consist of a basic block leading up to the branch,
a basic block for the true case, a basic block for the false case,
and a basic block where the two paths merge back together. Either the true
or the false case may not exist. A loop will normally have a basic block
for the loop body, which can branch to the top at the end or continue
to the next basic block. So basic blocks represent a node in the control
flow graph. The edges in that graph lead from one basic block to a
basic block which can follow it in the execution of the program.
*/
struct basic_block {
struct position pos;
unsigned long generation;
int context;
struct entrypoint *ep;
struct basic_block_list *parents; /* basic_block sources */ /* predecessors */
struct basic_block_list *children; /* basic_block destinations */ /* successors */
struct instruction_list *insns; /* Linear list of instructions */
struct pseudo_list *needs, *defines; /* pseudo lists */
/* TODO Following fields are used by the codegen backends.
In Sparse this is a union but we need the nr field
for NanoJIT backend's liveness analysis in addition to
creating unique labels.
*/
//union {
unsigned int nr; /* unique id for label's names */
DMRC_BACKEND_TYPE priv;
//};
};
static inline int dmrC_instruction_list_size(struct instruction_list *list)
{
return ptrlist_size((struct ptr_list *)list);
}
static inline int dmrC_pseudo_list_size(struct pseudo_list *list)
{
return ptrlist_size((struct ptr_list *)list);
}
static inline int dmrC_bb_list_size(struct basic_block_list *list)
{
return ptrlist_size((struct ptr_list *)list);
}
static inline void dmrC_free_instruction_list(struct pseudo_list **head)
{
ptrlist_remove_all((struct ptr_list **)head);
}
static inline struct instruction * dmrC_delete_last_instruction(struct instruction_list **head)
{
return (struct instruction *) ptrlist_undo_last((struct ptr_list **)head);
}
static inline struct basic_block * dmrC_delete_last_basic_block(struct basic_block_list **head)
{
return (struct basic_block *) ptrlist_delete_last((struct ptr_list **)head);
}
static inline struct basic_block *dmrC_first_basic_block(struct basic_block_list *head)
{
return (struct basic_block *) ptrlist_first((struct ptr_list *)head);
}
static inline struct instruction *dmrC_last_instruction(struct instruction_list *head)
{
return (struct instruction *) ptrlist_last((struct ptr_list *)head);
}
static inline struct instruction *dmrC_first_instruction(struct instruction_list *head)
{
return (struct instruction *) ptrlist_first((struct ptr_list *)head);
}
static inline pseudo_t dmrC_first_pseudo(struct pseudo_list *head)
{
return (pseudo_t) ptrlist_first((struct ptr_list *)head);
}
static inline void dmrC_concat_basic_block_list(struct basic_block_list *from, struct basic_block_list **to)
{
ptrlist_concat((struct ptr_list *)from, (struct ptr_list **)to);
}
static inline void dmrC_concat_instruction_list(struct instruction_list *from, struct instruction_list **to)
{
ptrlist_concat((struct ptr_list *)from, (struct ptr_list **)to);
}
static inline int dmrC_is_branch_goto(struct instruction *br)
{
return br && br->opcode==OP_BR && (!br->bb_true || !br->bb_false);
}
static inline void dmrC_add_bb(struct dmr_C *C, struct basic_block_list **list, struct basic_block *bb)
{
ptrlist_add((struct ptr_list **)list, bb, &C->ptrlist_allocator);
}
static inline void dmrC_add_instruction(struct dmr_C *C, struct instruction_list **list, struct instruction *insn)
{
ptrlist_add((struct ptr_list **)list, insn, &C->ptrlist_allocator);
}
static inline void dmrC_add_multijmp(struct dmr_C *C, struct multijmp_list **list, struct multijmp *multijmp)
{
ptrlist_add((struct ptr_list **)list, multijmp, &C->ptrlist_allocator);
}
static inline pseudo_t *dmrC_add_pseudo(struct dmr_C *C, struct pseudo_list **list, pseudo_t pseudo)
{
return (pseudo_t *) ptrlist_add((struct ptr_list **)list, pseudo, &C->ptrlist_allocator);
}
static inline int dmrC_remove_pseudo(struct pseudo_list **list, pseudo_t pseudo)
{
return ptrlist_remove((struct ptr_list **)list, pseudo, 0) != 0;
}
static inline int dmrC_bb_terminated(struct basic_block *bb)
{
struct instruction *insn;
if (!bb)
return 0;
insn = dmrC_last_instruction(bb->insns);
return insn && insn->opcode >= OP_TERMINATOR
&& insn->opcode <= OP_TERMINATOR_END;
}
static inline int dmrC_bb_reachable(struct basic_block *bb)
{
return bb != NULL;
}
static inline void dmrC_add_pseudo_user_ptr(struct dmr_C *C, struct pseudo_user *user, struct pseudo_user_list **list)
{
ptrlist_add((struct ptr_list **)list, user, &C->ptrlist_allocator);
}
static inline int dmrC_has_use_list(pseudo_t p)
{
return (p && p->type != PSEUDO_VOID && p->type != PSEUDO_VAL);
}
static inline struct pseudo_user *dmrC_alloc_pseudo_user(struct dmr_C *C, struct instruction *insn, pseudo_t *pp)
{
struct pseudo_user *user = (struct pseudo_user *) dmrC_allocator_allocate(&C->L->pseudo_user_allocator, 0);
user->userp = pp;
user->insn = insn;
return user;
}
static inline void dmrC_use_pseudo(struct dmr_C *C, struct instruction *insn, pseudo_t p, pseudo_t *pp)
{
*pp = p;
if (dmrC_has_use_list(p))
dmrC_add_pseudo_user_ptr(C, dmrC_alloc_pseudo_user(C, insn, pp), &p->users);
}
static inline void dmrC_remove_bb_from_list(struct basic_block_list **list, struct basic_block *entry, int count)
{
ptrlist_remove((struct ptr_list **)list, entry, count);
}
static inline void dmrC_replace_bb_in_list(struct basic_block_list **list,
struct basic_block *old, struct basic_block *newbb, int count)
{
ptrlist_replace((struct ptr_list **)list, old, newbb, count);
}
struct entrypoint {
struct symbol *name;
struct symbol_list *syms; /* symbol list */
struct pseudo_list *accesses; /* pseudo list */
struct basic_block_list *bbs; /* basic_block list */
struct basic_block *active;
struct instruction *entry;
};
extern void dmrC_insert_select(struct dmr_C *C, struct basic_block *bb, struct instruction *br, struct instruction *phi, pseudo_t if_true, pseudo_t if_false);
extern void dmrC_insert_branch(struct dmr_C *C, struct basic_block *bb, struct instruction *br, struct basic_block *target);
// From Luc: sssa-mini
struct instruction *dmrC_alloc_phisrc(struct dmr_C *C, pseudo_t pseudo, struct symbol *type);
pseudo_t dmrC_insert_phi_node(struct dmr_C *C, struct basic_block *bb, struct symbol *type);
pseudo_t dmrC_alloc_phi(struct dmr_C *C, struct basic_block *source, pseudo_t pseudo, struct symbol *type);
pseudo_t dmrC_alloc_pseudo(struct dmr_C *C, struct instruction *def);
pseudo_t dmrC_value_pseudo(struct dmr_C *C, struct symbol *type, long long val);
unsigned int dmrC_value_size(long long value);
struct entrypoint *dmrC_linearize_symbol(struct dmr_C *C, struct symbol *sym);
int dmrC_unssa(struct dmr_C *C, struct entrypoint *ep);
void dmrC_show_entry(struct dmr_C *C, struct entrypoint *ep);
const char *dmrC_show_pseudo(struct dmr_C *C, pseudo_t pseudo);
void dmrC_show_bb(struct dmr_C *C, struct basic_block *bb);
const char *dmrC_show_instruction(struct dmr_C *C, struct instruction *insn);
void dmrC_convert_instruction_target(struct dmr_C *C, struct instruction *insn, pseudo_t src);
void dmrC_kill_use(struct dmr_C *C, pseudo_t *usep);
void dmrC_kill_insn(struct dmr_C *C, struct instruction *, int force);
void dmrC_kill_unreachable_bbs(struct dmr_C *C, struct entrypoint *ep);
void dmrC_kill_bb(struct dmr_C *C, struct basic_block *);
static inline void dmrC_kill_instruction(struct dmr_C *C, struct instruction *insn)
{
dmrC_kill_insn(C, insn, 0);
}
static inline void dmrC_kill_instruction_force(struct dmr_C *C, struct instruction *insn)
{
dmrC_kill_insn(C, insn, 1);
}
void dmrC_clear_liveness(struct entrypoint *ep);
void dmrC_track_pseudo_liveness(struct dmr_C *C, struct entrypoint *ep);
void dmrC_track_pseudo_death(struct dmr_C *C, struct entrypoint *ep);
void dmrC_track_phi_uses(struct dmr_C *C, struct instruction *insn);
void dmrC_init_linearizer(struct dmr_C *C);
void dmrC_destroy_linearizer(struct dmr_C *C);
#define dmrC_hashval(x) ((unsigned long)(((uintptr_t)(x))))
#define REPEAT_CSE 1
#define REPEAT_SYMBOL_CLEANUP 2
#define REPEAT_CFG_CLEANUP 3
#ifdef __cplusplus
}
#endif
#endif /* LINEARIZE_H */

@ -1,384 +0,0 @@
/*
* Register - track pseudo usage, maybe eventually try to do register
* allocation.
*
* Copyright (C) 2004 Linus Torvalds
*/
#include <assert.h>
#include <port.h>
#include <parse.h>
#include <expression.h>
#include <linearize.h>
//#include <flow.h>
static void phi_defines(struct dmr_C *C, struct instruction * phi_node, pseudo_t target,
void (*defines)(struct dmr_C *C, struct basic_block *, pseudo_t))
{
pseudo_t phi;
FOR_EACH_PTR(phi_node->phi_list, phi) {
struct instruction *def;
if (phi == VOID_PSEUDO(C))
continue;
def = phi->def;
if (!def || !def->bb)
continue;
defines(C, def->bb, target);
} END_FOR_EACH_PTR(phi);
}
static void asm_liveness(struct dmr_C *C, struct basic_block *bb, struct instruction *insn,
void (*def)(struct dmr_C *C, struct basic_block *, pseudo_t),
void (*use)(struct dmr_C *C, struct basic_block *, pseudo_t))
{
struct asm_constraint *entry;
FOR_EACH_PTR(insn->asm_rules->inputs, entry) {
use(C, bb, entry->pseudo);
} END_FOR_EACH_PTR(entry);
FOR_EACH_PTR(insn->asm_rules->outputs, entry) {
def(C, bb, entry->pseudo);
} END_FOR_EACH_PTR(entry);
}
static void track_instruction_usage(struct dmr_C *C, struct basic_block *bb, struct instruction *insn,
void (*def)(struct dmr_C *C, struct basic_block *, pseudo_t),
void (*use)(struct dmr_C *C, struct basic_block *, pseudo_t))
{
#define USES(x) use(C, bb, insn->x)
#define DEFINES(x) def(C, bb, insn->x)
switch (insn->opcode) {
case OP_RET:
USES(src);
break;
case OP_CBR:
case OP_SWITCH:
USES(cond);
break;
case OP_COMPUTEDGOTO:
USES(target);
break;
/* Binary */
case OP_ADD:
case OP_SUB:
case OP_MULU:
case OP_MULS:
case OP_DIVU:
case OP_DIVS:
case OP_MODU:
case OP_MODS:
case OP_SHL:
case OP_LSR:
case OP_ASR:
case OP_AND:
case OP_OR:
case OP_XOR:
case OP_AND_BOOL:
case OP_OR_BOOL:
case OP_SET_EQ:
case OP_SET_NE:
case OP_SET_LE:
case OP_SET_GE:
case OP_SET_LT:
case OP_SET_GT:
case OP_SET_B:
case OP_SET_A:
case OP_SET_BE:
case OP_SET_AE:
USES(src1); USES(src2); DEFINES(target);
break;
/* Uni */
case OP_NOT: case OP_NEG:
USES(src1); DEFINES(target);
break;
case OP_SEL:
USES(src1); USES(src2); USES(src3); DEFINES(target);
break;
/* Memory */
case OP_LOAD:
USES(src); DEFINES(target);
break;
case OP_STORE:
USES(src); USES(target);
break;
case OP_SETVAL:
DEFINES(target);
break;
case OP_SYMADDR:
USES(symbol); DEFINES(target);
break;
/* Other */
case OP_PHI:
/* Phi-nodes are "backwards" nodes. Their def doesn't matter */
phi_defines(C, insn, insn->target, def);
break;
case OP_PHISOURCE:
/*
* We don't care about the phi-source define, they get set
* up and expanded by the OP_PHI
*/
USES(phi_src);
break;
case OP_CAST:
case OP_SCAST:
case OP_FPCAST:
case OP_PTRCAST:
USES(src); DEFINES(target);
break;
case OP_CALL: {
pseudo_t arg;
USES(func);
if (insn->target != VOID_PSEUDO(C))
DEFINES(target);
FOR_EACH_PTR(insn->arguments, arg) {
use(C, bb, arg);
} END_FOR_EACH_PTR(arg);
break;
}
case OP_SLICE:
USES(base); DEFINES(target);
break;
case OP_ASM:
asm_liveness(C, bb, insn, def, use);
break;
case OP_RANGE:
USES(src1); USES(src2); USES(src3);
break;
case OP_BADOP:
case OP_INVOKE:
case OP_UNWIND:
case OP_MALLOC:
case OP_FREE:
case OP_ALLOCA:
case OP_GET_ELEMENT_PTR:
case OP_VANEXT:
case OP_VAARG:
case OP_SNOP:
case OP_LNOP:
case OP_NOP:
case OP_CONTEXT:
break;
}
}
int dmrC_pseudo_in_list(struct pseudo_list *list, pseudo_t pseudo)
{
pseudo_t old;
FOR_EACH_PTR(list,old) {
if (old == pseudo)
return 1;
} END_FOR_EACH_PTR(old);
return 0;
}
static void add_pseudo_exclusive(struct dmr_C *C, struct pseudo_list **list, pseudo_t pseudo)
{
if (!dmrC_pseudo_in_list(*list, pseudo)) {
C->L->liveness_changed = 1;
dmrC_add_pseudo(C, list, pseudo);
}
}
static inline int trackable_pseudo(pseudo_t pseudo)
{
return pseudo && (pseudo->type == PSEUDO_REG || pseudo->type == PSEUDO_ARG);
}
static void insn_uses(struct dmr_C *C, struct basic_block *bb, pseudo_t pseudo)
{
if (trackable_pseudo(pseudo)) {
struct instruction *def = pseudo->def;
if (pseudo->type != PSEUDO_REG || def->bb != bb || def->opcode == OP_PHI)
add_pseudo_exclusive(C, &bb->needs, pseudo);
}
}
static void insn_defines(struct dmr_C *C, struct basic_block *bb, pseudo_t pseudo)
{
assert(trackable_pseudo(pseudo));
dmrC_add_pseudo(C, &bb->defines, pseudo);
}
static void track_bb_liveness(struct dmr_C *C, struct basic_block *bb)
{
pseudo_t needs;
FOR_EACH_PTR(bb->needs, needs) {
struct basic_block *parent;
FOR_EACH_PTR(bb->parents, parent) {
if (!dmrC_pseudo_in_list(parent->defines, needs)) {
add_pseudo_exclusive(C, &parent->needs, needs);
}
} END_FOR_EACH_PTR(parent);
} END_FOR_EACH_PTR(needs);
}
/*
* We need to clear the liveness information if we
* are going to re-run it.
*/
void dmrC_clear_liveness(struct entrypoint *ep)
{
struct basic_block *bb;
FOR_EACH_PTR(ep->bbs, bb) {
ptrlist_remove_all((struct ptr_list **)&bb->needs);
ptrlist_remove_all((struct ptr_list **)&bb->defines);
} END_FOR_EACH_PTR(bb);
}
/*
* Track inter-bb pseudo liveness. The intra-bb case
* is purely local information.
*/
void dmrC_track_pseudo_liveness(struct dmr_C *C, struct entrypoint *ep)
{
struct basic_block *bb;
/* Add all the bb pseudo usage */
FOR_EACH_PTR(ep->bbs, bb) {
struct instruction *insn;
FOR_EACH_PTR(bb->insns, insn) {
if (!insn->bb)
continue;
assert(insn->bb == bb);
track_instruction_usage(C, bb, insn, insn_defines, insn_uses);
} END_FOR_EACH_PTR(insn);
} END_FOR_EACH_PTR(bb);
/* Calculate liveness.. */
do {
C->L->liveness_changed = 0;
FOR_EACH_PTR_REVERSE(ep->bbs, bb) {
track_bb_liveness(C, bb);
} END_FOR_EACH_PTR_REVERSE(bb);
} while (C->L->liveness_changed);
/* Remove the pseudos from the "defines" list that are used internally */
FOR_EACH_PTR(ep->bbs, bb) {
pseudo_t def;
FOR_EACH_PTR(bb->defines, def) {
struct basic_block *child;
FOR_EACH_PTR(bb->children, child) {
if (dmrC_pseudo_in_list(child->needs, def))
goto is_used;
} END_FOR_EACH_PTR(child);
DELETE_CURRENT_PTR(def);
is_used:
;
} END_FOR_EACH_PTR(def);
ptrlist_pack((struct ptr_list **)&bb->defines);
} END_FOR_EACH_PTR(bb);
}
static void merge_pseudo_list(struct dmr_C *C, struct pseudo_list *src, struct pseudo_list **dest)
{
pseudo_t pseudo;
FOR_EACH_PTR(src, pseudo) {
add_pseudo_exclusive(C, dest, pseudo);
} END_FOR_EACH_PTR(pseudo);
}
void dmrC_track_phi_uses(struct dmr_C *C, struct instruction *insn)
{
pseudo_t phi;
FOR_EACH_PTR(insn->phi_list, phi) {
struct instruction *def;
if (phi == VOID_PSEUDO(C) || !phi->def)
continue;
def = phi->def;
assert(def->opcode == OP_PHISOURCE);
dmrC_add_instruction(C, &def->phi_users, insn);
} END_FOR_EACH_PTR(phi);
}
static void track_bb_phi_uses(struct dmr_C *C, struct basic_block *bb)
{
struct instruction *insn;
FOR_EACH_PTR(bb->insns, insn) {
if (insn->bb && insn->opcode == OP_PHI)
dmrC_track_phi_uses(C, insn);
} END_FOR_EACH_PTR(insn);
}
static void death_def(struct dmr_C *C, struct basic_block *bb, pseudo_t pseudo)
{
(void) C;
(void) bb;
(void) pseudo;
}
static void death_use(struct dmr_C *C, struct basic_block *bb, pseudo_t pseudo)
{
(void) C;
(void) bb;
if (trackable_pseudo(pseudo) && !dmrC_pseudo_in_list(*C->L->live_list, pseudo)) {
dmrC_add_pseudo(C, &C->L->dead_list, pseudo);
dmrC_add_pseudo(C, C->L->live_list, pseudo);
}
}
static void track_pseudo_death_bb(struct dmr_C *C, struct basic_block *bb)
{
struct pseudo_list *live = NULL;
struct basic_block *child;
struct instruction *insn;
FOR_EACH_PTR(bb->children, child) {
merge_pseudo_list(C, child->needs, &live);
} END_FOR_EACH_PTR(child);
C->L->live_list = &live;
FOR_EACH_PTR_REVERSE(bb->insns, insn) {
if (!insn->bb)
continue;
C->L->dead_list = NULL;
track_instruction_usage(C, bb, insn, death_def, death_use);
if (C->L->dead_list) {
pseudo_t dead;
FOR_EACH_PTR(C->L->dead_list, dead) {
struct instruction *deathnote = dmrC_allocator_allocate(&C->L->instruction_allocator, 0);
deathnote->bb = bb;
deathnote->opcode = OP_DEATHNOTE;
deathnote->target = dead;
INSERT_CURRENT(deathnote, insn);
} END_FOR_EACH_PTR(dead);
ptrlist_remove_all((struct ptr_list **)&C->L->dead_list);
}
} END_FOR_EACH_PTR_REVERSE(insn);
ptrlist_remove_all((struct ptr_list **)&live);
}
void dmrC_track_pseudo_death(struct dmr_C *C, struct entrypoint *ep)
{
struct basic_block *bb;
FOR_EACH_PTR(ep->bbs, bb) {
track_bb_phi_uses(C, bb);
} END_FOR_EACH_PTR(bb);
FOR_EACH_PTR(ep->bbs, bb) {
track_pseudo_death_bb(C, bb);
} END_FOR_EACH_PTR(bb);
}

@ -1,196 +0,0 @@
/*
* memops - try to combine memory ops.
*
* Copyright (C) 2004 Linus Torvalds
*/
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
#include <port.h>
#include <parse.h>
#include <expression.h>
#include <linearize.h>
#include <flow.h>
static int find_dominating_parents(struct dmr_C *C, pseudo_t pseudo, struct instruction *insn,
struct basic_block *bb, unsigned long generation, struct pseudo_list **dominators,
int local)
{
struct basic_block *parent;
FOR_EACH_PTR(bb->parents, parent) {
struct instruction *one;
struct instruction *br;
pseudo_t phi;
FOR_EACH_PTR_REVERSE(parent->insns, one) {
int dominance;
if (!one->bb)
continue;
if (one == insn)
goto no_dominance;
dominance = dmrC_dominates(C, pseudo, insn, one, local);
if (dominance < 0) {
if (one->opcode == OP_LOAD)
continue;
return 0;
}
if (!dominance)
continue;
goto found_dominator;
} END_FOR_EACH_PTR_REVERSE(one);
no_dominance:
if (parent->generation == generation)
continue;
parent->generation = generation;
if (!find_dominating_parents(C, pseudo, insn, parent, generation, dominators, local))
return 0;
continue;
found_dominator:
br = dmrC_delete_last_instruction(&parent->insns);
phi = dmrC_alloc_phi(C, parent, one->target, one->type);
phi->ident = phi->ident ? phi->ident: one->target->ident;
dmrC_add_instruction(C, &parent->insns, br);
dmrC_use_pseudo(C, insn, phi, dmrC_add_pseudo(C, dominators, phi));
} END_FOR_EACH_PTR(parent);
return 1;
}
static int address_taken(pseudo_t pseudo)
{
struct pseudo_user *pu;
FOR_EACH_PTR(pseudo->users, pu) {
struct instruction *insn = pu->insn;
if (insn->bb && (insn->opcode != OP_LOAD && insn->opcode != OP_STORE))
return 1;
} END_FOR_EACH_PTR(pu);
return 0;
}
static int local_pseudo(pseudo_t pseudo)
{
return pseudo->type == PSEUDO_SYM
&& !(pseudo->sym->ctype.modifiers & (MOD_STATIC | MOD_NONLOCAL))
&& !address_taken(pseudo);
}
static void simplify_loads(struct dmr_C *C, struct basic_block *bb)
{
struct instruction *insn;
FOR_EACH_PTR_REVERSE(bb->insns, insn) {
if (!insn->bb)
continue;
if (insn->opcode == OP_LOAD) {
struct instruction *dom;
pseudo_t pseudo = insn->src;
int local = local_pseudo(pseudo);
struct pseudo_list *dominators;
unsigned long generation;
/* Check for illegal offsets.. */
dmrC_check_access(C, insn);
if (insn->type->ctype.modifiers & MOD_VOLATILE)
continue;
RECURSE_PTR_REVERSE(insn, dom) {
int dominance;
if (!dom->bb)
continue;
dominance = dmrC_dominates(C, pseudo, insn, dom, local);
if (dominance) {
/* possible partial dominance? */
if (dominance < 0) {
if (dom->opcode == OP_LOAD)
continue;
goto next_load;
}
/* Yeehaa! Found one! */
dmrC_convert_load_instruction(C, insn, dom->target);
goto next_load;
}
} END_FOR_EACH_PTR_REVERSE(dom);
/* OK, go find the parents */
generation = ++C->L->bb_generation;
bb->generation = generation;
dominators = NULL;
if (find_dominating_parents(C, pseudo, insn, bb, generation, &dominators, local)) {
/* This happens with initial assignments to structures etc.. */
if (!dominators) {
if (local) {
assert(pseudo->type != PSEUDO_ARG);
dmrC_convert_load_instruction(C, insn, dmrC_value_pseudo(C, insn->type, 0));
}
goto next_load;
}
dmrC_rewrite_load_instruction(C, insn, dominators);
}
}
next_load:
/* Do the next one */;
} END_FOR_EACH_PTR_REVERSE(insn);
}
static void kill_store(struct dmr_C *C, struct instruction *insn)
{
if (insn) {
insn->bb = NULL;
insn->opcode = OP_SNOP;
dmrC_kill_use(C, &insn->target);
}
}
static void kill_dominated_stores(struct dmr_C *C, struct basic_block *bb)
{
struct instruction *insn;
FOR_EACH_PTR_REVERSE(bb->insns, insn) {
if (!insn->bb)
continue;
if (insn->opcode == OP_STORE) {
struct instruction *dom;
pseudo_t pseudo = insn->src;
int local = local_pseudo(pseudo);
RECURSE_PTR_REVERSE(insn, dom) {
int dominance;
if (!dom->bb)
continue;
dominance = dmrC_dominates(C, pseudo, insn, dom, local);
if (dominance) {
/* possible partial dominance? */
if (dominance < 0)
goto next_store;
if (dom->opcode == OP_LOAD)
goto next_store;
/* Yeehaa! Found one! */
kill_store(C, dom);
}
} END_FOR_EACH_PTR_REVERSE(dom);
/* OK, we should check the parents now */
}
next_store:
/* Do the next one */;
} END_FOR_EACH_PTR_REVERSE(insn);
}
void dmrC_simplify_memops(struct dmr_C *C, struct entrypoint *ep)
{
struct basic_block *bb;
FOR_EACH_PTR_REVERSE(ep->bbs, bb) {
simplify_loads(C, bb);
} END_FOR_EACH_PTR_REVERSE(bb);
FOR_EACH_PTR_REVERSE(ep->bbs, bb) {
kill_dominated_stores(C, bb);
} END_FOR_EACH_PTR_REVERSE(bb);
}

File diff suppressed because it is too large Load Diff

@ -1,185 +0,0 @@
#ifndef DMR_C_PARSE_H
#define DMR_C_PARSE_H
/*
* Basic parsing data structures. Statements and symbols.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <lib.h>
#include <symbol.h>
#ifdef __cplusplus
extern "C" {
#endif
enum statement_type {
STMT_NONE,
STMT_DECLARATION,
STMT_EXPRESSION,
STMT_COMPOUND,
STMT_IF,
STMT_RETURN,
STMT_CASE,
STMT_SWITCH,
STMT_ITERATOR,
STMT_LABEL,
STMT_GOTO,
STMT_ASM,
STMT_CONTEXT,
STMT_RANGE,
};
DECLARE_PTR_LIST(statement_list, struct statement);
struct statement {
enum statement_type type;
struct position pos;
union {
struct /* declaration */ {
struct symbol_list *declaration;
};
struct {
struct expression *expression;
struct expression *context;
};
struct /* return_statement */ {
struct expression *ret_value;
struct symbol *ret_target;
};
struct /* if_statement */ {
struct expression *if_conditional;
struct statement *if_true;
struct statement *if_false;
};
struct /* compound_struct */ {
struct statement_list *stmts;
struct symbol *ret;
struct symbol *inline_fn;
struct statement *args;
};
struct /* labeled_struct */ {
struct symbol *label_identifier;
struct statement *label_statement;
};
struct /* case_struct */ {
struct expression *case_expression;
struct expression *case_to;
struct statement *case_statement;
struct symbol *case_label;
};
struct /* switch_struct */ {
struct expression *switch_expression;
struct statement *switch_statement;
struct symbol *switch_break, *switch_case;
};
struct /* iterator_struct */ {
struct symbol *iterator_break;
struct symbol *iterator_continue;
struct symbol_list *iterator_syms;
struct statement *iterator_pre_statement;
struct expression *iterator_pre_condition;
struct statement *iterator_statement;
struct statement *iterator_post_statement;
struct expression *iterator_post_condition;
};
struct /* goto_struct */ {
struct symbol *goto_label;
/* computed gotos have these: */
struct expression *goto_expression;
struct symbol_list *target_list;
};
struct /* asm */ {
struct expression *asm_string;
struct expression_list *asm_outputs;
struct expression_list *asm_inputs;
struct expression_list *asm_clobbers;
struct symbol_list *asm_labels;
};
struct /* range */ {
struct expression *range_expression;
struct expression *range_low;
struct expression *range_high;
};
};
};
struct parse_state_t {
struct symbol_list **function_symbol_list;
struct symbol_list *function_computed_target_list;
struct statement_list *function_computed_goto_list;
struct symbol * int_types[4];
struct symbol * signed_types[5];
struct symbol * unsigned_types[5];
struct symbol * real_types[3];
struct symbol * char_types[3];
struct symbol ** types[7];
};
extern void dmrC_init_parser(struct dmr_C *C, int stream);
void dmrC_destroy_parser(struct dmr_C *C);
extern struct token *dmrC_parse_expression(struct dmr_C *C, struct token *, struct expression **);
extern struct symbol *dmrC_label_symbol(struct dmr_C *C, struct token *token);
extern int dmrC_show_statement(struct dmr_C *C, struct statement *);
extern int dmrC_show_expression(struct dmr_C *C, struct expression *);
typedef void(*validate_decl_t)(struct dmr_C *C, struct symbol *decl);
extern struct token *dmrC_external_declaration(struct dmr_C *C, struct token *token, struct symbol_list **symbol_list, validate_decl_t);
extern struct symbol *dmrC_ctype_integer(struct dmr_C *C, int size, int want_unsigned);
extern void dmrC_copy_statement(struct dmr_C *C, struct statement *src, struct statement *dst);
extern int dmrC_inline_function(struct dmr_C *C, struct expression *expr, struct symbol *sym);
extern void dmrC_uninline(struct dmr_C *C, struct symbol *sym);
static inline void dmrC_add_statement(struct dmr_C *C, struct statement_list **list, struct statement *stmt)
{
ptrlist_add((struct ptr_list **)list, stmt, &C->ptrlist_allocator);
}
static inline void dmrC_add_expression(struct dmr_C *C, struct expression_list **list, struct expression *expr)
{
ptrlist_add((struct ptr_list **)list, expr, &C->ptrlist_allocator);
}
static inline int dmrC_expression_list_size(struct expression_list *list)
{
return ptrlist_size((struct ptr_list *)list);
}
extern int dmrC_test_parse();
#ifdef __cplusplus
}
#endif
#endif /* PARSE_H */

@ -1,59 +0,0 @@
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#ifndef DMR_C_PORT_H
#define DMR_C_PORT_H
#ifndef _WIN32
#include <unistd.h>
#include <alloca.h>
#else
#include <io.h>
#include <malloc.h>
#endif
#if defined(_WIN32) && defined(_MSC_VER)
#include <stdlib.h>
#ifndef __cplusplus
#define inline __inline
#endif
#define __alignof__ __alignof
#define __builtin_bswap16 _byteswap_ushort
#define __builtin_bswap32 _byteswap_ulong
#define __builtin_bswap64 _byteswap_uint64
#endif
#ifdef __GNUC__
#define FORMAT_ATTR(pos) __attribute__((__format__(__printf__, pos, pos + 1)))
#define NORETURN_ATTR __attribute__((__noreturn__))
#define SENTINEL_ATTR __attribute__((__sentinel__))
#else
#define FORMAT_ATTR(pos)
#define NORETURN_ATTR
#define SENTINEL_ATTR
#endif
#ifdef __cplusplus
extern "C" {
#endif
void *dmrC_blob_alloc(size_t size);
void dmrC_blob_free(void *addr, size_t size);
long double dmrC_string_to_ld(const char *nptr, char **endptr);
#include <stdint.h>
#ifdef ASMJIT_STATIC
struct backend_data { uint64_t x[2]; };
#define DMRC_BACKEND_TYPE struct backend_data
#else
#define DMRC_BACKEND_TYPE void *
#endif
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -1,977 +0,0 @@
/*
* ptrlist.c
*
* Pointer ptrlist_t manipulation
*
* (C) Copyright Linus Torvalds 2003-2005
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#define PARANOIA 1
#include <ptrlist.h>
#include <stdio.h>
#include <stdlib.h>
/* The ptr list */
/* For testing we change this */
static int N_ = LIST_NODE_NR;
void ptrlist_split_node(struct ptr_list *head)
{
int old = head->nr_, nr = old / 2;
struct allocator *alloc = head->allocator_;
assert(alloc);
struct ptr_list *newlist =
(struct ptr_list *)dmrC_allocator_allocate(alloc, 0);
struct ptr_list *next = head->next_;
newlist->allocator_ = alloc;
old -= nr;
head->nr_ = old;
newlist->next_ = next;
next->prev_ = newlist;
newlist->prev_ = head;
head->next_ = newlist;
newlist->nr_ = nr;
memcpy(newlist->list_, head->list_ + old, nr * sizeof(void *));
memset(head->list_ + old, 0xf0, nr * sizeof(void *));
}
struct ptr_list_iter ptrlist_forward_iterator(struct ptr_list *head)
{
struct ptr_list_iter iter;
iter.__head = iter.__list = head;
iter.__nr = -1;
return iter;
}
// Reverse iterator has to start from previous node not previous entry
// in the given head
struct ptr_list_iter ptrlist_reverse_iterator(struct ptr_list *head)
{
struct ptr_list_iter iter;
iter.__head = iter.__list = head ? head->prev_ : NULL;
iter.__nr = iter.__head ? iter.__head->nr_ : 0;
return iter;
}
void *ptrlist_iter_next(struct ptr_list_iter *self)
{
if (self->__head == NULL)
return NULL;
self->__nr++;
Lretry:
if (self->__nr < self->__list->nr_) {
void *ptr = self->__list->list_[self->__nr];
if (self->__list->rm_ && !ptr) {
self->__nr++;
goto Lretry;
}
return ptr;
} else if (self->__list->next_ != self->__head) {
self->__list = self->__list->next_;
self->__nr = 0;
goto Lretry;
}
return NULL;
}
void *ptrlist_nth_entry(struct ptr_list *list, unsigned int idx)
{
struct ptr_list *head = list;
if (!head)
return NULL;
do {
unsigned int nr = list->nr_;
if (idx < nr)
return list->list_[idx];
else
idx -= nr;
} while ((list = list->next_) != head);
return NULL;
}
void *ptrlist_iter_prev(struct ptr_list_iter *self)
{
if (self->__head == NULL)
return NULL;
self->__nr--;
Lretry:
if (self->__nr >= 0 && self->__nr < self->__list->nr_) {
void *ptr = self->__list->list_[self->__nr];
if (self->__list->rm_ && !ptr) {
self->__nr--;
goto Lretry;
}
return ptr;
} else if (self->__list->prev_ != self->__head) {
self->__list = self->__list->prev_;
self->__nr = self->__list->nr_ - 1;
goto Lretry;
}
return NULL;
}
void ptrlist_iter_split_current(struct ptr_list_iter *self)
{
if (self->__list->nr_ == N_) {
/* full so split */
ptrlist_split_node(self->__list);
if (self->__nr >= self->__list->nr_) {
self->__nr -= self->__list->nr_;
self->__list = self->__list->next_;
}
}
}
void ptrlist_iter_insert(struct ptr_list_iter *self, void *newitem)
{
assert(self->__nr >= 0);
ptrlist_iter_split_current(self);
void **__this = self->__list->list_ + self->__nr;
void **__last = self->__list->list_ + self->__list->nr_ - 1;
while (__last >= __this) {
__last[1] = __last[0];
__last--;
}
*__this = newitem;
self->__list->nr_++;
}
void ptrlist_iter_remove(struct ptr_list_iter *self)
{
assert(self->__nr >= 0);
void **__this = self->__list->list_ + self->__nr;
void **__last = self->__list->list_ + self->__list->nr_ - 1;
while (__this < __last) {
__this[0] = __this[1];
__this++;
}
*__this = (void *)((uintptr_t)0xf0f0f0f0);
self->__list->nr_--;
self->__nr--;
}
void ptrlist_iter_set(struct ptr_list_iter *self, void *ptr)
{
assert(self->__list && self->__nr >= 0 &&
self->__nr < self->__list->nr_);
self->__list->list_[self->__nr] = ptr;
}
void ptrlist_iter_mark_deleted(struct ptr_list_iter *self)
{
ptrlist_iter_set(self, NULL);
self->__list->rm_++;
}
int ptrlist_size(const struct ptr_list *head) {
int nr = 0;
if (head) {
const struct ptr_list *list = head;
do {
nr += list->nr_ - list->rm_;
} while ((list = list->next_) != head);
}
return nr;
}
void **ptrlist_add(struct ptr_list **listp, void *ptr, struct allocator *alloc)
{
struct ptr_list *list = *listp;
struct ptr_list *last = NULL;
void **ret;
int nr;
if (!list || (nr = (last = list->prev_)->nr_) >= N_) {
struct ptr_list *newlist =
(struct ptr_list *)dmrC_allocator_allocate(alloc, 0);
newlist->allocator_ = alloc;
if (!list) {
newlist->next_ = newlist;
newlist->prev_ = newlist;
*listp = newlist;
} else {
newlist->prev_ = last;
newlist->next_ = list;
list->prev_ = newlist;
last->next_ = newlist;
}
last = newlist;
nr = 0;
}
ret = last->list_ + nr;
*ret = ptr;
nr++;
last->nr_ = nr;
return ret;
}
void *ptrlist_first(struct ptr_list *list)
{
if (!list)
return NULL;
return list->list_[0];
}
void *ptrlist_last(struct ptr_list *list)
{
if (!list)
return NULL;
list = list->prev_;
return list->list_[list->nr_ - 1];
}
/*
* Linearize the entries of a list up to a total of 'max',
* and return the nr of entries linearized.
*
* The array to linearize into (second argument) should really
* be "void *x[]", but we want to let people fill in any kind
* of pointer array, so let's just call it "void **".
*/
int ptrlist_linearize(struct ptr_list *head, void **arr, int max) {
int nr = 0;
if (head && max > 0) {
struct ptr_list *list = head;
do {
int i = list->nr_;
if (i > max)
i = max;
memcpy(arr, list->list_, i * sizeof(void *));
arr += i;
nr += i;
max -= i;
if (!max)
break;
} while ((list = list->next_) != head);
}
return nr;
}
/*
* When we've walked the list and deleted entries,
* we may need to re-pack it so that we don't have
* any empty blocks left (empty blocks upset the
* walking code
*/
void ptrlist_pack(struct ptr_list **listp)
{
struct ptr_list *head = *listp;
if (head) {
struct ptr_list *entry = head;
do {
struct ptr_list *next;
restart:
next = entry->next_;
if (!entry->nr_) {
struct ptr_list *prev;
if (next == entry) {
dmrC_allocator_free(entry->allocator_, entry);
*listp = NULL;
return;
}
prev = entry->prev_;
prev->next_ = next;
next->prev_ = prev;
dmrC_allocator_free(entry->allocator_, entry);
if (entry == head) {
*listp = next;
head = next;
entry = next;
goto restart;
}
}
entry = next;
} while (entry != head);
}
}
void ptrlist_remove_all(struct ptr_list **listp) {
struct ptr_list *tmp, *list = *listp;
if (!list)
return;
list->prev_->next_ = NULL;
while (list) {
tmp = list;
list = list->next_;
dmrC_allocator_free(tmp->allocator_, tmp);
}
*listp = NULL;
}
int ptrlist_remove(struct ptr_list **self, void *entry, int count) {
struct ptr_list_iter iter = ptrlist_forward_iterator(*self);
for (void *ptr = ptrlist_iter_next(&iter); ptr != NULL;
ptr = ptrlist_iter_next(&iter)) {
if (ptr == entry) {
ptrlist_iter_remove(&iter);
if (!--count)
goto out;
}
}
assert(count <= 0);
out:
ptrlist_pack(self);
return count;
}
int ptrlist_replace(struct ptr_list **self, void *old_ptr, void *new_ptr,
int count) {
struct ptr_list_iter iter = ptrlist_forward_iterator(*self);
for (void *ptr = ptrlist_iter_next(&iter); ptr != NULL;
ptr = ptrlist_iter_next(&iter)) {
if (ptr == old_ptr) {
ptrlist_iter_set(&iter, new_ptr);
if (!--count)
goto out;
}
}
assert(count <= 0);
out:
return count;
}
/* This removes the last entry, but doesn't pack the ptr list */
void *ptrlist_undo_last(struct ptr_list **head)
{
struct ptr_list *last, *first = *head;
if (!first)
return NULL;
last = first;
do {
last = last->prev_;
if (last->nr_) {
void *ptr;
int nr = --last->nr_;
ptr = last->list_[nr];
last->list_[nr] = (void *)((intptr_t)0xf1f1f1f1);
return ptr;
}
} while (last != first);
return NULL;
}
void *ptrlist_delete_last(struct ptr_list **head)
{
void *ptr = NULL;
struct ptr_list *last, *first = *head;
if (!first)
return NULL;
last = first->prev_;
if (last->nr_)
ptr = last->list_[--last->nr_];
if (last->nr_ <= 0) {
first->prev_ = last->prev_;
last->prev_->next_ = first;
if (last == first)
*head = NULL;
dmrC_allocator_free(last->allocator_, last);
}
return ptr;
}
void ptrlist_concat(struct ptr_list *a, struct ptr_list **b) {
struct allocator *alloc = NULL;
struct ptr_list_iter iter = ptrlist_forward_iterator(a);
if (a)
alloc = a->allocator_;
else if (*b)
alloc = (*b)->allocator_;
else
return;
for (void *ptr = ptrlist_iter_next(&iter); ptr != NULL;
ptr = ptrlist_iter_next(&iter)) {
ptrlist_add(b, ptr, alloc);
}
}
/*
* sort_list: a stable sort for lists.
*
* Time complexity: O(n*log n)
* [assuming limited zero-element fragments]
*
* Space complexity: O(1).
*
* Stable: yes.
*/
static void array_sort(void **ptr, int nr, void *userdata,
int (*cmp)(void *, const void *, const void *)) {
int i;
for (i = 1; i < nr; i++) {
void *p = ptr[i];
if (cmp(userdata, ptr[i - 1], p) > 0) {
int j = i;
do {
ptr[j] = ptr[j - 1];
if (!--j)
break;
} while (cmp(userdata, ptr[j - 1], p) > 0);
ptr[j] = p;
}
}
}
static void verify_sorted(struct ptr_list *l, int n, void *userdata,
int (*cmp)(void *, const void *, const void *)) {
int i = 0;
const void *a;
struct ptr_list *head = l;
while (l->nr_ == 0) {
l = l->next_;
if (--n == 0)
return;
assert(l != head);
}
a = l->list_[0];
while (n > 0) {
const void *b;
if (++i >= l->nr_) {
i = 0;
l = l->next_;
n--;
assert(l != head || n == 0);
continue;
}
b = l->list_[i];
assert(cmp(userdata, a, b) <= 0);
a = b;
}
}
static void flush_to(struct ptr_list *b, void **buffer, int *nbuf) {
int nr = b->nr_;
assert(*nbuf >= nr);
memcpy(b->list_, buffer, nr * sizeof(void *));
*nbuf = *nbuf - nr;
memmove(buffer, buffer + nr, *nbuf * sizeof(void *));
}
static void dump_to(struct ptr_list *b, void **buffer, int nbuf) {
assert(nbuf <= b->nr_);
memcpy(b->list_, buffer, nbuf * sizeof(void *));
}
// Merge two already-sorted sequences of blocks:
// (b1_1, ..., b1_n) and (b2_1, ..., b2_m)
// Since we may be moving blocks around, we return the new head
// of the merged list.
static struct ptr_list *
merge_block_seqs(struct ptr_list *b1, int n, struct ptr_list *b2,
int m, void *userdata, int (*cmp)(void *, const void *, const void *)) {
int i1 = 0, i2 = 0;
void *buffer[2 * LIST_NODE_NR];
int nbuf = 0;
struct ptr_list *newhead = b1;
// printf ("Merging %d blocks at %p with %d blocks at %p\n", n, b1, m, b2);
// Skip empty blocks in b2.
while (b2->nr_ == 0) {
// BEEN_THERE('F');
b2 = b2->next_;
if (--m == 0) {
// BEEN_THERE('G');
return newhead;
}
}
// Do a quick skip in case entire blocks from b1 are
// already less than smallest element in b2.
while (b1->nr_ == 0 ||
cmp(userdata, PTR_ENTRY(b1, b1->nr_ - 1), PTR_ENTRY(b2,0)) < 0) {
// printf ("Skipping whole block.\n");
// BEEN_THERE('H');
b1 = b1->next_;
if (--n == 0) {
// BEEN_THERE('I');
return newhead;
}
}
while (1) {
void *d1 = PTR_ENTRY(b1,i1);
void *d2 = PTR_ENTRY(b2,i2);
assert(i1 >= 0 && i1 < b1->nr_);
assert(i2 >= 0 && i2 < b2->nr_);
assert(b1 != b2);
assert(n > 0);
assert(m > 0);
if (cmp(userdata, d1, d2) <= 0) {
// BEEN_THERE('J');
buffer[nbuf++] = d1;
// Element from b1 is smaller
if (++i1 >= b1->nr_) {
// BEEN_THERE('L');
flush_to(b1, buffer, &nbuf);
do {
b1 = b1->next_;
if (--n == 0) {
// BEEN_THERE('O');
while (b1 != b2) {
// BEEN_THERE('P');
flush_to(b1, buffer, &nbuf);
b1 = b1->next_;
}
assert(nbuf == i2);
dump_to(b2, buffer, nbuf);
return newhead;
}
} while (b1->nr_ == 0);
i1 = 0;
}
} else {
// BEEN_THERE('K');
// Element from b2 is smaller
buffer[nbuf++] = d2;
if (++i2 >= b2->nr_) {
struct ptr_list *l = b2;
// BEEN_THERE('M');
// OK, we finished with b2. Pull it out
// and plug it in before b1.
b2 = b2->next_;
b2->prev_ = l->prev_;
b2->prev_->next_ = b2;
l->next_ = b1;
l->prev_ = b1->prev_;
l->next_->prev_ = l;
l->prev_->next_ = l;
if (b1 == newhead) {
// BEEN_THERE('N');
newhead = l;
}
flush_to(l, buffer, &nbuf);
b2 = b2->prev_;
do {
b2 = b2->next_;
if (--m == 0) {
// BEEN_THERE('Q');
assert(nbuf == i1);
dump_to(b1, buffer, nbuf);
return newhead;
}
} while (b2->nr_ == 0);
i2 = 0;
}
}
}
}
void ptrlist_sort(struct ptr_list **plist, void *userdata,
int (*cmp)(void *, const void *, const void *)) {
struct ptr_list *head = *plist, *list = head;
int blocks = 1;
assert(N_ == LIST_NODE_NR);
if (!head)
return;
// Sort all the sub-lists
do {
array_sort(list->list_, list->nr_, userdata, cmp);
#ifdef PARANOIA
verify_sorted(list, 1, userdata, cmp);
#endif
list = list->next_;
} while (list != head);
// Merge the damn things together
while (1) {
struct ptr_list *block1 = head;
do {
struct ptr_list *block2 = block1;
struct ptr_list *next, *newhead;
int i;
for (i = 0; i < blocks; i++) {
block2 = block2->next_;
if (block2 == head) {
if (block1 == head) {
// BEEN_THERE('A');
*plist = head;
return;
}
// BEEN_THERE('B');
goto next_pass;
}
}
next = block2;
for (i = 0; i < blocks;) {
next = next->next_;
i++;
if (next == head) {
// BEEN_THERE('C');
break;
}
// BEEN_THERE('D');
}
newhead = merge_block_seqs(block1, blocks, block2, i, userdata, cmp);
#ifdef PARANOIA
verify_sorted(newhead, blocks + i, userdata, cmp);
#endif
if (block1 == head) {
// BEEN_THERE('E');
head = newhead;
}
block1 = next;
} while (block1 != head);
next_pass:
blocks <<= 1;
}
}
static int int_cmp(void *ud, const void *_a, const void *_b) {
(void) ud;
const int *a = (const int *)_a;
const int *b = (const int *)_b;
return *a - *b;
}
#define MIN(_x, _y) ((_x) < (_y) ? (_x) : (_y))
static int test_sort() {
int i, *e;
const int N = 10000;
srand(N);
for (i = 0; i < 1000; i++)
(void)rand();
struct allocator ptrlist_allocator;
dmrC_allocator_init(&ptrlist_allocator, "ptrlist_nodes", sizeof(struct ptr_list),
__alignof__(struct ptr_list), CHUNK);
struct allocator int_allocator;
dmrC_allocator_init(&int_allocator, "ints", sizeof(int), __alignof__(int), CHUNK);
struct ptr_list *int_list = NULL;
for (i = 0; i < N; i++) {
e = (int*)dmrC_allocator_allocate(&int_allocator, 0);
*e = rand();
ptrlist_add(&int_list, e, &ptrlist_allocator);
}
if (ptrlist_size(int_list) != N)
return 1;
ptrlist_sort(&int_list, NULL, int_cmp);
// Sort already sorted stuff.
ptrlist_sort(&int_list, NULL, int_cmp);
int *p = NULL;
struct ptr_list_iter iter = ptrlist_forward_iterator(int_list);
int count = 0;
for (int *k = (int*)ptrlist_iter_next(&iter); k != NULL;
k = (int*)ptrlist_iter_next(&iter)) {
if (p != NULL) {
if (*k < *p)
return 1;
}
p = k;
count++;
}
if (count != N)
return 1;
struct ptr_list *l = int_list, *l2;
l2 = l;
int expected_count = 0;
do {
l2->nr_ = MIN(l2->nr_, rand() % 3);
for (i = 0; i < l2->nr_; i++) {
*((int *)(l2->list_[i])) = rand();
expected_count++;
}
l2 = l2->next_;
} while (l2 != l);
ptrlist_sort(&int_list, NULL, int_cmp);
p = NULL;
iter = ptrlist_forward_iterator(int_list);
count = 0;
for (int *k = (int*)ptrlist_iter_next(&iter); k != NULL;
k = (int*)ptrlist_iter_next(&iter)) {
if (p != NULL) {
if (*k < *p)
return 1;
}
p = k;
count++;
}
if (count != expected_count)
return 1;
ptrlist_remove_all(&int_list);
dmrC_allocator_destroy(&int_allocator);
dmrC_allocator_destroy(&ptrlist_allocator);
return 0;
}
struct mystruct {
int i;
};
struct mytoken {
const char *a;
};
static int test_ptrlist_basics() {
struct allocator ptrlist_allocator;
dmrC_allocator_init(&ptrlist_allocator, "ptrlist_nodes", sizeof(struct ptr_list),
__alignof__(struct ptr_list), CHUNK);
struct allocator token_allocator;
dmrC_allocator_init(&token_allocator, "ptr_list_tokens", sizeof(struct mytoken),
__alignof__(struct mytoken), CHUNK);
struct ptr_list *token_list = NULL;
if (ptrlist_size(token_list) != 0)
return 1;
struct mytoken *tok1 = (struct mytoken *)dmrC_allocator_allocate(&token_allocator, 0);
struct mytoken **tok1p = (struct mytoken **)ptrlist_add(&token_list, tok1, &ptrlist_allocator);
if (ptrlist_size(token_list) != 1)
return 1;
if (tok1 != *tok1p)
return 1;
if (ptrlist_first(token_list) != tok1)
return 1;
if (ptrlist_last(token_list) != tok1)
return 1;
struct mytoken *tok2 = (struct mytoken *)dmrC_allocator_allocate(&token_allocator, 0);
struct mytoken **tok2p = (struct mytoken **)ptrlist_add(&token_list, tok2, &ptrlist_allocator);
if (ptrlist_size(token_list) != 2)
return 1;
struct mytoken *tok3 = (struct mytoken *)dmrC_allocator_allocate(&token_allocator, 0);
ptrlist_add(&token_list, tok3, &ptrlist_allocator);
if (ptrlist_size(token_list) != 3)
return 1;
struct mytoken *tok4 = (struct mytoken *)dmrC_allocator_allocate(&token_allocator, 0);
ptrlist_add(&token_list, tok4, &ptrlist_allocator);
if (ptrlist_size(token_list) != 4)
return 1;
struct mytoken *tok5 = (struct mytoken *)dmrC_allocator_allocate(&token_allocator, 0);
struct mytoken **tok5p = (struct mytoken **)ptrlist_add(&token_list, tok5, &ptrlist_allocator);
if (ptrlist_size(token_list) != 5)
return 1;
if (tok2 != *tok2p)
return 1;
if (tok5 != *tok5p)
return 1;
if (ptrlist_first(token_list) != tok1)
return 1;
if (ptrlist_last(token_list) != tok5)
return 1;
struct mytoken *toks[5];
int lin1 = ptrlist_linearize(token_list, (void **)toks, 5);
if (lin1 != 5)
return 1;
if (toks[0] != tok1)
return 1;
if (toks[1] != tok2)
return 1;
if (toks[2] != tok3)
return 1;
if (toks[3] != tok4)
return 1;
if (toks[4] != tok5)
return 1;
if (ptrlist_size(token_list) != 5)
return 1;
ptrlist_pack(&token_list);
if (ptrlist_size(token_list) != 5)
return 1;
if (ptrlist_first(token_list) != tok1)
return 1;
if (ptrlist_last(token_list) != tok5)
return 1;
const int X = 5 + 1;
const int Y = X - 1;
const int Z = Y - 1;
struct ptr_list_iter iter1 = ptrlist_forward_iterator(token_list);
for (int i = 0; i < X; i++) {
struct mytoken *tk = (struct mytoken *)ptrlist_iter_next(&iter1);
if (tk == NULL) {
if (i == Y)
break;
return 1;
}
if (tk != toks[i])
return 1;
}
struct ptr_list_iter iter2 = ptrlist_reverse_iterator(token_list);
for (int i = 0; i < X; i++) {
struct mytoken *tk = (struct mytoken *)ptrlist_iter_prev(&iter2);
if (tk == NULL) {
if (i == Y)
break;
return 1;
}
if (tk != toks[Z - i])
return 1;
}
struct mytoken *tok0 = (struct mytoken *)dmrC_allocator_allocate(&token_allocator, 0);
struct ptr_list_iter iter3 = ptrlist_forward_iterator(token_list);
if (!ptrlist_iter_next(&iter3))
return 1;
ptrlist_iter_insert(&iter3, tok0);
if (ptrlist_size(token_list) != 6)
return 1;
if (ptrlist_first(token_list) != tok0)
return 1;
if (ptrlist_last(token_list) != tok5)
return 1;
struct allocator mystruct_allocator;
dmrC_allocator_init(&mystruct_allocator, "mystructs", sizeof(struct mystruct),
__alignof__(struct mystruct), CHUNK);
struct ptr_list *mystruct_list = NULL;
struct mystruct *s1 = (struct mystruct *)dmrC_allocator_allocate(&mystruct_allocator, 0);
s1->i = 1;
struct mystruct *s2 = (struct mystruct *)dmrC_allocator_allocate(&mystruct_allocator, 0);
s2->i = 2;
struct mystruct *s3 = (struct mystruct *)dmrC_allocator_allocate(&mystruct_allocator, 0);
s3->i = 3;
struct mystruct *s4 = (struct mystruct *)dmrC_allocator_allocate(&mystruct_allocator, 0);
s4->i = 4;
struct mystruct *s5 = (struct mystruct *)dmrC_allocator_allocate(&mystruct_allocator, 0);
s5->i = 5;
struct mystruct *s6 = (struct mystruct *)dmrC_allocator_allocate(&mystruct_allocator, 0);
s6->i = 6;
ptrlist_add(&mystruct_list, s1, &ptrlist_allocator);
ptrlist_add(&mystruct_list, s2, &ptrlist_allocator);
ptrlist_add(&mystruct_list, s3, &ptrlist_allocator);
ptrlist_add(&mystruct_list, s4, &ptrlist_allocator);
ptrlist_add(&mystruct_list, s5, &ptrlist_allocator);
ptrlist_add(&mystruct_list, s6, &ptrlist_allocator);
struct mystruct *serial1_expected[6] = { s1, s2, s3, s4, s5, s6 };
struct mystruct *serial1_got[6];
ptrlist_linearize(mystruct_list, (void **)serial1_got, 6);
for (int i = 0; i < 6; i++) {
if (serial1_expected[i] != serial1_got[i])
return 1;
}
if (ptrlist_remove(&mystruct_list, s3, 1) != 0)
return 1;
struct ptr_list_iter iter4 = ptrlist_forward_iterator(mystruct_list);
for (struct mystruct *p = (struct mystruct *)ptrlist_iter_next(&iter4); p != NULL;
p = (struct mystruct *)ptrlist_iter_next(&iter4)) {
if (p->i == 4)
ptrlist_iter_remove(&iter4);
}
if (ptrlist_size(mystruct_list) != 4)
return 1;
struct mystruct *serial3_expected[4] = { s1, s2, s5, s6 };
struct mystruct *serial3_got[4];
int reverse_expected[2] = { 2, 1 };
int i = 0;
struct mystruct *p;
FOR_EACH_PTR(mystruct_list, p) {
if (i == 4)
return 1;
serial3_got[i++] = p;
if (i == 3) {
struct mystruct *p2;
int j = 0;
RECURSE_PTR_REVERSE(p, p2) {
if (j >= 2 || reverse_expected[j] != p2->i)
return 1;
j++;
} END_FOR_EACH_PTR_REVERSE(p2);
}
} END_FOR_EACH_PTR(p);
if (i != 4)
return 1;
for (int i = 0; i < 4; i++) {
if (serial3_expected[i] != serial3_got[i])
return 1;
}
i = 0;
PREPARE_PTR_LIST(mystruct_list, p);
while (p != NULL) {
if (i == 4)
return 1;
serial3_got[i++] = p;
NEXT_PTR_LIST(p);
}
FINISH_PTR_LIST(p);
if (i != 4)
return 1;
for (int i = 0; i < 4; i++) {
if (serial3_expected[i] != serial3_got[i])
return 1;
}
i = 0;
FOR_EACH_PTR_REVERSE(mystruct_list, p) {
if (i == 4)
return 1;
serial3_got[i++] = p;
if (i == 2) {
struct mystruct *p3;
int j = 0;
RECURSE_PTR_REVERSE(p, p3) {
if (j >= 2 || reverse_expected[j] != p3->i)
return 1;
j++;
} END_FOR_EACH_PTR_REVERSE(p3);
}
} END_FOR_EACH_PTR_REVERSE(p);
if (i != 4)
return 1;
for (int i = 0; i < 4; i++) {
if (serial3_expected[3-i] != serial3_got[i])
return 1;
}
ptrlist_remove_all(&token_list);
ptrlist_remove_all(&mystruct_list);
dmrC_allocator_destroy(&token_allocator);
dmrC_allocator_destroy(&mystruct_allocator);
dmrC_allocator_destroy(&ptrlist_allocator);
return 0;
}
int test_ptrlist() {
if (test_sort() != 0)
return 1;
/* For testing we set N_ temporarily */
N_ = 2;
int failure_count = test_ptrlist_basics();
N_ = LIST_NODE_NR;
if (failure_count == 0)
printf("ptrlist test okay\n");
return failure_count;
}

@ -1,333 +0,0 @@
#ifndef DMR_C_PTRLIST_H
#define DMR_C_PTRLIST_H
/*
* Generic pointer list manipulation code.
*
* (C) Copyright Linus Torvalds 2003-2005
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <allocate.h>
#include <assert.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* The ptr list data structure is like a train - with cars linked to each other.
* Just as in a train each car has many seats, so in ptr list each "node" has
* several entries. Unlike a train however, the ptr list is arranged as a ring,
* i.e. the the front and back nodes are linked to each other. Hence there is no
* such thing as a 'head' of the list - i.e. any node can be the head!
*/
#ifndef LIST_NODE_NR
#define LIST_NODE_NR (29)
#endif
#define DECLARE_PTR_LIST(listname, type) \
struct listname { \
int nr_ : 8; \
int rm_ : 8; \
struct listname *prev_; \
struct listname *next_; \
struct allocator *allocator_; \
type *list_[LIST_NODE_NR]; \
}
/* Each node in the list */
DECLARE_PTR_LIST(ptr_list, void);
struct ptr_list_iter {
struct ptr_list *__head;
struct ptr_list *__list;
int __nr;
};
/* The ptr list */
extern int ptrlist_size(const struct ptr_list *self);
extern void **ptrlist_add(struct ptr_list **self, void *ptr, struct allocator *alloc);
extern void *ptrlist_nth_entry(struct ptr_list *list, unsigned int idx);
extern void *ptrlist_first(struct ptr_list *list);
extern void *ptrlist_last(struct ptr_list *list);
extern int ptrlist_linearize(struct ptr_list *head, void **arr, int max);
extern void ptrlist_split_node(struct ptr_list *head);
extern void ptrlist_pack(struct ptr_list **self);
extern void ptrlist_remove_all(struct ptr_list **self);
extern int ptrlist_remove(struct ptr_list **self, void *entry, int count);
extern int ptrlist_replace(struct ptr_list **self, void *old_ptr, void *new_ptr,
int count);
extern void *ptrlist_undo_last(struct ptr_list **self);
extern void *ptrlist_delete_last(struct ptr_list **self);
extern void ptrlist_concat(struct ptr_list *a, struct ptr_list **self);
extern void ptrlist_sort(struct ptr_list **self, void *,
int (*cmp)(void *, const void *, const void *));
/* iterator functions */
extern struct ptr_list_iter ptrlist_forward_iterator(struct ptr_list *self);
extern struct ptr_list_iter ptrlist_reverse_iterator(struct ptr_list *self);
extern void *ptrlist_iter_next(struct ptr_list_iter *self);
extern void *ptrlist_iter_prev(struct ptr_list_iter *self);
extern void ptrlist_iter_split_current(struct ptr_list_iter *self);
extern void ptrlist_iter_insert(struct ptr_list_iter *self, void *newitem);
extern void ptrlist_iter_remove(struct ptr_list_iter *self);
extern void ptrlist_iter_set(struct ptr_list_iter *self, void *ptr);
extern void ptrlist_iter_mark_deleted(struct ptr_list_iter *self);
static inline void **ptrlist_iter_this_address(struct ptr_list_iter *self) {
return &self->__list->list_[self->__nr];
}
#define ptr_list_empty(x) ((x) == NULL)
#define PTR_ENTRY_NOTAG(h,i) ((h)->list_[i])
#define PTR_ENTRY(h,i) (void *)(PTR_ENTRY_NOTAG(h,i))
#if 1
#define FOR_EACH_PTR(list, var) \
{ struct ptr_list_iter var##iter__ = ptrlist_forward_iterator((struct ptr_list *)list); \
for (var = ptrlist_iter_next(&var##iter__); var != NULL; var = ptrlist_iter_next(&var##iter__))
#define END_FOR_EACH_PTR(var) }
#define FOR_EACH_PTR_REVERSE(list, var) \
{ struct ptr_list_iter var##iter__ = ptrlist_reverse_iterator((struct ptr_list *)list); \
for (var = ptrlist_iter_prev(&var##iter__); var != NULL; var = ptrlist_iter_prev(&var##iter__))
#define END_FOR_EACH_PTR_REVERSE(var) }
#define RECURSE_PTR_REVERSE(list, var) \
{ struct ptr_list_iter var##iter__ = list##iter__; \
for (var = ptrlist_iter_prev(&var##iter__); var != NULL; var = ptrlist_iter_prev(&var##iter__))
#define PREPARE_PTR_LIST(list, var) \
struct ptr_list_iter var##iter__ = ptrlist_forward_iterator((struct ptr_list *)list); \
var = ptrlist_iter_next(&var##iter__)
#define NEXT_PTR_LIST(var) \
var = ptrlist_iter_next(&var##iter__)
#define FINISH_PTR_LIST(var)
#define THIS_ADDRESS(type, var) \
(type *)ptrlist_iter_this_address(&var##iter__)
#define DELETE_CURRENT_PTR(var) \
ptrlist_iter_remove(&var##iter__)
#define REPLACE_CURRENT_PTR(type, var, replacement) \
ptrlist_iter_set(&var##iter__, replacement)
#define INSERT_CURRENT(newval, var) \
ptrlist_iter_insert(&var##iter__, newval)
#define MARK_CURRENT_DELETED(PTR_TYPE, var) \
ptrlist_iter_mark_deleted(&var##iter__)
#else
#define DO_PREPARE(head, ptr, __head, __list, __nr, PTR_ENTRY) \
do { \
struct ptr_list *__head = (struct ptr_list *) (head); \
struct ptr_list *__list = __head; \
int __nr = 0; \
if (__head) ptr = PTR_ENTRY(__head, 0); \
else ptr = NULL
#define DO_NEXT(ptr, __head, __list, __nr, PTR_ENTRY) \
if (ptr) { \
if (++__nr < __list->nr_) { \
ptr = PTR_ENTRY(__list,__nr); \
} else { \
__list = __list->next_; \
ptr = NULL; \
while (__list->nr_ == 0 && __list != __head) \
__list = __list->next_; \
if (__list != __head) { \
__nr = 0; \
ptr = PTR_ENTRY(__list,0); \
} \
} \
}
#define DO_RESET(ptr, __head, __list, __nr, PTR_ENTRY) \
do { \
__nr = 0; \
__list = __head; \
if (__head) ptr = PTR_ENTRY(__head, 0); \
} while (0)
#define DO_FINISH(ptr, __head, __list, __nr) \
(void)(__nr); /* Sanity-check nesting */ \
} while (0)
#define PREPARE_PTR_LIST(head, ptr) \
DO_PREPARE(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
#define NEXT_PTR_LIST(ptr) \
DO_NEXT(ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
#define RESET_PTR_LIST(ptr) \
DO_RESET(ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
#define FINISH_PTR_LIST(ptr) \
DO_FINISH(ptr, __head##ptr, __list##ptr, __nr##ptr)
#define DO_FOR_EACH(head, ptr, __head, __list, __nr, PTR_ENTRY) do { \
struct ptr_list *__head = (struct ptr_list *) (head); \
struct ptr_list *__list = __head; \
if (__head) { \
do { int __nr; \
for (__nr = 0; __nr < __list->nr_; __nr++) { \
do { \
ptr = PTR_ENTRY(__list,__nr); \
if (__list->rm_ && !ptr) \
continue; \
do {
#define DO_END_FOR_EACH(ptr, __head, __list, __nr) \
} while (0); \
} while (0); \
} \
} while ((__list = __list->next_) != __head); \
} \
} while (0)
#define DO_FOR_EACH_REVERSE(head, ptr, __head, __list, __nr, PTR_ENTRY) do { \
struct ptr_list *__head = (struct ptr_list *) (head); \
struct ptr_list *__list = __head; \
if (__head) { \
do { int __nr; \
__list = __list->prev_; \
__nr = __list->nr_; \
while (--__nr >= 0) { \
do { \
ptr = PTR_ENTRY(__list,__nr); \
if (__list->rm_ && !ptr) \
continue; \
do {
#define DO_END_FOR_EACH_REVERSE(ptr, __head, __list, __nr) \
} while (0); \
} while (0); \
} \
} while (__list != __head); \
} \
} while (0)
#define DO_REVERSE(ptr, __head, __list, __nr, new, __newhead, \
__newlist, __newnr, PTR_ENTRY) do { \
struct ptr_list *__newhead = __head; \
struct ptr_list *__newlist = __list; \
int __newnr = __nr; \
new = ptr; \
goto __inside##new; \
if (1) { \
do { \
__newlist = __newlist->prev_; \
__newnr = __newlist->nr_; \
__inside##new: \
while (--__newnr >= 0) { \
do { \
new = PTR_ENTRY(__newlist,__newnr); \
do {
#define RECURSE_PTR_REVERSE(ptr, new) \
DO_REVERSE(ptr, __head##ptr, __list##ptr, __nr##ptr, \
new, __head##new, __list##new, __nr##new, PTR_ENTRY)
#define DO_THIS_ADDRESS(PTR_TYPE, ptr, __head, __list, __nr) \
((PTR_TYPE*) (__list->list_ + __nr))
#define FOR_EACH_PTR(head, ptr) \
DO_FOR_EACH(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
#define END_FOR_EACH_PTR(ptr) \
DO_END_FOR_EACH(ptr, __head##ptr, __list##ptr, __nr##ptr)
#define FOR_EACH_PTR_NOTAG(head, ptr) \
DO_FOR_EACH(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_NOTAG)
#define END_FOR_EACH_PTR_NOTAG(ptr) END_FOR_EACH_PTR(ptr)
#define FOR_EACH_PTR_REVERSE(head, ptr) \
DO_FOR_EACH_REVERSE(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
#define END_FOR_EACH_PTR_REVERSE(ptr) \
DO_END_FOR_EACH_REVERSE(ptr, __head##ptr, __list##ptr, __nr##ptr)
#define FOR_EACH_PTR_REVERSE_NOTAG(head, ptr) \
DO_FOR_EACH_REVERSE(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_NOTAG)
#define END_FOR_EACH_PTR_REVERSE_NOTAG(ptr) END_FOR_EACH_PTR_REVERSE(ptr)
#define THIS_ADDRESS(PTR_TYPE, ptr) \
DO_THIS_ADDRESS(PTR_TYPE, ptr, __head##ptr, __list##ptr, __nr##ptr)
#define DO_SPLIT(ptr, __head, __list, __nr) do { \
ptrlist_split_node(__list); \
if (__nr >= __list->nr_) { \
__nr -= __list->nr_; \
__list = __list->next_; \
}; \
} while (0)
#define DO_INSERT_CURRENT(new, ptr, __head, __list, __nr) do { \
void **__this, **__last; \
if (__list->nr_ == LIST_NODE_NR) \
DO_SPLIT(ptr, __head, __list, __nr); \
__this = __list->list_ + __nr; \
__last = __list->list_ + __list->nr_ - 1; \
while (__last >= __this) { \
__last[1] = __last[0]; \
__last--; \
} \
*__this = (new); \
__list->nr_++; \
} while (0)
#define INSERT_CURRENT(new, ptr) \
DO_INSERT_CURRENT(new, ptr, __head##ptr, __list##ptr, __nr##ptr)
#define DO_DELETE_CURRENT(ptr, __head, __list, __nr) do { \
void **__this = __list->list_ + __nr; \
void **__last = __list->list_ + __list->nr_ - 1; \
while (__this < __last) { \
__this[0] = __this[1]; \
__this++; \
} \
*__this = (void *)((uintptr_t)0xf0f0f0f0); \
__list->nr_--; __nr--; \
} while (0)
#define DELETE_CURRENT_PTR(ptr) \
DO_DELETE_CURRENT(ptr, __head##ptr, __list##ptr, __nr##ptr)
#define REPLACE_CURRENT_PTR(PTR_TYPE, ptr, new_ptr) \
do { *THIS_ADDRESS(PTR_TYPE, ptr) = (new_ptr); } while (0)
#define DO_MARK_CURRENT_DELETED(PTR_TYPE, ptr, __list) do { \
REPLACE_CURRENT_PTR(PTR_TYPE, ptr, NULL); \
__list->rm++; \
} while (0)
#define MARK_CURRENT_DELETED(PTR_TYPE, ptr) \
DO_MARK_CURRENT_DELETED(PTR_TYPE, ptr, __list##ptr)
#endif
extern int test_ptrlist();
#ifdef __cplusplus
}
#endif
#endif

@ -1,20 +0,0 @@
#include <allocate.h>
#include <ptrlist.h>
#include <token.h>
#include <parse.h>
#include <stdio.h>
int main()
{
int failure_count = 0;
failure_count += dmrC_test_allocator();
failure_count += test_ptrlist();
//failure_count += test_tokenizer();
//failure_count += dmrC_test_parse();
if (failure_count == 0)
printf("Tests OK\n");
else
printf("Tests FAILED\n");
return failure_count == 0 ? 0 : 1;
}

@ -1,162 +0,0 @@
/*
* Symbol scoping.
*
* This is pretty trivial.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003-2004 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <port.h>
#include <lib.h>
#include <allocate.h>
#include <symbol.h>
#include <scope.h>
void dmrC_init_scope(struct dmr_C *C) {
struct scope *scope = (struct scope *)dmrC_allocator_allocate(&C->scope_allocator, 0);
memset(scope, 0, sizeof(*scope));
scope->next = scope;
C->builtin_scope = scope;
C->block_scope = C->builtin_scope; // regular automatic variables etc
C->function_scope = C->builtin_scope; // labels, arguments etc
C->file_scope = C->builtin_scope; // static
C->global_scope = C->builtin_scope; // externally visible
}
void dmrC_destroy_all_scopes(struct dmr_C *C) {
(void) C;
}
void dmrC_bind_scope(struct dmr_C *C, struct symbol *sym, struct scope *scope)
{
sym->scope = scope;
dmrC_add_symbol(C, &scope->symbols, sym);
}
void dmrC_rebind_scope(struct dmr_C *C, struct symbol *sym, struct scope *news)
{
struct scope *old = sym->scope;
if (old == news)
return;
if (old)
ptrlist_remove((struct ptr_list **) &old->symbols, sym, 1);
dmrC_bind_scope(C, sym, news);
}
static void start_scope(struct dmr_C *C, struct scope **s)
{
struct scope *scope = (struct scope *)dmrC_allocator_allocate(&C->scope_allocator, 0);
memset(scope, 0, sizeof(*scope));
scope->next = *s;
*s = scope;
}
void dmrC_start_file_scope(struct dmr_C *C)
{
struct scope *scope = (struct scope *)dmrC_allocator_allocate(&C->scope_allocator, 0);
memset(scope, 0, sizeof(*scope));
scope->next = C->builtin_scope;
C->file_scope = scope;
/* top-level stuff defaults to file scope, "extern" etc will choose global scope */
C->function_scope = scope;
C->block_scope = scope;
}
void dmrC_start_symbol_scope(struct dmr_C *C)
{
start_scope(C, &C->block_scope);
}
void dmrC_start_function_scope(struct dmr_C *C)
{
start_scope(C, &C->function_scope);
start_scope(C, &C->block_scope);
}
static void remove_symbol_scope(struct dmr_C *C, struct symbol *sym)
{
(void) C;
struct symbol **ptr = &sym->ident->symbols;
while (*ptr != sym)
ptr = &(*ptr)->next_id;
*ptr = sym->next_id;
}
static void end_scope(struct dmr_C *C, struct scope **s)
{
struct scope *scope = *s;
struct symbol_list *symbols = scope->symbols;
struct symbol *sym;
*s = scope->next;
scope->symbols = NULL;
FOR_EACH_PTR(symbols, sym) {
remove_symbol_scope(C, sym);
} END_FOR_EACH_PTR(sym);
}
void dmrC_end_file_scope(struct dmr_C *C)
{
end_scope(C, &C->file_scope);
}
void dmrC_new_file_scope(struct dmr_C *C)
{
if (C->file_scope != C->builtin_scope)
dmrC_end_file_scope(C);
dmrC_start_file_scope(C);
}
void dmrC_end_symbol_scope(struct dmr_C *C)
{
end_scope(C, &C->block_scope);
}
void dmrC_end_function_scope(struct dmr_C *C)
{
end_scope(C, &C->block_scope);
end_scope(C, &C->function_scope);
}
int dmrC_is_outer_scope(struct dmr_C *C, struct scope *scope)
{
if (scope == C->block_scope)
return 0;
if (scope == C->builtin_scope && C->block_scope->next == C->builtin_scope)
return 0;
return 1;
}

@ -1,73 +0,0 @@
#ifndef DMR_C_SCOPE_H
#define DMR_C_SCOPE_H
/*
* Symbol scoping is pretty simple.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <lib.h>
#ifdef __cplusplus
extern "C" {
#endif
struct scope {
struct token *token; /* Scope start information */
struct symbol_list *symbols; /* List of symbols in this scope */
struct scope *next;
};
static inline int dmrC_toplevel(struct dmr_C *C, struct scope *scope)
{
return scope == C->file_scope || scope == C->global_scope;
}
extern void dmrC_start_file_scope(struct dmr_C *C);
extern void dmrC_end_file_scope(struct dmr_C *C);
extern void dmrC_new_file_scope(struct dmr_C *C);
extern void dmrC_start_symbol_scope(struct dmr_C *C);
extern void dmrC_end_symbol_scope(struct dmr_C *C);
extern void dmrC_start_function_scope(struct dmr_C *C);
extern void dmrC_end_function_scope(struct dmr_C *C);
extern void dmrC_bind_scope(struct dmr_C *C, struct symbol *, struct scope *);
extern void dmrC_rebind_scope(struct dmr_C *C, struct symbol *sym, struct scope *news);
extern int dmrC_is_outer_scope(struct dmr_C *C, struct scope *);
extern void dmrC_init_scope(struct dmr_C *C);
extern void dmrC_destroy_all_scopes(struct dmr_C *C);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,827 +0,0 @@
/*
* Symbol lookup and handling.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003-2004 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <port.h>
#include <lib.h>
#include <allocate.h>
#include <ptrlist.h>
#include <token.h>
#include <parse.h>
#include <symbol.h>
#include <scope.h>
#include <expression.h>
#include <target.h>
/*
* If the symbol is an inline symbol, add it to the list of symbols to parse
*/
void dmrC_access_symbol(struct global_symbols_t *S, struct symbol *sym)
{
if (sym->ctype.modifiers & MOD_INLINE) {
if (!(sym->ctype.modifiers & MOD_ACCESSED)) {
dmrC_add_symbol(S->C, &S->translation_unit_used_list, sym);
sym->ctype.modifiers |= MOD_ACCESSED;
}
}
}
struct symbol *dmrC_lookup_symbol(struct ident *ident, enum namespace_type ns)
{
struct symbol *sym;
for (sym = ident->symbols; sym; sym = sym->next_id) {
if (sym->ns & ns) {
sym->used = 1;
return sym;
}
}
return NULL;
}
struct context *dmrC_alloc_context(struct global_symbols_t *S)
{
return (struct context *)dmrC_allocator_allocate(&S->context_allocator, 0);
}
struct symbol *dmrC_alloc_symbol(struct global_symbols_t *S, struct position pos, int type)
{
struct symbol *sym = (struct symbol *) dmrC_allocator_allocate(&S->symbol_allocator, 0);
sym->type = type;
sym->pos = pos;
sym->endpos.type = 0;
return sym;
}
struct struct_union_info {
unsigned long max_align;
unsigned long bit_size;
int align_size;
};
/*
* Unions are fairly easy to lay out ;)
*/
static void lay_out_union(struct global_symbols_t *S, struct symbol *sym, struct struct_union_info *info)
{
dmrC_examine_symbol_type(S, sym);
// Unnamed bitfields do not affect alignment.
if (sym->ident || !dmrC_is_bitfield_type(sym)) {
if (sym->ctype.alignment > info->max_align)
info->max_align = sym->ctype.alignment;
}
if (sym->bit_size > (int) info->bit_size)
info->bit_size = sym->bit_size;
sym->offset = 0;
}
static int bitfield_base_size(struct symbol *sym)
{
if (sym->type == SYM_NODE)
sym = sym->ctype.base_type;
if (sym->type == SYM_BITFIELD)
sym = sym->ctype.base_type;
return sym->bit_size;
}
/*
* Structures are a bit more interesting to lay out
*/
static void lay_out_struct(struct global_symbols_t *S, struct symbol *sym, struct struct_union_info *info)
{
unsigned long bit_size, align_bit_mask;
int base_size;
dmrC_examine_symbol_type(S, sym);
// Unnamed bitfields do not affect alignment.
if (sym->ident || !dmrC_is_bitfield_type(sym)) {
if (sym->ctype.alignment > info->max_align)
info->max_align = sym->ctype.alignment;
}
bit_size = info->bit_size;
base_size = sym->bit_size;
/*
* Unsized arrays cause us to not align the resulting
* structure size
*/
if (base_size < 0) {
info->align_size = 0;
base_size = 0;
}
align_bit_mask = dmrC_bytes_to_bits(S->C->target, sym->ctype.alignment) - 1;
/*
* Bitfields have some very special rules..
*/
if (dmrC_is_bitfield_type (sym)) {
unsigned long bit_offset = bit_size & align_bit_mask;
int room = bitfield_base_size(sym) - bit_offset;
// Zero-width fields just fill up the unit.
int width = base_size ? base_size : (bit_offset ? room : 0);
if (width > room) {
bit_size = (bit_size + align_bit_mask) & ~align_bit_mask;
bit_offset = 0;
}
sym->offset = dmrC_bits_to_bytes(S->C->target, bit_size - bit_offset);
sym->bit_offset = bit_offset;
sym->ctype.base_type->bit_offset = bit_offset;
info->bit_size = bit_size + width;
// dmrC_warning (sym->pos, "bitfield: offset=%d:%d size=:%d", sym->offset, sym->bit_offset, width);
return;
}
/*
* Otherwise, just align it right and add it up..
*/
bit_size = (bit_size + align_bit_mask) & ~align_bit_mask;
sym->offset = dmrC_bits_to_bytes(S->C->target, bit_size);
info->bit_size = bit_size + base_size;
// dmrC_warning (sym->pos, "regular: offset=%d", sym->offset);
}
static struct symbol * examine_struct_union_type(struct global_symbols_t *S, struct symbol *sym, int advance)
{
struct struct_union_info info = {
.max_align = 1,
.bit_size = 0,
.align_size = 1
};
unsigned long bit_size, bit_align;
void (*fn)(struct global_symbols_t *S, struct symbol *, struct struct_union_info *);
struct symbol *member;
fn = advance ? lay_out_struct : lay_out_union;
FOR_EACH_PTR(sym->symbol_list, member) {
fn(S, member, &info);
} END_FOR_EACH_PTR(member);
if (!sym->ctype.alignment)
sym->ctype.alignment = info.max_align;
bit_size = info.bit_size;
if (info.align_size) {
bit_align = dmrC_bytes_to_bits(S->C->target, sym->ctype.alignment)-1;
bit_size = (bit_size + bit_align) & ~bit_align;
}
sym->bit_size = bit_size;
return sym;
}
static struct symbol *examine_base_type(struct global_symbols_t *S, struct symbol *sym)
{
struct symbol *base_type;
/* Check the base type */
base_type = dmrC_examine_symbol_type(S, sym->ctype.base_type);
if (!base_type || base_type->type == SYM_PTR)
return base_type;
sym->ctype.as |= base_type->ctype.as;
sym->ctype.modifiers |= base_type->ctype.modifiers & MOD_PTRINHERIT;
dmrC_concat_context_list(base_type->ctype.contexts,
&sym->ctype.contexts);
if (base_type->type == SYM_NODE) {
base_type = base_type->ctype.base_type;
sym->ctype.base_type = base_type;
}
return base_type;
}
static struct symbol * examine_array_type(struct global_symbols_t *S, struct symbol *sym)
{
struct symbol *base_type = examine_base_type(S, sym);
unsigned int bit_size = -1, alignment;
struct expression *array_size = sym->array_size;
if (!base_type)
return sym;
if (array_size) {
bit_size = (unsigned int) dmrC_array_element_offset(S->C->target, base_type->bit_size,
(int) dmrC_get_expression_value_silent(S->C, array_size));
if (array_size->type != EXPR_VALUE) {
if (S->C->Wvla)
dmrC_warning(S->C, array_size->pos, "Variable length array is used.");
bit_size = -1;
}
}
alignment = base_type->ctype.alignment;
if (!sym->ctype.alignment)
sym->ctype.alignment = alignment;
sym->bit_size = bit_size;
return sym;
}
static struct symbol *examine_bitfield_type(struct global_symbols_t *S, struct symbol *sym)
{
struct symbol *base_type = examine_base_type(S, sym);
unsigned long bit_size, alignment, modifiers;
if (!base_type)
return sym;
bit_size = base_type->bit_size;
if (sym->bit_size > (int) bit_size)
dmrC_warning(S->C, sym->pos, "impossible field-width, %d, for this type", sym->bit_size);
alignment = base_type->ctype.alignment;
if (!sym->ctype.alignment)
sym->ctype.alignment = alignment;
modifiers = base_type->ctype.modifiers;
/* Bitfields are unsigned, unless the base type was explicitly signed */
if (!(modifiers & MOD_EXPLICITLY_SIGNED))
modifiers = (modifiers & ~MOD_SIGNED) | MOD_UNSIGNED;
sym->ctype.modifiers |= modifiers & MOD_SIGNEDNESS;
return sym;
}
/*
* "typeof" will have to merge the types together
*/
void dmrC_merge_type(struct symbol *sym, struct symbol *base_type)
{
sym->ctype.as |= base_type->ctype.as;
sym->ctype.modifiers |= (base_type->ctype.modifiers & ~MOD_STORAGE);
dmrC_concat_context_list(base_type->ctype.contexts,
&sym->ctype.contexts);
sym->ctype.base_type = base_type->ctype.base_type;
if (sym->ctype.base_type->type == SYM_NODE)
dmrC_merge_type(sym, sym->ctype.base_type);
}
static int count_array_initializer(struct global_symbols_t *S, struct symbol *t, struct expression *expr)
{
int nr = 0;
int is_char = 0;
/*
* Arrays of character types are special; they can be initialized by
* string literal _or_ by string literal in braces. The latter means
* that with T x[] = {<string literal>} number of elements in x depends
* on T - if it's a character type, we get the length of string literal
* (including NUL), otherwise we have one element here.
*/
if (t->ctype.base_type == &S->int_type && t->ctype.modifiers & MOD_CHAR)
is_char = 1;
switch (expr->type) {
case EXPR_INITIALIZER: {
struct expression *entry;
int count = 0;
int str_len = 0;
FOR_EACH_PTR(expr->expr_list, entry) {
count++;
switch (entry->type) {
case EXPR_INDEX:
if ((int)entry->idx_to >= nr)
nr = entry->idx_to+1;
break;
case EXPR_PREOP: {
struct expression *e = entry;
if (is_char) {
while (e && e->type == EXPR_PREOP && e->op == '(')
e = e->unop;
if (e && e->type == EXPR_STRING) {
entry = e;
case EXPR_STRING:
if (is_char)
str_len = entry->string->length;
}
}
}
default:
nr++;
}
} END_FOR_EACH_PTR(entry);
if (count == 1 && str_len)
nr = str_len;
break;
}
case EXPR_PREOP:
if (is_char) {
struct expression *e = expr;
while (e && e->type == EXPR_PREOP && e->op == '(')
e = e->unop;
if (e && e->type == EXPR_STRING) {
expr = e;
case EXPR_STRING:
if (is_char)
nr = expr->string->length;
}
}
break;
default:
break;
}
return nr;
}
static struct expression *get_symbol_initializer(struct symbol *sym)
{
do {
if (sym->initializer)
return sym->initializer;
} while ((sym = sym->same_symbol) != NULL);
return NULL;
}
static struct symbol * examine_node_type(struct global_symbols_t *S, struct symbol *sym)
{
struct symbol *base_type = examine_base_type(S, sym);
int bit_size;
unsigned long alignment;
/* SYM_NODE - figure out what the type of the node was.. */
bit_size = 0;
alignment = 0;
if (!base_type)
return sym;
bit_size = base_type->bit_size;
alignment = base_type->ctype.alignment;
/* Pick up signedness information into the node */
sym->ctype.modifiers |= (MOD_SIGNEDNESS & base_type->ctype.modifiers);
if (!sym->ctype.alignment)
sym->ctype.alignment = alignment;
/* Unsized array? The size might come from the initializer.. */
if (bit_size < 0 && base_type->type == SYM_ARRAY) {
struct expression *initializer = get_symbol_initializer(sym);
if (initializer) {
struct symbol *node_type = base_type->ctype.base_type;
int count = count_array_initializer(S, node_type, initializer);
if (node_type && node_type->bit_size >= 0)
bit_size = (int) dmrC_array_element_offset(S->C->target, node_type->bit_size, count);
/* Note that the bit_size will be set on parent SYM_NODE rather than here */
//base_type->bit_size = bit_size;
}
}
sym->bit_size = bit_size;
return sym;
}
static struct symbol *examine_enum_type(struct global_symbols_t *S, struct symbol *sym)
{
struct symbol *base_type = examine_base_type(S, sym);
sym->ctype.modifiers |= (base_type->ctype.modifiers & MOD_SIGNEDNESS);
sym->bit_size = S->C->target->bits_in_enum;
if (base_type->bit_size > sym->bit_size)
sym->bit_size = base_type->bit_size;
sym->ctype.alignment = S->C->target->enum_alignment;
if (base_type->ctype.alignment > sym->ctype.alignment)
sym->ctype.alignment = base_type->ctype.alignment;
return sym;
}
static struct symbol *examine_pointer_type(struct global_symbols_t *S, struct symbol *sym)
{
/*
* We need to set the pointer size first, and
* examine the thing we point to only afterwards.
* That's because this pointer type may end up
* being needed for the base type size evaluation.
*/
if (!sym->bit_size)
sym->bit_size = S->C->target->bits_in_pointer;
if (!sym->ctype.alignment)
sym->ctype.alignment = S->C->target->pointer_alignment;
return sym;
}
/*
* Fill in type size and alignment information for
* regular SYM_TYPE things.
*/
struct symbol *dmrC_examine_symbol_type(struct global_symbols_t *S, struct symbol * sym)
{
if (!sym)
return sym;
/* Already done? */
if (sym->examined)
return sym;
sym->examined = 1;
switch (sym->type) {
case SYM_FN:
case SYM_NODE:
return examine_node_type(S, sym);
case SYM_ARRAY:
return examine_array_type(S, sym);
case SYM_STRUCT:
return examine_struct_union_type(S, sym, 1);
case SYM_UNION:
return examine_struct_union_type(S, sym, 0);
case SYM_PTR:
return examine_pointer_type(S, sym);
case SYM_ENUM:
return examine_enum_type(S, sym);
case SYM_BITFIELD:
return examine_bitfield_type(S, sym);
case SYM_BASETYPE:
/* Size and alignment had better already be set up */
return sym;
case SYM_TYPEOF: {
struct symbol *base = dmrC_evaluate_expression(S->C, sym->initializer);
if (base) {
unsigned long mod = 0;
if (dmrC_is_bitfield_type(base))
dmrC_warning(S->C, base->pos, "typeof applied to bitfield type");
if (base->type == SYM_NODE) {
mod |= base->ctype.modifiers & MOD_TYPEOF;
base = base->ctype.base_type;
}
sym->type = SYM_NODE;
sym->ctype.modifiers = mod;
sym->ctype.base_type = base;
return examine_node_type(S, sym);
}
break;
}
case SYM_PREPROCESSOR:
dmrC_sparse_error(S->C, sym->pos, "ctype on preprocessor command? (%s)", dmrC_show_ident(S->C, sym->ident));
return NULL;
case SYM_UNINITIALIZED:
dmrC_sparse_error(S->C, sym->pos, "ctype on uninitialized symbol %p", sym);
return NULL;
case SYM_RESTRICT:
examine_base_type(S, sym);
return sym;
case SYM_FOULED:
examine_base_type(S, sym);
return sym;
default:
dmrC_sparse_error(S->C, sym->pos, "Examining unknown symbol type %d", sym->type);
break;
}
return sym;
}
const char* dmrC_get_type_name(enum type type)
{
const char *type_lookup[] = {
[SYM_UNINITIALIZED] = "uninitialized",
[SYM_PREPROCESSOR] = "preprocessor",
[SYM_BASETYPE] = "basetype",
[SYM_NODE] = "node",
[SYM_PTR] = "pointer",
[SYM_FN] = "function",
[SYM_ARRAY] = "array",
[SYM_STRUCT] = "struct",
[SYM_UNION] = "union",
[SYM_ENUM] = "enum",
[SYM_TYPEDEF] = "typedef",
[SYM_TYPEOF] = "typeof",
[SYM_MEMBER] = "member",
[SYM_BITFIELD] = "bitfield",
[SYM_LABEL] = "label",
[SYM_RESTRICT] = "restrict",
[SYM_FOULED] = "fouled",
[SYM_KEYWORD] = "keyword",
[SYM_BAD] = "bad"};
if (type <= SYM_BAD)
return type_lookup[type];
else
return NULL;
}
struct symbol *dmrC_examine_pointer_target(struct global_symbols_t *S, struct symbol *sym)
{
return examine_base_type(S, sym);
}
void dmrC_create_fouled(struct global_symbols_t *S, struct symbol *type)
{
if (type->bit_size < S->C->target->bits_in_int) {
struct symbol *news = dmrC_alloc_symbol(S, type->pos, type->type);
*news = *type;
news->bit_size = S->C->target->bits_in_int;
news->type = SYM_FOULED;
news->ctype.base_type = type;
dmrC_add_symbol(S->C, &S->restr, type);
dmrC_add_symbol(S->C, &S->fouled, news);
}
}
struct symbol *dmrC_befoul(struct global_symbols_t *S, struct symbol *type)
{
struct symbol *t1, *t2;
while (type->type == SYM_NODE)
type = type->ctype.base_type;
PREPARE_PTR_LIST(S->restr, t1);
PREPARE_PTR_LIST(S->fouled, t2);
for (;;) {
if (t1 == type)
return t2;
if (!t1)
break;
NEXT_PTR_LIST(t1);
NEXT_PTR_LIST(t2);
}
FINISH_PTR_LIST(t2);
FINISH_PTR_LIST(t1);
return NULL;
}
void dmrC_check_declaration(struct global_symbols_t *S, struct symbol *sym)
{
int warned = 0;
struct symbol *next = sym;
while ((next = next->next_id) != NULL) {
if (next->ns != sym->ns)
continue;
if (sym->scope == next->scope) {
sym->same_symbol = next;
return;
}
/* Extern in block level matches a TOPLEVEL non-static symbol */
if (sym->ctype.modifiers & MOD_EXTERN) {
if ((next->ctype.modifiers & (MOD_TOPLEVEL|MOD_STATIC)) == MOD_TOPLEVEL) {
sym->same_symbol = next;
return;
}
}
if (!S->C->Wshadow || warned)
continue;
if (dmrC_get_sym_type(next) == SYM_FN)
continue;
warned = 1;
dmrC_warning(S->C, sym->pos, "symbol '%s' shadows an earlier one", dmrC_show_ident(S->C, sym->ident));
dmrC_info(S->C, next->pos, "originally declared here");
}
}
void dmrC_bind_symbol(struct global_symbols_t *S, struct symbol *sym, struct ident *ident, enum namespace_type ns)
{
struct scope *scope;
if (sym->bound) {
dmrC_sparse_error(S->C, sym->pos, "internal error: symbol type already bound");
return;
}
if (ident->reserved && (ns & (NS_TYPEDEF | NS_STRUCT | NS_LABEL | NS_SYMBOL))) {
dmrC_sparse_error(S->C, sym->pos, "Trying to use reserved word '%s' as identifier", dmrC_show_ident(S->C, ident));
return;
}
sym->ns = ns;
sym->next_id = ident->symbols;
ident->symbols = sym;
if (sym->ident && sym->ident != ident)
dmrC_warning(S->C, sym->pos, "Symbol '%s' already bound", dmrC_show_ident(S->C, sym->ident));
sym->ident = ident;
sym->bound = 1;
scope = S->C->block_scope;
if (ns == NS_SYMBOL && dmrC_toplevel(S->C, scope)) {
unsigned mod = MOD_ADDRESSABLE | MOD_TOPLEVEL;
scope = S->C->global_scope;
if (sym->ctype.modifiers & MOD_STATIC ||
dmrC_is_extern_inline(sym)) {
scope = S->C->file_scope;
mod = MOD_TOPLEVEL;
}
sym->ctype.modifiers |= mod;
}
if (ns == NS_MACRO)
scope = S->C->file_scope;
if (ns == NS_LABEL)
scope = S->C->function_scope;
dmrC_bind_scope(S->C, sym, scope);
}
struct symbol *dmrC_create_symbol(struct global_symbols_t *S, int stream, const char *name, int type, int ns)
{
struct ident *ident = dmrC_built_in_ident(S->C, name);
struct symbol *sym = dmrC_lookup_symbol(ident, ns);
if (sym && sym->type != type)
dmrC_die(S->C, "symbol %s created with different types: %d old %d", name,
type, sym->type);
if (!sym) {
struct token *token = dmrC_built_in_token(S->C, stream, ident);
sym = dmrC_alloc_symbol(S, token->pos, type);
dmrC_bind_symbol(S, sym, token->ident, ns);
}
return sym;
}
void dmrC_init_symbols(struct dmr_C *C)
{
struct global_symbols_t *S = (struct global_symbols_t *) calloc(1, sizeof(struct global_symbols_t));
C->S = S;
S->C = C;
dmrC_allocator_init(&S->context_allocator, "contexts", sizeof(struct context), __alignof__(struct context),
CHUNK);
dmrC_allocator_init(&S->global_ident_allocator, "global_identifiers", sizeof(struct ident),
__alignof__(struct ident), CHUNK);
dmrC_allocator_init(&S->symbol_allocator, "symbols", sizeof(struct symbol),
__alignof__(struct symbol), CHUNK);
int stream = dmrC_init_stream(C, "builtin", -1, C->T->includepath);
#define __INIT_IDENT(n, str, res) (struct ident *) dmrC_allocator_allocate(&S->global_ident_allocator, sizeof(str)); S->n->len = sizeof(str)-1; memcpy(S->n->name, str, sizeof(str)); S->n->reserved = res;
#define __IDENT(n,str,res) \
{S->n = __INIT_IDENT(n, str, res)}
#include "ident-list.h"
#define __IDENT(n,str,res) \
dmrC_hash_ident(C, S->n)
#include "ident-list.h"
dmrC_init_parser(C, stream);
dmrC_init_builtins(C, stream);
}
void dmrC_destroy_symbols(struct dmr_C *C) {
/* tokenizer must be destroyed before this */
assert(C->T == NULL);
dmrC_destroy_parser(C);
assert(C->P == NULL);
struct global_symbols_t *S = C->S;
dmrC_allocator_destroy(&S->context_allocator);
dmrC_allocator_destroy(&S->global_ident_allocator);
dmrC_allocator_destroy(&S->symbol_allocator);
free(S);
C->S = NULL;
}
void dmrC_init_ctype(struct dmr_C *C)
{
assert(C);
struct global_symbols_t *S = C->S;
assert(S);
struct target_t *T = C->target;
assert(T);
const struct ctype_declare *ctype;
#ifdef _MSC_VER
if (sizeof(long long) == sizeof(size_t)) {
T->size_t_ctype = &S->ullong_ctype;
T->ssize_t_ctype = &S->llong_ctype;
}
else {
assert(sizeof(int) == sizeof(size_t));
T->size_t_ctype = &S->uint_ctype;
T->ssize_t_ctype = &S->int_ctype;
}
#else
T->size_t_ctype = &S->uint_ctype;
T->ssize_t_ctype = &S->int_ctype;
#endif
#define MOD_ESIGNED (MOD_SIGNED | MOD_EXPLICITLY_SIGNED)
#define MOD_LL (MOD_LONG | MOD_LONGLONG)
#define MOD_LLL MOD_LONGLONGLONG
const struct ctype_declare {
struct symbol *ptr;
enum type type;
unsigned long modifiers;
int *bit_size;
int *maxalign;
struct symbol *base_type;
} ctype_declaration[] = {
{ &S->bool_ctype, SYM_BASETYPE, MOD_UNSIGNED, &T->bits_in_bool, &T->max_int_alignment, &S->int_type },
{ &S->void_ctype, SYM_BASETYPE, 0, NULL, NULL, NULL },
{ &S->type_ctype, SYM_BASETYPE, MOD_TYPE, NULL, NULL, NULL },
{ &S->incomplete_ctype,SYM_BASETYPE, 0, NULL, NULL, NULL },
{ &S->bad_ctype, SYM_BASETYPE, 0, NULL, NULL, NULL },
{ &S->char_ctype, SYM_BASETYPE, MOD_SIGNED | MOD_CHAR, &T->bits_in_char, &T->max_int_alignment, &S->int_type },
{ &S->schar_ctype, SYM_BASETYPE, MOD_ESIGNED | MOD_CHAR, &T->bits_in_char, &T->max_int_alignment, &S->int_type },
{ &S->uchar_ctype, SYM_BASETYPE, MOD_UNSIGNED | MOD_CHAR, &T->bits_in_char, &T->max_int_alignment, &S->int_type },
{ &S->short_ctype, SYM_BASETYPE, MOD_SIGNED | MOD_SHORT, &T->bits_in_short, &T->max_int_alignment, &S->int_type },
{ &S->sshort_ctype, SYM_BASETYPE, MOD_ESIGNED | MOD_SHORT, &T->bits_in_short, &T->max_int_alignment, &S->int_type },
{ &S->ushort_ctype, SYM_BASETYPE, MOD_UNSIGNED | MOD_SHORT, &T->bits_in_short, &T->max_int_alignment, &S->int_type },
{ &S->int_ctype, SYM_BASETYPE, MOD_SIGNED, &T->bits_in_int, &T->max_int_alignment, &S->int_type },
{ &S->sint_ctype, SYM_BASETYPE, MOD_ESIGNED, &T->bits_in_int, &T->max_int_alignment, &S->int_type },
{ &S->uint_ctype, SYM_BASETYPE, MOD_UNSIGNED, &T->bits_in_int, &T->max_int_alignment, &S->int_type },
{ &S->long_ctype, SYM_BASETYPE, MOD_SIGNED | MOD_LONG, &T->bits_in_long, &T->max_int_alignment, &S->int_type },
{ &S->slong_ctype, SYM_BASETYPE, MOD_ESIGNED | MOD_LONG, &T->bits_in_long, &T->max_int_alignment, &S->int_type },
{ &S->ulong_ctype, SYM_BASETYPE, MOD_UNSIGNED | MOD_LONG, &T->bits_in_long, &T->max_int_alignment, &S->int_type },
{ &S->llong_ctype, SYM_BASETYPE, MOD_SIGNED | MOD_LL, &T->bits_in_longlong, &T->max_int_alignment, &S->int_type },
{ &S->sllong_ctype, SYM_BASETYPE, MOD_ESIGNED | MOD_LL, &T->bits_in_longlong, &T->max_int_alignment, &S->int_type },
{ &S->ullong_ctype, SYM_BASETYPE, MOD_UNSIGNED | MOD_LL, &T->bits_in_longlong, &T->max_int_alignment, &S->int_type },
{ &S->lllong_ctype, SYM_BASETYPE, MOD_SIGNED | MOD_LLL, &T->bits_in_longlonglong, &T->max_int_alignment, &S->int_type },
{ &S->slllong_ctype, SYM_BASETYPE, MOD_ESIGNED | MOD_LLL, &T->bits_in_longlonglong, &T->max_int_alignment, &S->int_type },
{ &S->ulllong_ctype, SYM_BASETYPE, MOD_UNSIGNED | MOD_LLL, &T->bits_in_longlonglong, &T->max_int_alignment, &S->int_type },
{ &S->float_ctype, SYM_BASETYPE, 0, &T->bits_in_float, &T->max_fp_alignment, &S->fp_type },
{ &S->double_ctype, SYM_BASETYPE, MOD_LONG, &T->bits_in_double, &T->max_fp_alignment, &S->fp_type },
{ &S->ldouble_ctype, SYM_BASETYPE, MOD_LONG | MOD_LONGLONG, &T->bits_in_longdouble, &T->max_fp_alignment, &S->fp_type },
{ &S->string_ctype, SYM_PTR, 0, &T->bits_in_pointer, &T->pointer_alignment, &S->char_ctype },
{ &S->ptr_ctype, SYM_PTR, 0, &T->bits_in_pointer, &T->pointer_alignment, &S->void_ctype },
{ &S->null_ctype, SYM_PTR, 0, &T->bits_in_pointer, &T->pointer_alignment, &S->void_ctype },
{ &S->label_ctype, SYM_PTR, 0, &T->bits_in_pointer, &T->pointer_alignment, &S->void_ctype },
{ &S->lazy_ptr_ctype, SYM_PTR, 0, &T->bits_in_pointer, &T->pointer_alignment, &S->void_ctype },
{ NULL, SYM_UNINITIALIZED, 0, NULL, NULL, NULL }
};
#undef MOD_LLL
#undef MOD_LL
#undef MOD_ESIGNED
for (ctype = ctype_declaration ; ctype->ptr; ctype++) {
struct symbol *sym = ctype->ptr;
unsigned long bit_size = ctype->bit_size ? *ctype->bit_size : -1;
unsigned long maxalign = ctype->maxalign ? *ctype->maxalign : 0;
unsigned long alignment = dmrC_bits_to_bytes(T, bit_size);
if (alignment > maxalign)
alignment = maxalign;
sym->type = ctype->type;
sym->bit_size = bit_size;
sym->ctype.alignment = alignment;
sym->ctype.base_type = ctype->base_type;
sym->ctype.modifiers = ctype->modifiers;
}
S->typenames[0].sym = &S->char_ctype; S->typenames[0].name = "char";
S->typenames[1].sym = &S->schar_ctype; S->typenames[1].name = "signed char";
S->typenames[2].sym = &S->uchar_ctype; S->typenames[2].name = "unsigned char";
S->typenames[3].sym = &S->short_ctype; S->typenames[3].name = "short";
S->typenames[4].sym = &S->sshort_ctype; S->typenames[4].name = "signed short";
S->typenames[5].sym = &S->ushort_ctype; S->typenames[5].name = "unsigned short";
S->typenames[6].sym = &S->int_ctype; S->typenames[6].name = "int";
S->typenames[7].sym = &S->sint_ctype; S->typenames[7].name = "signed int";
S->typenames[8].sym = &S->uint_ctype; S->typenames[8].name = "unsigned int";
S->typenames[9].sym = &S->slong_ctype; S->typenames[9].name = "signed long";
S->typenames[10].sym = &S->long_ctype; S->typenames[10].name = "long";
S->typenames[11].sym = &S->ulong_ctype; S->typenames[11].name = "unsigned long";
S->typenames[12].sym = &S->llong_ctype; S->typenames[12].name = "long long";
S->typenames[13].sym = &S->sllong_ctype; S->typenames[13].name = "signed long long";
S->typenames[14].sym = &S->ullong_ctype; S->typenames[14].name = "unsigned long long";
S->typenames[15].sym = &S->lllong_ctype; S->typenames[15].name = "long long long";
S->typenames[16].sym = &S->slllong_ctype; S->typenames[16].name = "signed long long long";
S->typenames[17].sym = &S->ulllong_ctype; S->typenames[17].name = "unsigned long long long";
S->typenames[18].sym = &S->void_ctype; S->typenames[18].name = "void";
S->typenames[19].sym = &S->bool_ctype; S->typenames[19].name = "bool";
S->typenames[20].sym = &S->string_ctype; S->typenames[20].name = "string";
S->typenames[21].sym = &S->float_ctype; S->typenames[21].name = "float";
S->typenames[22].sym = &S->double_ctype; S->typenames[22].name = "double";
S->typenames[23].sym = &S->ldouble_ctype; S->typenames[23].name = "long double";
S->typenames[24].sym = &S->incomplete_ctype; S->typenames[24].name = "incomplete type";
S->typenames[25].sym = &S->int_type; S->typenames[25].name = "abstract int";
S->typenames[26].sym = &S->fp_type; S->typenames[26].name = "abstract fp";
S->typenames[27].sym = &S->label_ctype; S->typenames[27].name = "label type";
S->typenames[28].sym = &S->bad_ctype; S->typenames[28].name = "bad type";
S->typenames[29].sym = NULL, S->typenames[29].name = NULL;
}

@ -1,595 +0,0 @@
#ifndef DMR_C_SYMBOL_H
#define DMR_C_SYMBOL_H
/*
* Basic symbol and namespace definitions.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <target.h>
#include <token.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* An identifier with semantic meaning is a "symbol".
*
* There's a 1:n relationship: each symbol is always
* associated with one identifier, while each identifier
* can have one or more semantic meanings due to C scope
* rules.
*
* The progression is symbol -> token -> identifier. The
* token contains the information on where the symbol was
* declared.
*/
enum namespace_type {
NS_NONE = 0,
NS_MACRO = 1,
NS_TYPEDEF = 2,
NS_STRUCT = 4, // Also used for unions and enums.
NS_LABEL = 8,
NS_SYMBOL = 16,
NS_ITERATOR = 32,
NS_PREPROCESSOR = 64,
NS_UNDEF = 128,
NS_KEYWORD = 256,
};
enum type {
SYM_UNINITIALIZED,
SYM_PREPROCESSOR,
SYM_BASETYPE,
SYM_NODE,
SYM_PTR,
SYM_FN,
SYM_ARRAY,
SYM_STRUCT,
SYM_UNION,
SYM_ENUM,
SYM_TYPEDEF,
SYM_TYPEOF,
SYM_MEMBER,
SYM_BITFIELD,
SYM_LABEL,
SYM_RESTRICT,
SYM_FOULED,
SYM_KEYWORD,
SYM_BAD,
};
enum keyword {
KW_SPECIFIER = 1 << 0,
KW_MODIFIER = 1 << 1,
KW_QUALIFIER = 1 << 2,
KW_ATTRIBUTE = 1 << 3,
KW_STATEMENT = 1 << 4,
KW_ASM = 1 << 5,
KW_MODE = 1 << 6,
KW_SHORT = 1 << 7,
KW_LONG = 1 << 8,
KW_EXACT = 1 << 9,
};
struct context {
struct expression *context_expr;
unsigned int in, out;
};
DECLARE_PTR_LIST(context_list, struct context);
struct phi_map;
struct ctype {
unsigned long modifiers;
unsigned long alignment;
struct context_list *contexts;
unsigned int as;
struct symbol *base_type;
};
struct decl_state {
struct ctype ctype;
struct ident **ident;
struct symbol_op *mode;
unsigned char prefer_abstract, is_inline, storage_class, is_tls;
};
struct symbol;
DECLARE_PTR_LIST(symbol_list, struct symbol);
struct symbol_op {
enum keyword type;
int (*evaluate)(struct dmr_C *, struct expression *);
int (*expand)(struct dmr_C *, struct expression *, int);
int (*args)(struct dmr_C *, struct expression *);
/* keywords */
struct token *(*declarator)(struct dmr_C *, struct token *token,
struct decl_state *ctx);
struct token *(*statement)(struct dmr_C *, struct token *token, struct statement *stmt);
struct token *(*toplevel)(struct dmr_C *, struct token *token, struct symbol_list **list);
struct token *(*attribute)(struct dmr_C *, struct token *token, struct symbol *attr,
struct decl_state *ctx);
struct symbol *(*to_mode)(struct dmr_C *, struct symbol *);
int test, set, cls;
};
#define SYM_ATTR_WEAK 0
#define SYM_ATTR_NORMAL 1
#define SYM_ATTR_STRONG 2
struct symbol {
enum type type : 8;
enum namespace_type ns : 9;
unsigned char used : 1, attr : 2, enum_member : 1, bound : 1;
struct position pos; /* Where this symbol was declared */
struct position endpos; /* Where this symbol ends*/
struct ident *ident; /* What identifier this symbol is associated with */
struct symbol *next_id; /* Next semantic symbol that shares this identifier */
struct symbol *replace; /* What is this symbol shadowed by in copy-expression */
struct scope *scope;
union {
struct symbol *same_symbol;
struct symbol *next_subobject;
};
struct symbol_op *op;
union {
struct /* NS_MACRO */ {
struct token *expansion;
struct token *arglist;
struct scope *used_in;
};
struct /* NS_PREPROCESSOR */ {
int (*handler)(struct dmr_C *, struct stream *, struct token **, struct token *);
int normal;
};
struct /* NS_SYMBOL */ {
unsigned long offset;
int bit_size;
unsigned int bit_offset:8,
arg_count:10,
variadic:1,
initialized:1,
examined:1,
expanding:1,
evaluated:1,
string:1,
designated_init:1,
forced_arg:1,
transparent_union:1;
struct expression *array_size;
struct ctype ctype;
struct symbol_list *arguments;
struct statement *stmt;
struct symbol_list *symbol_list;
struct statement *inline_stmt;
struct symbol_list *inline_symbol_list;
struct expression *initializer;
struct entrypoint *ep;
long long value; /* Initial value */
struct symbol *definition;
};
};
union /* backend */ {
struct basic_block *bb_target; /* label */
void *aux; /* Auxiliary info, e.g. backend information */
struct { /* sparse ctags */
char kind;
unsigned char visited:1;
};
};
pseudo_t pseudo;
DMRC_BACKEND_TYPE priv;
};
/* Modifiers */
#define MOD_AUTO 0x0001
#define MOD_REGISTER 0x0002
#define MOD_STATIC 0x0004
#define MOD_EXTERN 0x0008
#define MOD_CONST 0x0010
#define MOD_VOLATILE 0x0020
#define MOD_SIGNED 0x0040
#define MOD_UNSIGNED 0x0080
#define MOD_CHAR 0x0100
#define MOD_SHORT 0x0200
#define MOD_LONG 0x0400
#define MOD_LONGLONG 0x0800
#define MOD_LONGLONGLONG 0x1000
#define MOD_PURE 0x2000
#define MOD_TYPEDEF 0x10000
#define MOD_TLS 0x20000
#define MOD_INLINE 0x40000
#define MOD_ADDRESSABLE 0x80000
#define MOD_NOCAST 0x100000
#define MOD_NODEREF 0x200000
#define MOD_ACCESSED 0x400000
#define MOD_TOPLEVEL 0x800000 // scoping..
#define MOD_ASSIGNED 0x2000000
#define MOD_TYPE 0x4000000
#define MOD_SAFE 0x8000000 // non-null/non-trapping pointer
#define MOD_USERTYPE 0x10000000
#define MOD_NORETURN 0x20000000
#define MOD_EXPLICITLY_SIGNED 0x40000000
#define MOD_BITWISE 0x80000000
#define MOD_NONLOCAL (MOD_EXTERN | MOD_TOPLEVEL)
#define MOD_STORAGE (MOD_AUTO | MOD_REGISTER | MOD_STATIC | MOD_EXTERN | MOD_INLINE | MOD_TOPLEVEL)
#define MOD_SIGNEDNESS (MOD_SIGNED | MOD_UNSIGNED | MOD_EXPLICITLY_SIGNED)
#define MOD_LONG_ALL (MOD_LONG | MOD_LONGLONG | MOD_LONGLONGLONG)
#define MOD_SPECIFIER (MOD_CHAR | MOD_SHORT | MOD_LONG_ALL | MOD_SIGNEDNESS)
#define MOD_SIZE (MOD_CHAR | MOD_SHORT | MOD_LONG_ALL)
#define MOD_IGNORE (MOD_TOPLEVEL | MOD_STORAGE | MOD_ADDRESSABLE | \
MOD_ASSIGNED | MOD_USERTYPE | MOD_ACCESSED | MOD_EXPLICITLY_SIGNED)
#define MOD_PTRINHERIT (MOD_VOLATILE | MOD_CONST | MOD_NODEREF | MOD_NORETURN | MOD_NOCAST)
/* modifiers preserved by typeof() operator */
#define MOD_TYPEOF (MOD_VOLATILE | MOD_CONST | MOD_NOCAST | MOD_SPECIFIER)
struct ctype_name {
struct symbol *sym;
const char *name;
};
struct global_symbols_t {
struct dmr_C *C;
/* Abstract types */
struct symbol int_type,
fp_type;
/* C types */
struct symbol bool_ctype, void_ctype, type_ctype,
char_ctype, schar_ctype, uchar_ctype,
short_ctype, sshort_ctype, ushort_ctype,
int_ctype, sint_ctype, uint_ctype,
long_ctype, slong_ctype, ulong_ctype,
llong_ctype, sllong_ctype, ullong_ctype,
lllong_ctype, slllong_ctype, ulllong_ctype,
float_ctype, double_ctype, ldouble_ctype,
string_ctype, ptr_ctype, lazy_ptr_ctype,
incomplete_ctype, label_ctype, bad_ctype,
null_ctype;
/* Special internal symbols */
struct symbol zero_int;
/*
* Secondary symbol list for stuff that needs to be output because it
* was used.
*/
struct symbol_list *translation_unit_used_list;
struct allocator context_allocator;
struct allocator symbol_allocator;
struct allocator global_ident_allocator;
struct symbol_list *restr, *fouled;
struct ctype_name typenames[30];
#define __IDENT(n, str, res) struct ident *n
#include "ident-list.h"
#undef __IDENT
};
extern void dmrC_init_symbols(struct dmr_C *C);
extern void dmrC_init_ctype(struct dmr_C *C);
extern void dmrC_init_builtins(struct dmr_C *C, int stream);
extern void dmrC_destroy_symbols(struct dmr_C *C);
extern struct context *dmrC_alloc_context(struct global_symbols_t *S);
extern void dmrC_access_symbol(struct global_symbols_t *S, struct symbol *sym);
extern const char *dmrC_type_difference(struct dmr_C *C, struct ctype *c1, struct ctype *c2,
unsigned long mod1, unsigned long mod2);
extern struct symbol *dmrC_lookup_symbol(struct ident *, enum namespace_type);
extern struct symbol *dmrC_create_symbol(struct global_symbols_t *S, int stream, const char *name, int type, int ns);
extern struct symbol *dmrC_alloc_symbol(struct global_symbols_t *S,
struct position pos, int type);
extern void dmrC_show_type(struct dmr_C *C, struct symbol *);
extern const char *dmrC_modifier_string(struct dmr_C *C, unsigned long mod);
extern void dmrC_show_symbol(struct dmr_C *C, struct symbol *);
extern int dmrC_show_symbol_expr_init(struct dmr_C *C, struct symbol *sym);
extern void dmrC_show_symbol_list(struct dmr_C *C, struct symbol_list *, const char *);
extern void dmrC_bind_symbol(struct global_symbols_t *S, struct symbol *sym,
struct ident *ident, enum namespace_type ns);
extern struct symbol *dmrC_examine_symbol_type(struct global_symbols_t *S,
struct symbol *sym);
extern struct symbol *dmrC_examine_pointer_target(struct global_symbols_t *S,
struct symbol *sym);
extern const char *dmrC_show_typename(struct dmr_C *C, struct symbol *sym);
extern const char *dmrC_builtin_typename(struct dmr_C *C, struct symbol *sym);
extern const char *dmrC_builtin_ctypename(struct dmr_C *C, struct ctype *ctype);
extern const char *dmrC_get_type_name(enum type type);
extern void dmrC_debug_symbol(struct dmr_C *C, struct symbol *);
extern void dmrC_merge_type(struct symbol *sym, struct symbol *base_type);
extern void dmrC_check_declaration(struct global_symbols_t *S, struct symbol *sym);
static inline struct symbol *dmrC_get_base_type(struct global_symbols_t *S,
const struct symbol *sym)
{
return dmrC_examine_symbol_type(S, sym->ctype.base_type);
}
static inline int dmrC_is_int_type(struct global_symbols_t *S,
const struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
if (type->type == SYM_ENUM)
type = type->ctype.base_type;
return type->type == SYM_BITFIELD ||
type->ctype.base_type == &S->int_type;
}
static inline int dmrC_is_enum_type(const struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
return (type->type == SYM_ENUM);
}
static inline int dmrC_is_type_type(struct symbol *type)
{
return (type->ctype.modifiers & MOD_TYPE) != 0;
}
static inline int dmrC_is_ptr_type(struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
return type->type == SYM_PTR || type->type == SYM_ARRAY || type->type == SYM_FN;
}
static inline int dmrC_is_func_type(struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
return type->type == SYM_FN;
}
static inline int dmrC_is_array_type(struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
return type->type == SYM_ARRAY;
}
static inline int dmrC_is_float_type(struct global_symbols_t *S, struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
return type->ctype.base_type == &S->fp_type;
}
static inline int dmrC_is_byte_type(const struct target_t *target,
struct symbol *type)
{
return type->bit_size == target->bits_in_char && type->type != SYM_BITFIELD;
}
static inline int dmrC_is_void_type(struct global_symbols_t *S, struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
return type == &S->void_ctype;
}
static inline int dmrC_is_bool_type(struct global_symbols_t *S, struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
return type == &S->bool_ctype;
}
static inline int dmrC_is_scalar_type(struct global_symbols_t *S, struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
switch (type->type) {
case SYM_ENUM:
case SYM_BITFIELD:
case SYM_PTR:
case SYM_ARRAY: // OK, will be a PTR after conversion
case SYM_FN:
case SYM_RESTRICT: // OK, always integer types
return 1;
default:
break;
}
if (type->ctype.base_type == &S->int_type)
return 1;
if (type->ctype.base_type == &S->fp_type)
return 1;
return 0;
}
// From Luc - sssa-mini
static inline int dmrC_is_simple_type(struct global_symbols_t *S, struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
switch (type->type) {
case SYM_ENUM:
case SYM_BITFIELD:
case SYM_PTR:
case SYM_RESTRICT: // OK, always integer types
return 1;
// Following is causing failures because the IR
// attempts to store values into unions or structs
//case SYM_STRUCT:
//case SYM_UNION:
// return type->bit_size <= S->long_ctype.bit_size;
default:
break;
}
if (type->ctype.base_type == &S->int_type)
return 1;
if (type->ctype.base_type == &S->fp_type)
return 1;
return 0;
}
// From Luc - sssa-mini
static inline int dmrC_is_simple_var(struct global_symbols_t *S, struct symbol *var)
{
if (!dmrC_is_simple_type(S, var))
return 0;
#define MOD_NONREG (MOD_STATIC|MOD_NONLOCAL|MOD_ADDRESSABLE|MOD_VOLATILE)
if (var->ctype.modifiers & MOD_NONREG)
return 0;
return 1;
}
static inline int dmrC_is_function(struct symbol *type)
{
return type && type->type == SYM_FN;
}
static inline int dmrC_is_extern_inline(struct symbol *sym)
{
return (sym->ctype.modifiers & MOD_EXTERN) &&
(sym->ctype.modifiers & MOD_INLINE) &&
dmrC_is_function(sym->ctype.base_type);
}
static inline int dmrC_is_toplevel(struct symbol *sym)
{
return (sym->ctype.modifiers & MOD_TOPLEVEL);
}
static inline int dmrC_is_extern(struct symbol *sym)
{
return (sym->ctype.modifiers & MOD_EXTERN);
}
static inline int dmrC_is_static(struct symbol *sym)
{
return (sym->ctype.modifiers & MOD_STATIC);
}
static int dmrC_is_signed_type(struct symbol *sym)
{
if (sym->type == SYM_NODE)
sym = sym->ctype.base_type;
if (sym->type == SYM_PTR)
return 0;
return !(sym->ctype.modifiers & MOD_UNSIGNED);
}
static inline int dmrC_is_unsigned(struct symbol *sym)
{
return !dmrC_is_signed_type(sym);
}
static inline int dmrC_get_sym_type(struct symbol *type)
{
if (type->type == SYM_NODE)
type = type->ctype.base_type;
if (type->type == SYM_ENUM)
type = type->ctype.base_type;
return type->type;
}
static inline struct symbol *dmrC_get_nth_symbol(struct symbol_list *list, unsigned int idx)
{
return (struct symbol *)ptrlist_nth_entry((struct ptr_list *)list, idx);
}
static inline struct symbol *dmrC_lookup_keyword(struct ident *ident,
enum namespace_type ns)
{
if (!ident->keyword)
return NULL;
return dmrC_lookup_symbol(ident, ns);
}
static inline void dmrC_concat_symbol_list(struct symbol_list *from, struct symbol_list **to)
{
ptrlist_concat((struct ptr_list *)from, (struct ptr_list **) to);
}
static inline void dmrC_add_symbol(struct dmr_C *C, struct symbol_list **list, struct symbol *sym)
{
ptrlist_add((struct ptr_list**)list, sym, &C->ptrlist_allocator);
}
static inline int dmrC_symbol_list_size(struct symbol_list *list)
{
return ptrlist_size((struct ptr_list *)list);
}
static inline void dmrC_concat_context_list(struct context_list *from,
struct context_list **to)
{
ptrlist_concat((struct ptr_list *)from, (struct ptr_list **)to);
}
static inline void dmrC_add_context(struct dmr_C *C, struct context_list **list,
struct context *ctx)
{
ptrlist_add((struct ptr_list **)list, ctx, &C->ptrlist_allocator);
}
static inline int dmrC_is_prototype(struct symbol *sym)
{
if (sym->type == SYM_NODE)
sym = sym->ctype.base_type;
return sym && sym->type == SYM_FN && !sym->stmt;
}
#define dmrC_is_restricted_type(type) (dmrC_get_sym_type(type) == SYM_RESTRICT)
#define dmrC_is_fouled_type(type) (dmrC_get_sym_type(type) == SYM_FOULED)
#define dmrC_is_bitfield_type(type) (dmrC_get_sym_type(type) == SYM_BITFIELD)
extern void dmrC_create_fouled(struct global_symbols_t *S, struct symbol *type);
extern struct symbol *dmrC_befoul(struct global_symbols_t *S, struct symbol *type);
#ifdef __cplusplus
}
#endif
#endif

@ -1,88 +0,0 @@
/*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <stdio.h>
#include <stdlib.h>
#include <port.h>
#include <symbol.h>
#include <target.h>
enum dummy { DUMMY };
void dmrC_init_target(struct dmr_C *C) {
struct target_t *t = (struct target_t *)calloc(1, sizeof(struct target_t));
/*
* For "__attribute__((aligned))"
*/
t->max_alignment = 16;
/*
* Integer data types
*/
t->bits_in_bool = 1;
t->bits_in_char = 8;
t->bits_in_short = 16;
t->bits_in_int = 32;
t->bits_in_long = sizeof(long) * t->bits_in_char;
t->bits_in_longlong = 64;
t->bits_in_longlonglong = 128;
t->bits_in_wchar = 32;
t->max_int_alignment = __alignof__(long long);
/*
* Floating point data types
*/
t->bits_in_float = 32;
t->bits_in_double = 64;
t->bits_in_longdouble = sizeof(long double) * t->bits_in_char;
t->max_fp_alignment = 8;
/*
* Pointer data type
*/
t->bits_in_pointer = sizeof(void *) * t->bits_in_char;
t->pointer_alignment = __alignof__(void *);
/*
* Enum data types
*/
t->bits_in_enum = 32;
t->enum_alignment = 4;
C->target = t;
}
void dmrC_destroy_target(struct dmr_C *C) {
free(C->target);
C->target = NULL;
}

@ -1,85 +0,0 @@
#ifndef DMR_C_TARGET_H
#define DMR_C_TARGET_H
/*
* sparse/target.h
*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#include <lib.h>
struct target_t {
struct symbol *size_t_ctype;
struct symbol *ssize_t_ctype;
/*
* For "__attribute__((aligned))"
*/
int max_alignment;
/*
* Integer data types
*/
int bits_in_bool;
int bits_in_char;
int bits_in_short;
int bits_in_int;
int bits_in_long;
int bits_in_longlong;
int bits_in_longlonglong;
int bits_in_wchar;
int max_int_alignment;
/*
* Floating point data types
*/
int bits_in_float;
int bits_in_double;
int bits_in_longdouble;
int max_fp_alignment;
/*
* Pointer data type
*/
int bits_in_pointer;
int pointer_alignment;
/*
* Enum data types
*/
int bits_in_enum;
int enum_alignment;
};
/*
* Helper functions for converting bits to bytes and vice versa.
*/
static inline int dmrC_bits_to_bytes(const struct target_t *target, int bits) {
return bits >= 0 ? (bits + target->bits_in_char - 1) / target->bits_in_char : -1;
}
static inline int dmrC_bytes_to_bits(const struct target_t *target, int bytes) {
return bytes * target->bits_in_char;
}
static inline unsigned long long dmrC_array_element_offset(const struct target_t *target, unsigned int base_bits, int idx)
{
int fragment = base_bits % target->bits_in_char;
if (fragment)
base_bits += target->bits_in_char - fragment;
return base_bits * idx;
}
extern void dmrC_init_target(struct dmr_C *C);
extern void dmrC_destroy_target(struct dmr_C *C);
#endif

@ -1,294 +0,0 @@
/*
* Basic tokenization structures. NOTE! Those tokens had better
* be pretty small, since we're going to keep them all in memory
* indefinitely.
*
* Copyright (C) 2003 Transmeta Corp.
* 2003 Linus Torvalds
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This version is part of the dmr_c project.
* Copyright (C) 2017 Dibyendu Majumdar
*/
#ifndef DMR_C_TOKENIZER_H
#define DMR_C_TOKENIZER_H
#include <lib.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* This describes the pure lexical elements (tokens), with
* no semantic meaning. In other words, an identifier doesn't
* have a type or meaning, it is only a specific string in
* the input stream.
*
* Semantic meaning is handled elsewhere.
*/
enum constantfile {
CONSTANT_FILE_MAYBE, // To be determined, not inside any #ifs in this file
CONSTANT_FILE_IFNDEF, // To be determined, currently inside #ifndef
CONSTANT_FILE_NOPE, // No
CONSTANT_FILE_YES // Yes
};
struct stream {
int fd;
const char *name;
const char *path; // input-file path - see set_stream_include_path()
const char **next_path;
/* Use these to check for "already parsed" */
enum constantfile constant;
int dirty, next_stream, once;
struct ident *protect;
struct token *ifndef;
struct token *top_if;
};
struct ident {
struct ident *next; /* Hash chain of identifiers */
struct symbol *symbols; /* Pointer to semantic meaning list */
unsigned char len; /* Length of identifier name */
unsigned char tainted:1,
reserved:1,
keyword:1;
char name[]; /* Actual identifier */
};
DECLARE_PTR_LIST(ident_list, struct ident);
enum e_token_type {
TOKEN_EOF,
TOKEN_ERROR,
TOKEN_IDENT,
TOKEN_ZERO_IDENT,
TOKEN_NUMBER,
TOKEN_CHAR,
TOKEN_CHAR_EMBEDDED_0,
TOKEN_CHAR_EMBEDDED_1,
TOKEN_CHAR_EMBEDDED_2,
TOKEN_CHAR_EMBEDDED_3,
TOKEN_WIDE_CHAR,
TOKEN_WIDE_CHAR_EMBEDDED_0,
TOKEN_WIDE_CHAR_EMBEDDED_1,
TOKEN_WIDE_CHAR_EMBEDDED_2,
TOKEN_WIDE_CHAR_EMBEDDED_3,
TOKEN_STRING,
TOKEN_WIDE_STRING,
TOKEN_SPECIAL,
TOKEN_STREAMBEGIN,
TOKEN_STREAMEND,
TOKEN_MACRO_ARGUMENT,
TOKEN_STR_ARGUMENT,
TOKEN_QUOTED_ARGUMENT,
TOKEN_CONCAT,
TOKEN_GNU_KLUDGE,
TOKEN_UNTAINT,
TOKEN_ARG_COUNT,
TOKEN_IF,
TOKEN_SKIP_GROUPS,
TOKEN_ELSE,
};
/* Combination tokens */
#define COMBINATION_STRINGS { \
"+=", "++", \
"-=", "--", "->", \
"*=", \
"/=", \
"%=", \
"<=", ">=", \
"==", "!=", \
"&&", "&=", \
"||", "|=", \
"^=", "##", \
"<<", ">>", "..", \
"<<=", ">>=", "...", \
"", \
"<", ">", "<=", ">=" \
}
extern unsigned char dmrC_combinations_[][4];
enum special_token {
SPECIAL_BASE = 256,
SPECIAL_ADD_ASSIGN = SPECIAL_BASE,
SPECIAL_INCREMENT,
SPECIAL_SUB_ASSIGN,
SPECIAL_DECREMENT,
SPECIAL_DEREFERENCE,
SPECIAL_MUL_ASSIGN,
SPECIAL_DIV_ASSIGN,
SPECIAL_MOD_ASSIGN,
SPECIAL_LTE,
SPECIAL_GTE,
SPECIAL_EQUAL,
SPECIAL_NOTEQUAL,
SPECIAL_LOGICAL_AND,
SPECIAL_AND_ASSIGN,
SPECIAL_LOGICAL_OR,
SPECIAL_OR_ASSIGN,
SPECIAL_XOR_ASSIGN,
SPECIAL_HASHHASH,
SPECIAL_LEFTSHIFT,
SPECIAL_RIGHTSHIFT,
SPECIAL_DOTDOT,
SPECIAL_SHL_ASSIGN,
SPECIAL_SHR_ASSIGN,
SPECIAL_ELLIPSIS,
SPECIAL_ARG_SEPARATOR,
SPECIAL_UNSIGNED_LT,
SPECIAL_UNSIGNED_GT,
SPECIAL_UNSIGNED_LTE,
SPECIAL_UNSIGNED_GTE,
};
struct string {
unsigned int length:31;
unsigned int immutable:1;
char data[];
};
/* will fit into 32 bits */
struct argcount {
unsigned normal:10;
unsigned quoted:10;
unsigned str:10;
unsigned vararg:1;
};
/*
* This is a very common data structure, it should be kept
* as small as humanly possible. Big (rare) types go as
* pointers.
*/
struct token {
struct position pos;
struct token *next;
union {
const char *number;
struct ident *ident;
unsigned int special;
struct string *string;
int argnum;
struct argcount count;
char embedded[4];
};
};
static inline struct token *dmrC_containing_token(struct token **p)
{
void *addr = (char *)p - ((char *)&((struct token *)0)->next - (char *)0);
return (struct token *)addr;
}
struct tokenizer_state_t {
unsigned int tabstop;
int input_stream_nr;
struct stream *input_streams;
int input_streams_allocated;
char special[256]; // identifies CR LF TAB
long cclass[257]; // character class
unsigned char hash_results[32][2]; // hashes compound operators
int code[32]; // token values for compound operators
char special_buffer[4];
char ident_buffer[256];
char string_buffer[4 * MAX_STRING + 3];
char char_buffer[MAX_STRING + 4];
char quote_buffer[2 * MAX_STRING + 6];
char token_buffer[256];
char quoted_token_buffer[256];
char number_buffer[4095];
char string_buffer2[MAX_STRING];
struct ident **hash_table;
int ident_hit, ident_miss, idents;
const char **includepath;
};
#define dmrC_token_type(x) ((x)->pos.type)
/*
* Last token in the stream - points to itself.
* This allows us to not test for NULL pointers
* when following the token->next chain..
*/
extern struct token dmrC_eof_token_entry_;
#define dmrC_eof_token(x) ((x) == &dmrC_eof_token_entry_)
extern void dmrC_init_tokenizer(struct dmr_C *C);
extern void dmrC_destroy_tokenizer(struct dmr_C *C);
extern int dmrC_init_stream(struct dmr_C *C, const char *name, int fd,
const char **next_path);
extern const char *dmrC_stream_name(struct dmr_C *C, int stream);
extern struct ident *dmrC_hash_ident(struct dmr_C *C, struct ident *ident);
extern struct ident *dmrC_built_in_ident(struct dmr_C *C, const char *name);
extern struct token *dmrC_built_in_token(struct dmr_C *C, int stream, struct ident *ident);
extern const char *dmrC_show_special(struct dmr_C *C, int val);
extern const char *dmrC_show_ident(struct dmr_C *C, const struct ident *ident);
extern const char *dmrC_show_string(struct dmr_C *C, const struct string *string);
extern const char *dmrC_show_token(struct dmr_C *C, const struct token *token);
extern const char *dmrC_quote_token(struct dmr_C *C, const struct token *token);
extern int *dmrC_hash_stream(const char *name);
extern struct token *dmrC_tokenize(struct dmr_C *C, const char *name, int fd,
struct token *endtoken, const char **next_path);
/* This function assumes that stream 0 is being used - so it is not suitable
for general use */
extern struct token *dmrC_tokenize_buffer(struct dmr_C *C, unsigned char *buffer,
unsigned long size,
struct token **endtoken);
/* This version allows a named stream to be created */
extern struct token *dmrC_tokenize_buffer_stream(struct dmr_C *C,
const char *name,
unsigned char *buffer,
unsigned long size,
struct token **endtoken);
extern void dmrC_show_identifier_stats(struct dmr_C *C);
extern struct token *dmrC_preprocess(struct dmr_C *C, struct token *);
extern void dmrC_init_preprocessor_state(struct dmr_C *C);
static inline int dmrC_match_op(struct token *token, unsigned int op)
{
return token->pos.type == TOKEN_SPECIAL && token->special == op;
}
static inline int dmrC_match_ident(struct token *token, struct ident *id)
{
return token->pos.type == TOKEN_IDENT && token->ident == id;
}
static inline void dmrC_add_ident(struct dmr_C *C, struct ident_list **list, struct ident *ident)
{
ptrlist_add((struct ptr_list **)list, ident, &C->ptrlist_allocator);
}
extern int dmrC_test_tokenizer();
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -1,148 +0,0 @@
/*
* UnSSA - translate the SSA back to normal form.
*
* For now it's done by replacing to set of copies:
* 1) For each phi-node, replace all their phisrc by copies to a common
* temporary.
* 2) Replace all the phi-nodes by copies of the temporaries to the phi-node target.
* This is node to preserve the semantic of the phi-node (they should all "execute"
* simultaneously on entry in the basic block in which they belong).
*
* This is similar to the "Sreedhar method I" except that the copies to the
* temporaries are not placed at the end of the predecessor basic blocks, but
* at the place where the phi-node operands are defined.
* This is particulary easy since these copies are essentialy already present
* as the corresponding OP_PHISOURCE.
*
* While very simple this method create a lot more copies that really necessary.
* We eliminate some of these copies but most probably most of them are still
* useless.
* Ideally, "Sreedhar method III" should be used:
* "Translating Out of Static Single Assignment Form", V. C. Sreedhar, R. D.-C. Ju,
* D. M. Gillies and V. Santhanam. SAS'99, Vol. 1694 of Lecture Notes in Computer
* Science, Springer-Verlag, pp. 194-210, 1999.
* But for this we need precise liveness, on each %phi and not only on OP_PHI's
* target pseudos.
*
* Copyright (C) 2005 Luc Van Oostenryck
*/
#include <assert.h>
#include <port.h>
#include <lib.h>
#include <linearize.h>
#include <allocate.h>
#include <flow.h>
static inline int nbr_pseudo_users(pseudo_t p)
{
return ptrlist_size((struct ptr_list *)p->users);
}
static int simplify_phi_node(struct dmr_C *C, struct instruction *phi, pseudo_t tmp)
{
pseudo_t target = phi->target;
struct pseudo_user *pu;
pseudo_t src;
// verify if this phi can be simplified
FOR_EACH_PTR(phi->phi_list, src) {
struct instruction *def = src->def;
if (!def)
continue;
if (def->bb == phi->bb)
return 0;
} END_FOR_EACH_PTR(src);
// no need to make a copy of this one
// -> replace the target pseudo by the tmp
FOR_EACH_PTR(target->users, pu) {
dmrC_use_pseudo(C, pu->insn, tmp, pu->userp);
} END_FOR_EACH_PTR(pu);
phi->bb = NULL;
return 1;
}
static void replace_phi_node(struct dmr_C *C, struct instruction *phi)
{
pseudo_t tmp;
pseudo_t p;
tmp = dmrC_alloc_pseudo(C, NULL);
tmp->type = phi->target->type;
tmp->ident = phi->target->ident;
tmp->def = NULL; // defined by all the phisrc
// can we avoid to make of copy?
simplify_phi_node(C, phi, tmp);
// rewrite all it's phi_src to copy to a new tmp
FOR_EACH_PTR(phi->phi_list, p) {
struct instruction *def = p->def;
pseudo_t src;
if (p == VOID_PSEUDO(C))
continue;
assert(def->opcode == OP_PHISOURCE);
def->opcode = OP_COPY;
def->target = tmp;
// can we eliminate the copy?
src = def->phi_src;
if (src->type != PSEUDO_REG)
continue;
switch (nbr_pseudo_users(src)) {
struct instruction *insn;
case 1:
insn = src->def;
if (!insn)
break;
insn->target = tmp;
case 0:
dmrC_kill_instruction(C, def);
def->bb = NULL;
}
} END_FOR_EACH_PTR(p);
if (!phi->bb)
return;
// rewrite the phi node:
// phi %rt, ...
// to:
// copy %rt, %tmp
phi->opcode = OP_COPY;
dmrC_use_pseudo(C, phi, tmp, &phi->src);
}
static void rewrite_phi_bb(struct dmr_C *C, struct basic_block *bb)
{
struct instruction *insn;
// Replace all the phi-nodes by copies of a temporary
// (which represent the set of all the %phi that feed them).
// The target pseudo doesn't change.
FOR_EACH_PTR(bb->insns, insn) {
if (!insn->bb)
continue;
if (insn->opcode != OP_PHI)
continue;
replace_phi_node(C, insn);
} END_FOR_EACH_PTR(insn);
}
int dmrC_unssa(struct dmr_C *C, struct entrypoint *ep)
{
struct basic_block *bb;
FOR_EACH_PTR(ep->bbs, bb) {
rewrite_phi_bb(C, bb);
} END_FOR_EACH_PTR(bb);
return 0;
}

@ -1,868 +0,0 @@
#include <ctype.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <walksymbol.h>
static void walk_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_statement(struct dmr_C *C, struct statement *stmt, struct symbol_visitor *visitor);
static void walk_symbol_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_assignment_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_binary_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_preop_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_postop_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_call_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_cast_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_conditional_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_label_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor);
static void walk_initializer_expression(struct dmr_C *C, struct expression *expr, struct symbol *ctype,
struct symbol_visitor *visitor);
static void walk_label(struct dmr_C *C, struct symbol *label, struct symbol_visitor *visitor);
static void walk_return_statement(struct dmr_C *C, struct statement *stmt, struct symbol_visitor *visitor);
static void walk_iterator_statement(struct dmr_C *C, struct statement *stmt, struct symbol_visitor *visitor);
static void walk_switch_statement(struct dmr_C *C, struct statement *stmt, struct symbol_visitor *visitor);
void walk_return_statement(struct dmr_C *C, struct statement *stmt, struct symbol_visitor *visitor)
{
struct expression *expr = stmt->ret_value;
struct symbol *target = stmt->ret_target;
if (expr && expr->ctype) {
walk_expression(C, expr, visitor);
}
visitor->begin_statement(visitor->data, STMT_GOTO);
dmrC_walk_symbol(C, target, visitor);
visitor->end_statement(visitor->data);
}
void walk_label(struct dmr_C *C, struct symbol *label, struct symbol_visitor *visitor)
{
visitor->begin_label(visitor->data, dmrC_show_ident(C, label->ident));
dmrC_walk_symbol(C, label, visitor);
visitor->end_label(visitor->data);
}
void walk_iterator_statement(struct dmr_C *C, struct statement *stmt, struct symbol_visitor *visitor)
{
struct statement *pre_statement = stmt->iterator_pre_statement;
struct expression *pre_condition = stmt->iterator_pre_condition;
struct statement *statement = stmt->iterator_statement;
struct statement *post_statement = stmt->iterator_post_statement;
struct expression *post_condition = stmt->iterator_post_condition;
dmrC_walk_symbol_list(C, stmt->iterator_syms, visitor);
if (pre_statement) {
visitor->begin_iterator_prestatement(visitor->data);
walk_statement(C, pre_statement, visitor);
visitor->end_iterator_prestatement(visitor->data);
}
if (pre_condition) {
visitor->begin_iterator_precondition(visitor->data);
walk_expression(C, pre_condition, visitor);
visitor->end_iterator_precondition(visitor->data);
}
visitor->begin_iterator_statement(visitor->data);
walk_statement(C, statement, visitor);
visitor->end_iterator_statement(visitor->data);
if (stmt->iterator_continue->used) {
walk_label(C, stmt->iterator_continue, visitor);
}
if (post_statement) {
visitor->begin_iterator_poststatement(visitor->data);
walk_statement(C, post_statement, visitor);
visitor->end_iterator_poststatement(visitor->data);
}
if (post_condition) {
visitor->begin_iterator_postcondition(visitor->data);
walk_expression(C, post_condition, visitor);
visitor->end_iterator_postcondition(visitor->data);
}
if (stmt->iterator_break->used) {
walk_label(C, stmt->iterator_break, visitor);
}
}
void walk_switch_statement(struct dmr_C *C, struct statement *stmt, struct symbol_visitor *visitor)
{
walk_expression(C, stmt->switch_expression, visitor);
struct symbol *sym;
/*
* Debugging only: Check that the case list is correct
* by printing it out.
*
* This is where a _real_ back-end would go through the
* cases to decide whether to use a lookup table or a
* series of comparisons etc
*/
FOR_EACH_PTR(stmt->switch_case->symbol_list, sym)
{
struct statement *case_stmt = sym->stmt;
struct expression *expr = case_stmt->case_expression;
struct expression *to = case_stmt->case_to;
if (!expr) {
visitor->begin_default_case(visitor->data);
} else {
if (expr->type == EXPR_VALUE) {
if (to) {
if (to->type == EXPR_VALUE) {
visitor->begin_case_range(visitor->data, expr->value, to->value);
}
} else {
visitor->begin_case_value(visitor->data, expr->value);
}
}
}
dmrC_walk_symbol(C, sym, visitor);
visitor->end_case(visitor->data);
}
END_FOR_EACH_PTR(sym);
walk_statement(C, stmt->switch_statement, visitor);
if (stmt->switch_break->used)
walk_label(C, stmt->switch_break, visitor);
}
void walk_statement(struct dmr_C *C, struct statement *stmt, struct symbol_visitor *visitor)
{
if (!stmt)
return;
visitor->begin_statement(visitor->data, stmt->type);
switch (stmt->type) {
case STMT_DECLARATION:
dmrC_walk_symbol_list(C, stmt->declaration, visitor);
break;
case STMT_RETURN:
walk_return_statement(C, stmt, visitor);
break;
case STMT_COMPOUND: {
struct statement *s;
// if (stmt->inline_fn) {
// dmrC_show_statement(C, stmt->args);
// printf("\tbegin_inline \t%s\n", dmrC_show_ident(C,
// stmt->inline_fn->ident));
//}
FOR_EACH_PTR(stmt->stmts, s) { walk_statement(C, s, visitor); }
END_FOR_EACH_PTR(s);
if (stmt->ret) {
walk_label(C, stmt->ret, visitor);
}
// if (stmt->inline_fn)
// printf("\tend_inlined\t%s\n", dmrC_show_ident(C,
// stmt->inline_fn->ident));
break;
}
case STMT_EXPRESSION:
walk_expression(C, stmt->expression, visitor);
break;
case STMT_IF: {
struct expression *cond = stmt->if_conditional;
walk_expression(C, cond, visitor);
visitor->begin_if_then(visitor->data);
walk_statement(C, stmt->if_true, visitor);
visitor->end_if_then(visitor->data);
if (stmt->if_false) {
visitor->begin_if_else(visitor->data);
walk_statement(C, stmt->if_false, visitor);
visitor->end_if_else(visitor->data);
}
break;
}
case STMT_SWITCH:
walk_switch_statement(C, stmt, visitor);
break;
case STMT_CASE:
walk_label(C, stmt->case_label, visitor);
walk_statement(C, stmt->case_statement, visitor);
break;
case STMT_ITERATOR:
walk_iterator_statement(C, stmt, visitor);
break;
case STMT_NONE:
break;
case STMT_LABEL:
visitor->begin_label(visitor->data, dmrC_show_ident(C, stmt->label_identifier->ident));
dmrC_walk_symbol(C, stmt->label_identifier, visitor);
visitor->end_label(visitor->data);
walk_statement(C, stmt->label_statement, visitor);
break;
case STMT_GOTO:
if (stmt->goto_expression) {
walk_expression(C, stmt->goto_expression, visitor);
} else {
dmrC_walk_symbol(C, stmt->goto_label, visitor);
}
break;
case STMT_ASM:
// printf("\tasm( .... )\n");
break;
case STMT_CONTEXT: {
// int val = dmrC_show_expression(C, stmt->expression);
// printf("\tcontext( %d )\n", val);
break;
}
case STMT_RANGE: {
// int val = dmrC_show_expression(C, stmt->range_expression);
// int low = dmrC_show_expression(C, stmt->range_low);
// int high = dmrC_show_expression(C, stmt->range_high);
// printf("\trange( %d %d-%d)\n", val, low, high);
break;
}
}
visitor->end_statement(visitor->data);
}
void walk_symbol_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
assert(expr->type == EXPR_SYMBOL);
struct symbol *sym = expr->symbol;
if (!sym)
return;
dmrC_walk_symbol(C, sym, visitor);
}
void walk_assignment_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
assert(expr->type == EXPR_ASSIGNMENT);
if (!expr->ctype)
return;
int op = expr->op;
visitor->begin_assignment_expression(visitor->data, expr->type, op);
walk_expression(C, expr->left, visitor);
walk_expression(C, expr->right, visitor);
visitor->end_assignment_expression(visitor->data);
}
void walk_binary_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
assert(expr->type == EXPR_BINOP || expr->type == EXPR_COMPARE || expr->type == EXPR_LOGICAL);
if (!expr->ctype)
return;
int op = expr->op;
visitor->begin_binop_expression(visitor->data, expr->type, op);
walk_expression(C, expr->left, visitor);
walk_expression(C, expr->right, visitor);
visitor->end_binop_expression(visitor->data);
}
void walk_preop_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
assert(expr->type == EXPR_PREOP);
visitor->begin_preop_expression(visitor->data, expr->type, expr->op);
walk_expression(C, expr->unop, visitor);
visitor->end_preop_expression(visitor->data);
}
void walk_postop_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
assert(expr->type == EXPR_POSTOP);
visitor->begin_postop_expression(visitor->data, expr->type, expr->op);
walk_expression(C, expr->unop, visitor);
visitor->end_postop_expression(visitor->data);
}
void walk_call_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
assert(expr->type == EXPR_CALL);
if (!expr->ctype) {
return;
}
struct symbol *direct;
struct expression *arg, *fn;
fn = expr->fn;
/* Remove dereference, if any */
direct = NULL;
if (fn->type == EXPR_PREOP) {
if (fn->unop->type == EXPR_SYMBOL) {
struct symbol *sym = fn->unop->symbol;
if (sym->ctype.base_type->type == SYM_FN)
direct = sym;
}
}
if (direct && !direct->aux) {
dmrC_walk_symbol(C, direct, visitor);
}
if (direct) {
visitor->begin_direct_call_expression(visitor->data, expr->type, dmrC_show_ident(C, direct->ident));
} else {
visitor->begin_indirect_call_expression(visitor->data, expr->type);
walk_expression(C, fn, visitor);
}
int n = 0;
FOR_EACH_PTR(expr->args, arg)
{
visitor->begin_callarg_expression(visitor->data, expr->type, ++n);
walk_expression(C, arg, visitor);
visitor->end_callarg_expression(visitor->data);
}
END_FOR_EACH_PTR(arg);
visitor->end_call_expression(visitor->data);
}
void walk_cast_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
struct symbol *old_type, *new_type;
int oldbits, newbits;
int is_signed;
old_type = expr->cast_expression->ctype;
new_type = expr->cast_type;
oldbits = old_type->bit_size;
newbits = new_type->bit_size;
is_signed = dmrC_is_signed_type(old_type);
visitor->begin_cast_expression(visitor->data, expr->type, oldbits, newbits, !is_signed);
walk_expression(C, expr->cast_expression, visitor);
dmrC_walk_symbol(C, new_type, visitor);
visitor->end_cast_expression(visitor->data);
}
void walk_conditional_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
visitor->begin_conditional_expression(visitor->data, expr->type);
walk_expression(C, expr->conditional, visitor);
walk_expression(C, expr->cond_true, visitor);
walk_expression(C, expr->cond_false, visitor);
visitor->end_conditional_expression(visitor->data);
}
void walk_label_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
visitor->begin_label_expression(visitor->data, expr->type);
dmrC_walk_symbol(C, expr->label_symbol, visitor);
visitor->end_label_expression(visitor->data);
}
static void walk_initialization(struct dmr_C *C, struct symbol *sym, struct expression *expr,
struct symbol_visitor *visitor)
{
if (!expr->ctype)
return;
visitor->begin_initialization(visitor->data, expr->type);
walk_expression(C, expr, visitor);
dmrC_walk_symbol(C, sym, visitor);
visitor->end_initialization(visitor->data);
}
static void walk_position_expression(struct dmr_C *C, struct expression *expr, struct symbol *base,
struct symbol_visitor *visitor)
{
struct symbol *ctype = expr->init_expr->ctype;
int bit_offset;
bit_offset = ctype ? ctype->bit_offset : -1;
visitor->begin_expression_position(visitor->data, EXPR_POS, expr->init_offset, bit_offset,
dmrC_show_ident(C, base->ident));
walk_expression(C, expr->init_expr, visitor);
visitor->end_expression_position(visitor->data);
}
void walk_initializer_expression(struct dmr_C *C, struct expression *expr, struct symbol *ctype,
struct symbol_visitor *visitor)
{
struct expression *entry;
FOR_EACH_PTR(expr->expr_list, entry)
{
again:
// Nested initializers have their positions already
// recursively calculated - just output them too
if (entry->type == EXPR_INITIALIZER) {
walk_initializer_expression(C, entry, ctype, visitor);
continue;
}
// Initializer indexes and identifiers should
// have been evaluated to EXPR_POS
if (entry->type == EXPR_IDENTIFIER) {
visitor->do_expression_identifier(visitor->data, entry->type,
dmrC_show_ident(C, entry->expr_ident));
entry = entry->ident_expression;
goto again;
}
if (entry->type == EXPR_INDEX) {
visitor->do_expression_index(visitor->data, entry->type, entry->idx_from, entry->idx_to);
entry = entry->idx_expression;
goto again;
}
if (entry->type == EXPR_POS) {
walk_position_expression(C, entry, ctype, visitor);
continue;
}
walk_initialization(C, ctype, entry, visitor);
}
END_FOR_EACH_PTR(entry);
}
void walk_expression(struct dmr_C *C, struct expression *expr, struct symbol_visitor *visitor)
{
if (!expr)
return;
if (!expr->ctype)
return;
visitor->begin_expression(visitor->data, expr->type);
switch (expr->type) {
case EXPR_CALL:
walk_call_expression(C, expr, visitor);
break;
case EXPR_ASSIGNMENT:
walk_assignment_expression(C, expr, visitor);
break;
case EXPR_COMMA:
// return show_comma(C, expr);
break;
case EXPR_BINOP:
case EXPR_COMPARE:
case EXPR_LOGICAL:
walk_binary_expression(C, expr, visitor);
break;
case EXPR_PREOP:
walk_preop_expression(C, expr, visitor);
break;
case EXPR_POSTOP:
walk_postop_expression(C, expr, visitor);
break;
case EXPR_SYMBOL:
walk_symbol_expression(C, expr, visitor);
break;
case EXPR_DEREF:
case EXPR_SIZEOF:
case EXPR_PTRSIZEOF:
case EXPR_ALIGNOF:
case EXPR_OFFSETOF:
break;
case EXPR_CAST:
case EXPR_FORCE_CAST:
case EXPR_IMPLIED_CAST:
walk_cast_expression(C, expr, visitor);
break;
case EXPR_VALUE:
visitor->int_literal(visitor->data, expr->value, expr->ctype->bit_size,
expr->ctype->ctype.modifiers & MOD_UNSIGNED);
break;
case EXPR_FVALUE:
visitor->float_literal(visitor->data, expr->fvalue, expr->ctype->bit_size);
break;
case EXPR_STRING:
visitor->string_literal(visitor->data, dmrC_show_string(C, expr->string));
break;
case EXPR_INITIALIZER:
walk_initializer_expression(C, expr, expr->ctype, visitor);
break;
case EXPR_SELECT:
case EXPR_CONDITIONAL:
walk_conditional_expression(C, expr, visitor);
break;
case EXPR_STATEMENT:
// return show_statement_expr(C, expr);
break;
case EXPR_LABEL:
walk_label_expression(C, expr, visitor);
break;
case EXPR_SLICE:
// return show_slice(C, expr);
break;
// None of these should exist as direct expressions: they are
// only valid as sub-expressions of initializers.
case EXPR_POS:
case EXPR_IDENTIFIER:
case EXPR_INDEX:
case EXPR_TYPE:
break;
}
visitor->end_expression(visitor->data);
}
void dmrC_walk_symbol_list(struct dmr_C *C, struct symbol_list *list, struct symbol_visitor *visitor)
{
struct symbol *sym;
FOR_EACH_PTR(list, sym) { dmrC_walk_symbol(C, sym, visitor); }
END_FOR_EACH_PTR(sym);
}
void dmrC_walk_symbol(struct dmr_C *C, struct symbol *sym, struct symbol_visitor *visitor)
{
if (!sym)
return;
if (sym->type != SYM_BASETYPE) {
if (sym->aux) {
/* already visited */
const char *name = sym->ident ? dmrC_show_ident(C, sym->ident) : "";
visitor->reference_symbol(visitor->data, (uint64_t)sym->aux, name);
return;
}
visitor->id++;
sym->aux = (void *)visitor->id;
}
char name[80] = {0};
if (sym->ident)
snprintf(name, sizeof name, "%s", dmrC_show_ident(C, sym->ident));
else if (sym->type == SYM_BASETYPE)
snprintf(name, sizeof name, "%s", dmrC_builtin_typename(C, sym));
struct symbol_info syminfo = {.id = (uint64_t)sym->aux,
.name = name,
.symbol_namespace = sym->ns,
.symbol_type = sym->type,
.alignment = sym->ctype.alignment,
.pos = sym->pos,
.bit_size = sym->bit_size,
.offset = sym->offset};
if (sym->ns == NS_STRUCT && dmrC_is_bitfield_type(sym)) {
syminfo.bit_offset = sym->bit_offset;
}
if (sym->array_size) {
syminfo.array_size = dmrC_get_expression_value(C, sym->array_size);
}
visitor->begin_symbol(visitor->data, &syminfo);
if (sym->type == SYM_STRUCT || sym->type == SYM_UNION) {
struct symbol *member;
visitor->begin_struct_members(visitor->data, &syminfo);
FOR_EACH_PTR(sym->symbol_list, member) { dmrC_walk_symbol(C, member, visitor); }
END_FOR_EACH_PTR(member);
visitor->end_struct_members(visitor->data);
}
if (sym->type == SYM_FN) {
struct symbol *arg;
visitor->begin_func_arguments(visitor->data, &syminfo);
FOR_EACH_PTR(sym->arguments, arg) { dmrC_walk_symbol(C, arg, visitor); }
END_FOR_EACH_PTR(member);
visitor->end_func_arguments(visitor->data);
}
// Is there a base type?
if (sym->type != SYM_BASETYPE && sym->ctype.base_type) {
if (sym->type == SYM_FN)
visitor->begin_func_returntype(visitor->data, &syminfo);
else
visitor->begin_basetype(visitor->data, &syminfo);
dmrC_walk_symbol(C, sym->ctype.base_type, visitor);
if (sym->type == SYM_FN)
visitor->end_func_returntype(visitor->data);
else
visitor->end_basetype(visitor->data);
}
if (sym->type == SYM_FN) {
if (sym->stmt) {
visitor->begin_func_body(visitor->data, &syminfo);
walk_statement(C, sym->stmt, visitor);
visitor->end_func_body(visitor->data);
}
}
if (sym->initializer) {
visitor->begin_initializer(visitor->data, &syminfo);
walk_expression(C, sym->initializer, visitor);
visitor->end_initializer(visitor->data);
}
visitor->end_symbol(visitor->data);
}
static void begin_symbol_default(void *data, struct symbol_info *syminfo)
{
(void)data;
(void)syminfo;
}
static void end_symbol_default(void *data) { (void)data; }
static void begin_members_default(void *data, struct symbol_info *syminfo)
{
(void)data;
(void)syminfo;
}
static void end_members_default(void *data) { (void)data; }
static void begin_arguments_default(void *data, struct symbol_info *syminfo)
{
(void)data;
(void)syminfo;
}
static void end_arguments_default(void *data) { (void)data; }
static void reference_symbol_default(void *data, uint64_t id, const char *name)
{
(void)data;
(void)id;
(void)name;
}
static void begin_body_default(void *data, struct symbol_info *syminfo)
{
(void)data;
(void)syminfo;
}
static void end_body_default(void *data) { (void)data; }
static void begin_func_returntype_default(void *data, struct symbol_info *syminfo)
{
(void)data;
(void)syminfo;
}
static void end_func_returntype_default(void *data) { (void)data; }
static void begin_basetype_default(void *data, struct symbol_info *syminfo)
{
(void)data;
(void)syminfo;
}
static void end_basetype_default(void *data) { (void)data; }
static void begin_initializer_default(void *data, struct symbol_info *syminfo)
{
(void)data;
(void)syminfo;
}
static void end_initializer_default(void *data) { (void)data; }
static void string_expression_default(void *data, const char *str)
{
(void)data;
(void)str;
}
static void int_literal_default(void *data, long long value, int bit_size, bool is_unsigned)
{
(void)data;
(void)value;
(void)bit_size;
(void)is_unsigned;
}
static void float_literal_default(void *data, long double fvalue, int bit_size)
{
(void)data;
(void)fvalue;
(void)bit_size;
}
static void begin_statement_default(void *data, enum statement_type statement_type)
{
(void)data;
(void)statement_type;
}
static void end_statement_default(void *data) { (void)data; }
static void begin_expression_default(void *data, enum expression_type expr_type)
{
(void)data;
(void)expr_type;
}
static void end_expression_default(void *data) { (void)data; }
static void begin_assignment_expression_default(void *data, enum expression_type expr_type, int op)
{
(void)data;
(void)expr_type;
(void)op;
}
static void end_assignment_expression_default(void *data) { (void)data; }
static void begin_binop_expression_default(void *data, enum expression_type expr_type, int op)
{
(void)data;
(void)expr_type;
(void)op;
}
static void end_binop_expression_default(void *data) { (void)data; }
static void begin_preop_expression_default(void *data, enum expression_type expr_type, int op)
{
(void)data;
(void)expr_type;
(void)op;
}
static void end_preop_expression_default(void *data) { (void)data; }
static void begin_postop_expression_default(void *data, enum expression_type expr_type, int op)
{
(void)data;
(void)expr_type;
(void)op;
}
static void end_postop_expression_default(void *data) { (void)data; }
static void begin_direct_call_expression_default(void *data, enum expression_type expr_type, const char *name)
{
(void)data;
(void)expr_type;
(void)name;
}
static void begin_indirect_call_expression_default(void *data, enum expression_type expr_type)
{
(void)data;
(void)expr_type;
}
static void end_call_expression_default(void *data) { (void)data; }
static void begin_callarg_expression_default(void *data, enum expression_type expr_type, int argpos)
{
(void)data;
(void)expr_type;
(void)argpos;
}
static void end_callarg_expression_default(void *data) { (void)data; }
static void begin_cast_expression_default(void *data, enum expression_type expr_type, int oldbits, int newbits,
bool is_unsigned)
{
(void)data;
(void)expr_type;
(void)oldbits;
(void)newbits;
(void)is_unsigned;
}
static void end_cast_expression_default(void *data) { (void)data; }
static void begin_conditional_expression_default(void *data, enum expression_type expr_type)
{
(void)data;
(void)expr_type;
}
static void end_conditional_expression_default(void *data) { (void)data; }
static void begin_label_expression_default(void *data, enum expression_type expr_type)
{
(void)data;
(void)expr_type;
}
static void end_label_expression_default(void *data) { (void)data; }
static void do_expression_identifier_default(void *data, enum expression_type expr_type, const char *ident)
{
(void)data;
(void)expr_type;
(void)ident;
}
static void do_expression_index_default(void *data, enum expression_type expr_type, unsigned from, unsigned to)
{
(void)data;
(void)expr_type;
(void)from;
(void)to;
}
static void begin_expression_position_default(void *data, enum expression_type expr_type, unsigned init_offset,
int bit_offset, const char *ident)
{
(void)data;
(void)expr_type;
(void)init_offset;
(void)ident;
(void)bit_offset;
}
static void end_expression_position_default(void *data) { (void)data; }
static void begin_initialization_default(void *data, enum expression_type expr_type)
{
(void)data;
(void)expr_type;
}
static void end_initialization_default(void *data) { (void)data; }
static void begin_label_default(void *data, const char *name)
{
(void)data;
(void)name;
}
static void end_label_default(void *data) { (void)data; }
static void begin_iterator_prestatement_default(void *data) { (void)data; }
static void end_iterator_prestatement_default(void *data) { (void)data; }
static void begin_iterator_precondition_default(void *data) { (void)data; }
static void end_iterator_precondition_default(void *data) { (void)data; }
static void begin_iterator_statement_default(void *data) { (void)data; }
static void end_iterator_statement_default(void *data) { (void)data; }
static void begin_iterator_postcondition_default(void *data) { (void)data; }
static void end_iterator_postcondition_default(void *data) { (void)data; }
static void begin_iterator_poststatement_default(void *data) { (void)data; }
static void end_iterator_poststatement_default(void *data) { (void)data; }
static void begin_case_value_default(void *data, long long value)
{
(void)data;
(void)value;
}
static void begin_case_range_default(void *data, long long from, long long to)
{
(void)data;
(void)from;
(void)to;
}
static void begin_default_case_default(void *data) { (void)data; }
static void end_case_default(void *data) { (void)data; }
static void begin_if_then_default(void *data) { (void)data; }
static void end_if_then_default(void *data) { (void)data; }
static void begin_if_else_default(void *data) { (void)data; }
static void end_if_else_default(void *data) { (void)data; }
void dmrC_init_symbol_visitor(struct symbol_visitor *visitor)
{
visitor->data = NULL;
visitor->id = 0;
visitor->begin_symbol = begin_symbol_default;
visitor->end_symbol = end_symbol_default;
visitor->begin_struct_members = begin_members_default;
visitor->end_struct_members = end_members_default;
visitor->begin_func_arguments = begin_arguments_default;
visitor->end_func_arguments = end_arguments_default;
visitor->reference_symbol = reference_symbol_default;
visitor->begin_func_body = begin_body_default;
visitor->end_func_body = end_body_default;
visitor->begin_func_returntype = begin_func_returntype_default;
visitor->end_func_returntype = end_func_returntype_default;
visitor->begin_basetype = begin_basetype_default;
visitor->end_basetype = end_basetype_default;
visitor->begin_initializer = begin_initializer_default;
visitor->end_initializer = end_initializer_default;
visitor->string_literal = string_expression_default;
visitor->float_literal = float_literal_default;
visitor->int_literal = int_literal_default;
visitor->begin_statement = begin_statement_default;
visitor->end_statement = end_statement_default;
visitor->begin_expression = begin_expression_default;
visitor->end_expression = end_expression_default;
visitor->begin_assignment_expression = begin_assignment_expression_default;
visitor->end_assignment_expression = end_assignment_expression_default;
visitor->begin_binop_expression = begin_binop_expression_default;
visitor->end_binop_expression = end_binop_expression_default;
visitor->begin_preop_expression = begin_preop_expression_default;
visitor->end_preop_expression = end_preop_expression_default;
visitor->begin_postop_expression = begin_postop_expression_default;
visitor->end_postop_expression = end_postop_expression_default;
visitor->begin_direct_call_expression = begin_direct_call_expression_default;
visitor->begin_indirect_call_expression = begin_indirect_call_expression_default;
visitor->end_call_expression = end_call_expression_default;
visitor->begin_callarg_expression = begin_callarg_expression_default;
visitor->end_callarg_expression = end_callarg_expression_default;
visitor->begin_cast_expression = begin_cast_expression_default;
visitor->end_cast_expression = end_cast_expression_default;
visitor->begin_conditional_expression = begin_conditional_expression_default;
visitor->end_conditional_expression = end_conditional_expression_default;
visitor->begin_label_expression = begin_label_expression_default;
visitor->end_label_expression = end_label_expression_default;
visitor->do_expression_identifier = do_expression_identifier_default;
visitor->do_expression_index = do_expression_index_default;
visitor->begin_expression_position = begin_expression_position_default;
visitor->end_expression_position = end_expression_position_default;
visitor->begin_initialization = begin_initialization_default;
visitor->end_initialization = end_initialization_default;
visitor->begin_label = begin_label_default;
visitor->end_label = end_label_default;
visitor->begin_iterator_prestatement = begin_iterator_prestatement_default;
visitor->end_iterator_prestatement = end_iterator_prestatement_default;
visitor->begin_iterator_precondition = begin_iterator_precondition_default;
visitor->end_iterator_precondition = end_iterator_precondition_default;
visitor->begin_iterator_statement = begin_iterator_statement_default;
visitor->end_iterator_statement = end_iterator_statement_default;
visitor->begin_iterator_postcondition = begin_iterator_postcondition_default;
visitor->end_iterator_postcondition = end_iterator_postcondition_default;
visitor->begin_iterator_poststatement = begin_iterator_poststatement_default;
visitor->end_iterator_poststatement = end_iterator_poststatement_default;
visitor->begin_case_value = begin_case_value_default;
visitor->begin_case_range = begin_case_range_default;
visitor->begin_default_case = begin_default_case_default;
visitor->end_case = end_case_default;
visitor->begin_if_then = begin_if_then_default;
visitor->end_if_then = end_if_then_default;
visitor->begin_if_else = begin_if_else_default;
visitor->end_if_else = end_if_else_default;
}

@ -1,144 +0,0 @@
#ifndef DMR_C_PARSETREE_H
#define DMR_C_PARSETREE_H
#include <allocate.h>
#include <lib.h>
#include <expression.h>
#include <parse.h>
#include <port.h>
#include <symbol.h>
#include <token.h>
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct symbol_info {
uint64_t id;
enum namespace_type symbol_namespace;
enum type symbol_type;
const char *name;
int bit_size;
unsigned long alignment;
unsigned int offset;
int bit_offset;
long long array_size;
struct position pos;
};
struct symbol_visitor {
void *data;
uint64_t id;
void (*begin_symbol)(void *data, struct symbol_info *syminfo);
void (*end_symbol)(void *data);
void (*begin_struct_members)(void *data, struct symbol_info *syminfo);
void (*end_struct_members)(void *data);
void (*begin_func_arguments)(void *data, struct symbol_info *syminfo);
void (*end_func_arguments)(void *data);
void (*reference_symbol)(void *data, uint64_t id, const char *name);
void (*begin_func_body)(void *data, struct symbol_info *syminfo);
void (*end_func_body)(void *data);
void (*begin_func_returntype)(void *data, struct symbol_info *syminfo);
void (*end_func_returntype)(void *data);
void (*begin_basetype)(void *data, struct symbol_info *syminfo);
void (*end_basetype)(void *data);
void (*begin_initializer)(void *data, struct symbol_info *syminfo);
void (*end_initializer)(void *data);
void (*string_literal)(void *data, const char *str);
void (*int_literal)(void *data, long long value, int bit_size,
bool is_unsigned);
void (*float_literal)(void *data, long double fvalue, int bit_size);
void (*begin_statement)(void *data, enum statement_type statement_type);
void (*end_statement)(void *data);
void (*begin_expression)(void *data, enum expression_type expr_type);
void (*end_expression)(void *data);
void (*begin_assignment_expression)(void *data,
enum expression_type expr_type,
int op);
void (*end_assignment_expression)(void *data);
void (*begin_binop_expression)(void *data,
enum expression_type expr_type, int op);
void (*end_binop_expression)(void *data);
void (*begin_preop_expression)(void *data,
enum expression_type expr_type, int op);
void (*end_preop_expression)(void *data);
void (*begin_postop_expression)(void *data,
enum expression_type expr_type, int op);
void (*end_postop_expression)(void *data);
void (*begin_direct_call_expression)(void *data,
enum expression_type expr_type,
const char *name);
void (*begin_indirect_call_expression)(void *data,
enum expression_type expr_type);
void (*end_call_expression)(void *data);
void (*begin_callarg_expression)(void *data,
enum expression_type expr_type,
int argpos);
void (*end_callarg_expression)(void *data);
void (*begin_cast_expression)(void *data,
enum expression_type expr_type,
int oldbits, int newbits,
bool is_unsigned);
void (*end_cast_expression)(void *data);
void (*begin_conditional_expression)(void *data,
enum expression_type expr_type);
void (*end_conditional_expression)(void *data);
void (*begin_label_expression)(void *data,
enum expression_type expr_type);
void (*end_label_expression)(void *data);
void (*do_expression_identifier)(void *data,
enum expression_type expr_type,
const char *ident);
void (*do_expression_index)(void *data, enum expression_type expr_type,
unsigned from, unsigned to);
void (*begin_expression_position)(void *data,
enum expression_type expr_type,
unsigned init_offset, int bit_offset,
const char *ident);
void (*end_expression_position)(void *data);
void (*begin_initialization)(void *data,
enum expression_type expr_type);
void (*end_initialization)(void *data);
void (*begin_label)(void *data, const char *name);
void (*end_label)(void *data);
void(*begin_iterator_prestatement)(void *data);
void(*end_iterator_prestatement)(void *data);
void(*begin_iterator_precondition)(void *data);
void(*end_iterator_precondition)(void *data);
void(*begin_iterator_statement)(void *data);
void(*end_iterator_statement)(void *data);
void(*begin_iterator_postcondition)(void *data);
void(*end_iterator_postcondition)(void *data);
void(*begin_iterator_poststatement)(void *data);
void(*end_iterator_poststatement)(void *data);
void(*begin_case_value)(void *data, long long value);
void(*begin_case_range)(void *data, long long from, long long to);
void(*begin_default_case)(void *data);
void(*end_case)(void *data);
void(*begin_if_then)(void *data);
void(*end_if_then)(void *data);
void(*begin_if_else)(void *data);
void(*end_if_else)(void *data);
};
extern void dmrC_init_symbol_visitor(struct symbol_visitor *visitor);
extern void dmrC_walk_symbol_list(struct dmr_C *C, struct symbol_list *list,
struct symbol_visitor *visitor);
extern void dmrC_walk_symbol(struct dmr_C *C, struct symbol *sym,
struct symbol_visitor *visitor);
#ifdef __cplusplus
}
#endif
#endif

@ -12,20 +12,15 @@ RUN set -x \
&& cd /Software \
&& tar xvf "cmake-3.14.5-Linux-x86_64.tar.gz" \
&& rm -rf "/Software/cmake-3.14.5-Linux-x86_64.tar.gz" \
&& wget -O "/Software/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz" "http://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz" \
&& cd /Software \
&& tar xvf "clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz" \
&& rm -rf "/Software/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz" \
&& mkdir -p /sources \
&& cd /sources \
&& git clone https://github.com/dibyendumajumdar/ravi.git \
&& cd /sources/ravi \
&& mkdir build \
&& cd build \
&& /Software/cmake-3.14.5-Linux-x86_64/bin/cmake -DSTATIC_BUILD=ON -DCMAKE_INSTALL_PREFIX=/Software/ravi -DLLVM_JIT=ON -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR=/Software/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04/lib/cmake/llvm .. \
&& /Software/cmake-3.14.5-Linux-x86_64/bin/cmake -DCMAKE_INSTALL_PREFIX=/Software/ravi -DCMAKE_BUILD_TYPE=Release .. \
&& make install \
&& rm -rf /Software/cmake-3.14.5-Linux-x86_64 \
&& rm -rf /Software/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04 \
&& rm -rf /sources \
&& apt-get autoremove \
&& apt-get remove -y --purge git wget build-essential \

@ -1,5 +1,5 @@
/*
** $Id: lauxlib.h,v 1.131.1.1 2017/04/19 17:20:42 roberto Exp $
** $Id: lauxlib.h $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@ -15,6 +15,12 @@
#include "lua.h"
/* global table */
#define LUA_GNAME "_G"
typedef struct luaL_Buffer luaL_Buffer;
/* extra error code for 'luaL_loadfilex' */
#define LUA_ERRFILE (LUA_ERRERR+1)
@ -48,6 +54,7 @@ LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
api function ravi_typename() */
LUALIB_API const char *(raviL_tolstring) (lua_State *L, int idx, size_t *len);
LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname);
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
size_t *l);
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,
@ -77,6 +84,7 @@ LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
/* predefined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)
@ -97,8 +105,10 @@ LUALIB_API lua_State *(luaL_newstate) (void);
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r);
LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s,
const char *p, const char *r);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s,
const char *p, const char *r);
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
@ -125,6 +135,10 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
#define luaL_argcheck(L, cond,arg,extramsg) \
((void)((cond) || luaL_argerror(L, (arg), (extramsg))))
#define luaL_argexpected(L,cond,arg,tname) \
((void)((cond) || luaL_typeerror(L, (arg), (tname))))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
@ -143,6 +157,10 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
/* push the value used to represent failure/error */
#define luaL_pushfail(L) lua_pushnil(L)
/*
** {======================================================
** Generic Buffer manipulation
@ -276,10 +294,6 @@ LUALIB_API void (luaL_setmetatable)(lua_State *L, const char *tname);
LUALIB_API void *(luaL_testudata)(lua_State *L, int ud, const char *tname);
LUALIB_API void *(luaL_checkudata)(lua_State *L, int ud, const char *tname);
LUALIB_API int (raviL_build_ast_from_buffer) (lua_State *L, const char *buff, size_t size,
const char *name, const char *mode);
LUALIB_API int (raviL_dumpast) (lua_State *L);
LUALIB_API void *ravi_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize);
#endif

@ -1,147 +0,0 @@
/*
** $Id: lgc.h,v 2.91.1.1 2017/04/19 17:39:34 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
#ifndef lgc_h
#define lgc_h
#include "lobject.h"
#include "lstate.h"
/*
** Collectable objects may have one of three colors: white, which
** means the object is not marked; gray, which means the
** object is marked, but its references may be not marked; and
** black, which means that the object and all its references are marked.
** The main invariant of the garbage collector, while marking objects,
** is that a black object can never point to a white one. Moreover,
** any gray object must be in a "gray list" (gray, grayagain, weak,
** allweak, ephemeron) so that it can be visited again before finishing
** the collection cycle. These lists have no meaning when the invariant
** is not being enforced (e.g., sweep phase).
*/
/* how much to allocate before next GC step */
#if !defined(GCSTEPSIZE)
/* ~100 small strings */
#define GCSTEPSIZE (cast_int(100 * sizeof(TString)))
#endif
/*
** Possible states of the Garbage Collector
*/
#define GCSpropagate 0
#define GCSatomic 1
#define GCSswpallgc 2
#define GCSswpfinobj 3
#define GCSswptobefnz 4
#define GCSswpend 5
#define GCScallfin 6
#define GCSpause 7
#define issweepphase(g) \
(GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend)
/*
** macro to tell when main invariant (white objects cannot point to black
** ones) must be kept. During a collection, the sweep
** phase may break the invariant, as objects turned white may point to
** still-black objects. The invariant is restored when sweep ends and
** all objects are white again.
*/
#define keepinvariant(g) ((g)->gcstate <= GCSatomic)
/*
** some useful bit tricks
*/
#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
#define setbits(x,m) ((x) |= (m))
#define testbits(x,m) ((x) & (m))
#define bitmask(b) (1<<(b))
#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
#define l_setbit(x,b) setbits(x, bitmask(b))
#define resetbit(x,b) resetbits(x, bitmask(b))
#define testbit(x,b) testbits(x, bitmask(b))
/* Layout for bit use in 'marked' field: */
#define WHITE0BIT 0 /* object is white (type 0) */
#define WHITE1BIT 1 /* object is white (type 1) */
#define BLACKBIT 2 /* object is black */
#define FINALIZEDBIT 3 /* object has been marked for finalization */
/* bit 7 is currently used by tests (luaL_checkmemory) */
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
#define iswhite(x) testbits((x)->marked, WHITEBITS)
#define isblack(x) testbit((x)->marked, BLACKBIT)
#define isgray(x) /* neither white nor black */ \
(!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT)))
#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT)
#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS)
#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow)))
#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked)
#define changewhite(x) ((x)->marked ^= WHITEBITS)
#define gray2black(x) l_setbit((x)->marked, BLACKBIT)
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
/*
** Does one step of collection when debt becomes positive. 'pre'/'pos'
** allows some adjustments to be done only when needed. macro
** 'condchangemem' is used only for heavy tests (forcing a full
** GC cycle on every opportunity)
*/
#define luaC_condGC(L,pre,pos) \
{ if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \
condchangemem(L,pre,pos); }
/* more often than not, 'pre'/'pos' are empty */
#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0)
#define luaC_barrier(L,p,v) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0))
#define luaC_barrierback(L,p,v) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
luaC_barrierback_(L,p) : cast_void(0))
#define luaC_objbarrier(L,p,o) ( \
(isblack(p) && iswhite(o)) ? \
luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
#define luaC_upvalbarrier(L,uv) ( \
(iscollectable((uv)->v) && !upisopen(uv)) ? \
luaC_upvalbarrier_(L,uv) : cast_void(0))
LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
LUAI_FUNC void luaC_freeallobjects (lua_State *L);
LUAI_FUNC void luaC_step (lua_State *L);
LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask);
LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o);
LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv);
#endif

@ -140,10 +140,10 @@ typedef void(*ravi_Writestringerror)(const char *fmt, const char *p);
#define lua_assert(c) assert(c)
#if !defined(RAVI_OPTION_STRING1)
#define RAVI_OPTION_STRING1 " assertions"
#define RAVI_OPTION_STRING1 "assertions "
#endif
#define RAVI_OPTION_STRING2 " ltests"
#define RAVI_OPTION_STRING2 "ltests "
/* to avoid warnings, and to make sure value is really unused */
#define UNUSED(x) (x=0, (void)(x))
@ -164,6 +164,7 @@ typedef struct Memcontrol {
unsigned long total;
unsigned long maxmem;
unsigned long memlimit;
unsigned long countlimit;
unsigned long objcount[LUA_NUMTAGS];
} Memcontrol;
@ -225,8 +226,7 @@ extern const char lua_ident[];
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
LUA_API void (lua_close) (lua_State *L);
LUA_API lua_State *(lua_newthread) (lua_State *L);
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
LUA_API int (lua_resetthread) (lua_State *L);
LUA_API const lua_Number *(lua_version) (lua_State *L);
@ -363,11 +363,14 @@ LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
lua_KContext ctx, lua_KFunction k);
#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL)
/* A Lua Closure must be on top of the stack. This will set _ENV upvalue */
LUA_API void (ravi_closure_setenv) (lua_State* L);
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
const char *chunkname, const char *mode);
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
LUA_API void (raviV_raise_error) (lua_State *L, int errorcode);
/*
** coroutine functions
@ -394,8 +397,10 @@ LUA_API int (lua_isyieldable) (lua_State *L);
#define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7
#define LUA_GCISRUNNING 9
#define LUA_GCGEN 10
#define LUA_GCINC 11
LUA_API int (lua_gc) (lua_State *L, int what, int data);
LUA_API int (lua_gc) (lua_State *L, int what, ...);
/*
@ -634,6 +639,9 @@ LUA_API int ravi_list_code(lua_State *L);
/* Returns a table with various system limits */
LUA_API int ravi_get_limits(lua_State *L);
/* Options */
LUA_API const char *raviV_options(struct lua_State *L);
/* Following are for debugging purposes only */
LUAI_DDEC int ravi_parser_debug;
LUA_API void ravi_set_debuglevel(int level);

@ -61,15 +61,19 @@
#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#ifndef LUA_USE_READLINE
#define LUA_USE_READLINE /* needs some extra libraries */
#endif
#endif
#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* MacOS does not need -ldl */
#ifndef LUA_USE_READLINE
#define LUA_USE_READLINE /* needs an extra library: -lreadline */
#endif
#endif
/*
@ -256,9 +260,11 @@
#endif /* } */
/* more often than not the libs go together with the core */
/*
** More often than not the libs go together with the core.
*/
#define LUALIB_API LUA_API
#define LUAMOD_API LUALIB_API
#define LUAMOD_API LUA_API
/*
@ -275,15 +281,17 @@
** give a warning about it. To avoid these warnings, change to the
** default definition.
*/
#if 0
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__) /* { */
/** RAVI change **/
#define LUAI_FUNC /* __attribute__((visibility("hidden")))*/ extern
#define LUAI_FUNC __attribute__((visibility("internal"))) extern
#else /* }{ */
#define LUAI_FUNC extern
#endif /* } */
#endif
#define LUAI_FUNC LUA_API /* AOT code needs to access symbols */
#define LUAI_DDEC LUAI_FUNC
#define LUAI_DDEC extern
#define LUAI_DDEF /* empty */
/* }================================================================== */
@ -421,14 +429,14 @@
@@ LUA_NUMBER is the floating-point type used by Lua.
@@ LUAI_UACNUMBER is the result of a 'default argument promotion'
@@ over a floating number.
@@ l_mathlim(x) corrects limit name 'x' to the proper float type
@@ l_floatatt(x) corrects float attribute 'x' to the proper float type
** by prefixing it with one of FLT/DBL/LDBL.
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
@@ LUA_NUMBER_FMT is the format for writing floats.
@@ lua_number2str converts a float to a string.
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
@@ l_floor takes the floor of a float.
@@ lua_str2number converts a decimal numeric string to a number.
@@ lua_str2number converts a decimal numeral to a number.
*/
@ -440,12 +448,13 @@
l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n))
/*
@@ lua_numbertointeger converts a float number to an integer, or
** returns 0 if float is not within the range of a lua_Integer.
** (The range comparisons are tricky because of rounding. The tests
** here assume a two-complement representation, where MININTEGER always
** has an exact representation as a float; MAXINTEGER may not have one,
** and therefore its conversion to float may have an ill-defined value.)
@@ lua_numbertointeger converts a float number with an integral value
** to an integer, or returns 0 if float is not within the range of
** a lua_Integer. (The range comparisons are tricky because of
** rounding. The tests here assume a two-complement representation,
** where MININTEGER always has an exact representation as a float;
** MAXINTEGER may not have one, and therefore its conversion to float
** may have an ill-defined value.)
*/
#define lua_numbertointeger(n,p) \
((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
@ -459,7 +468,7 @@
#define LUA_NUMBER float
#define l_mathlim(n) (FLT_##n)
#define l_floatatt(n) (FLT_##n)
#define LUAI_UACNUMBER double
@ -475,7 +484,7 @@
#define LUA_NUMBER long double
#define l_mathlim(n) (LDBL_##n)
#define l_floatatt(n) (LDBL_##n)
#define LUAI_UACNUMBER long double
@ -490,7 +499,7 @@
#define LUA_NUMBER double
#define l_mathlim(n) (DBL_##n)
#define l_floatatt(n) (DBL_##n)
#define LUAI_UACNUMBER double
@ -515,11 +524,13 @@
@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
**
@@ LUAI_UACINT is the result of a 'default argument promotion'
@@ over a lUA_INTEGER.
@@ over a LUA_INTEGER.
@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
@@ LUA_INTEGER_FMT is the format for writing integers.
@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED.
@@ LUA_UNSIGNEDBITS is the number of bits in a LUA_UNSIGNED.
@@ lua_integer2str converts an integer to a string.
*/
@ -540,6 +551,9 @@
#define LUA_UNSIGNED unsigned LUAI_UACINT
#define LUA_UNSIGNEDBITS (sizeof(LUA_UNSIGNED) * CHAR_BIT)
/* now the variable definitions */
#if LUA_INT_TYPE == LUA_INT_INT /* { int */
@ -550,6 +564,8 @@
#define LUA_MAXINTEGER INT_MAX
#define LUA_MININTEGER INT_MIN
#define LUA_MAXUNSIGNED UINT_MAX
#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */
#define LUA_INTEGER long
@ -558,6 +574,8 @@
#define LUA_MAXINTEGER LONG_MAX
#define LUA_MININTEGER LONG_MIN
#define LUA_MAXUNSIGNED ULONG_MAX
#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */
/* use presence of macro LLONG_MAX as proxy for C99 compliance */
@ -570,6 +588,8 @@
#define LUA_MAXINTEGER LLONG_MAX
#define LUA_MININTEGER LLONG_MIN
#define LUA_MAXUNSIGNED ULLONG_MAX
#elif defined(LUA_USE_WINDOWS) /* }{ */
/* in Windows, can use specific Windows types */
@ -579,6 +599,8 @@
#define LUA_MAXINTEGER _I64_MAX
#define LUA_MININTEGER _I64_MIN
#define LUA_MAXUNSIGNED _UI64_MAX
#else /* }{ */
#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \
@ -613,7 +635,7 @@
/*
@@ lua_strx2number converts an hexadecimal numeric string to a number.
@@ lua_strx2number converts a hexadecimal numeral to a number.
** In C99, 'strtod' does that conversion. Otherwise, you can
** leave 'lua_strx2number' undefined and Lua will provide its own
** implementation.
@ -631,7 +653,7 @@
/*
@@ lua_number2strx converts a float to an hexadecimal numeric string.
@@ lua_number2strx converts a float to a hexadecimal numeral.
** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that.
** Otherwise, you can leave 'lua_number2strx' undefined and Lua will
** provide its own implementation.
@ -677,7 +699,7 @@
/*
@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point).
** Change that if you do not want to use C locales. (Code using this
** macro must include header 'locale.h'.)
** macro must include the header 'locale.h'.)
*/
#if !defined(lua_getlocaledecpoint)
#define lua_getlocaledecpoint() (localeconv()->decimal_point[0])
@ -718,7 +740,7 @@
** {==================================================================
** Macros that affect the API and must be stable (that is, must be the
** same when you compile Lua and when you compile code that links to
** Lua). You probably do not want/need to change them.
** Lua).
** =====================================================================
*/
@ -813,7 +835,7 @@
#endif
#if defined(_MSC_VER)
#if defined(_MSC_VER) && !defined(__clang__)
#define RAVI_NORETURN __declspec(noreturn)
#define RAVI_INLINE __inline
@ -830,12 +852,6 @@
/* Following cause the first hash lookup to be inlined,
and if value is 2 then the second hash lookup is also inlined. */
#define RAVI_USE_INLINE_SHORTSTR_TGET 1
#define RAVI_USE_LLVM_BRANCH_WEIGHTS 1
/* If following is defined as true then LLVM instructions emitted for arithmetic ops
priority floating point ops, else default is to prioritise integer ops */
#define RAVI_USE_LLVM_ARITH_FLOATPRIORITY 1
/* Enables the 'defer' statement - RAVI extension */
#define RAVI_DEFER_STATEMENT
#endif

@ -54,8 +54,10 @@ LUAMOD_API int (luaopen_package) (lua_State *L);
#define LUA_RAVILIBNAME "ravi"
LUAMOD_API int (raviopen_jit)(lua_State *L);
#define LUA_ASTLIBNAME "ast"
LUAMOD_API int (raviopen_ast_library)(lua_State *L);
#define LUA_RAVICOMPLIBNAME "compiler"
LUAMOD_API int (raviopen_compiler)(lua_State *L);
/* open all previous libraries */
LUALIB_API void (luaL_openlibs) (lua_State *L);

@ -1,289 +0,0 @@
#ifndef ravi_ast_h
#define ravi_ast_h
/*
A parser and syntax tree builder for Ravi. This is work in progress.
Once ready it will be used to create a new byte code generator for Ravi.
The parser will perform following actions:
a) Generate syntax tree
b) Perform type checking (Ravi enhancement)
*/
#define LUA_CORE
#include "lprefix.h"
#include "lua.h"
#include "lcode.h"
#include "ldo.h"
#include "lstring.h"
#include "ltable.h"
#include "lauxlib.h"
#include "ravi_ast.h"
#include "ravi_membuf.h"
#include "allocate.h"
#include "ptrlist.h"
#include <assert.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MAXVARS 125
//////////////////////////
struct lua_symbol_list;
/*
* Userdata object to hold the abstract syntax tree;
* All memory is held by this object. Memory is freed when
* the object is GC collected; or when
* ast_container:release() method is called
* by user.
*/
struct ast_container {
struct allocator ast_node_allocator;
struct allocator ptrlist_allocator;
struct allocator block_scope_allocator;
struct allocator symbol_allocator;
struct ast_node *main_function;
bool killed; /* flag to check if this is already destroyed */
};
struct ast_node;
DECLARE_PTR_LIST(ast_node_list, struct ast_node);
struct var_type;
DECLARE_PTR_LIST(var_type_list, struct var_type);
/* Lua type info. We need to support user defined types too which are known by name */
struct var_type {
ravitype_t type_code;
const TString *type_name; /* type name for user defined types; used to lookup metatable in registry, only set when
type_code is RAVI_TUSERDATA */
};
struct lua_symbol;
DECLARE_PTR_LIST(lua_symbol_list, struct lua_symbol);
struct block_scope;
/* Types of symbols */
enum symbol_type {
SYM_LOCAL,
SYM_UPVALUE,
SYM_GLOBAL, /* Global symbols are never added to a scope so they are always looked up */
SYM_LABEL
};
/* A symbol is a name recognised in Ravi/Lua code*/
struct lua_symbol {
enum symbol_type symbol_type;
struct var_type value_type;
union {
struct {
const TString *var_name; /* name of the variable */
struct block_scope *block; /* NULL if global symbol, as globals are never added to a scope */
} var;
struct {
const TString *label_name;
struct block_scope *block;
} label;
struct {
struct lua_symbol *var; /* variable reference */
struct ast_node *function; /* Where the upvalue lives */
} upvalue;
};
};
struct block_scope {
struct ast_node *function; /* function owning this block - of type FUNCTION_EXPR */
struct block_scope *parent; /* parent block, may belong to parent function */
struct lua_symbol_list *symbol_list; /* symbols defined in this block */
};
enum ast_node_type {
AST_NONE, /* Used when the node doesn't represent an AST such as test_then_block. */
AST_RETURN_STMT,
AST_GOTO_STMT,
AST_LABEL_STMT,
AST_DO_STMT,
AST_LOCAL_STMT,
AST_FUNCTION_STMT,
AST_IF_STMT,
AST_WHILE_STMT,
AST_FORIN_STMT,
AST_FORNUM_STMT,
AST_REPEAT_STMT,
AST_EXPR_STMT, /* Also used for assignment statements */
AST_LITERAL_EXPR,
AST_SYMBOL_EXPR,
AST_Y_INDEX_EXPR, /* [] operator */
AST_FIELD_SELECTOR_EXPR, /* table field access - '.' or ':' operator */
AST_INDEXED_ASSIGN_EXPR, /* table value assign in table constructor */
AST_SUFFIXED_EXPR,
AST_UNARY_EXPR,
AST_BINARY_EXPR,
AST_FUNCTION_EXPR, /* function literal */
AST_TABLE_EXPR, /* table constructor */
AST_FUNCTION_CALL_EXPR
};
/* The parse tree is made up of ast_node objects. Some of the ast_nodes reference the appropriate block
scopes but not all scopes may be referenced. The tree captures Lua syntax tree - i.e. statements such as
while, repeat, and for are captured in the way user uses them and not the way Lua generates code. Potentially
we can have a transformation step to convert to a tree that is more like the code generation */
struct ast_node {
enum ast_node_type type;
union {
struct {
struct ast_node_list *expr_list;
} return_stmt;
struct {
struct lua_symbol *symbol;
} label_stmt;
struct {
const TString *name; /* target label, used to resolve the goto destination */
struct ast_node *label_stmt; /* Initially this will be NULL; set by a separate pass */
} goto_stmt;
struct {
struct lua_symbol_list *var_list;
struct ast_node_list *expr_list;
} local_stmt; /* local declarations */
struct {
struct ast_node_list *var_expr_list; /* Optional var expressions, comma separated */
struct ast_node_list *expr_list; /* Comma separated expressions */
} expression_stmt; /* Also covers assignments */
struct {
struct ast_node *name; /* base symbol to be looked up */
struct ast_node_list *selectors; /* Optional */
struct ast_node *method_name; /* Optional */
struct ast_node *function_expr; /* Function's AST */
} function_stmt;
struct {
struct block_scope *scope; /* The do statement only creates a new scope */
struct ast_node_list *do_statement_list; /* statements in this block */
} do_stmt;
struct {
struct ast_node *condition;
struct block_scope *test_then_scope;
struct ast_node_list *test_then_statement_list; /* statements in this block */
} test_then_block; /* Used internally in if_stmt, not an independent AST node */
struct {
struct ast_node_list *if_condition_list; /* Actually a list of test_then_blocks */
struct block_scope *else_block;
struct ast_node_list *else_statement_list; /* statements in this block */
} if_stmt;
struct {
struct ast_node *condition;
struct block_scope *loop_scope;
struct ast_node_list *loop_statement_list; /* statements in this block */
} while_or_repeat_stmt;
struct {
struct lua_symbol_list *symbols;
struct ast_node_list *expr_list;
struct block_scope *for_body;
struct ast_node_list *for_statement_list; /* statements in this block */
} for_stmt; /* Used for both generic and numeric for loops */
struct {
struct var_type type;
} common_expr; /* To access the type field common to all expr objects */
/* all expr types must be compatible with common_expr */
struct {
struct var_type type;
union {
lua_Integer i;
lua_Number n;
const TString *s;
} u;
} literal_expr;
struct {
struct var_type type;
struct lua_symbol *var;
} symbol_expr;
struct {
struct var_type type;
struct ast_node *expr; /* '[' expr ']' */
} index_expr;
struct {
struct var_type type;
UnOpr unary_op;
struct ast_node *expr;
} unary_expr;
struct {
struct var_type type;
BinOpr binary_op;
struct ast_node *expr_left;
struct ast_node *expr_right;
} binary_expr;
struct {
struct var_type type;
unsigned int is_vararg : 1;
unsigned int is_method : 1;
struct ast_node *parent_function; /* parent function or NULL if main chunk */
struct block_scope *main_block; /* the function's main block */
struct ast_node_list *function_statement_list; /* statements in this block */
struct lua_symbol_list *args; /* arguments, also must be part of the function block's symbol list */
struct ast_node_list *child_functions; /* child functions declared in this function */
struct lua_symbol_list *upvalues; /* List of upvalues */
struct lua_symbol_list *locals; /* List of locals */
} function_expr; /* a literal expression whose result is a value of type function */
struct {
struct var_type type;
struct ast_node *
index_expr; /* If NULL means this is a list field with next available index, else specfies index expression */
struct ast_node *value_expr;
} indexed_assign_expr; /* Assign values in table constructor */
struct {
struct var_type type;
struct ast_node_list *expr_list;
} table_expr; /* table constructor expression */
struct {
struct var_type type;
struct ast_node *primary_expr;
struct ast_node_list *suffix_list;
} suffixed_expr;
struct {
/* Note that in Ravi the results from a function call must be type asserted during assignment to variables.
* This is not explicit in the AST but is required to ensure that function return values do not
* overwrite the type of the variables in an inconsistent way.
*/
struct var_type type;
TString *method_name; /* Optional method_name */
struct ast_node_list *arg_list; /* Call arguments */
} function_call_expr;
};
};
#define set_typecode(vt, t) \
(vt).type_code = t
#define set_type(vt, t) \
(vt).type_code = t, \
(vt).type_name = NULL
#define set_typename(vt, t, name) \
(vt).type_code = t, \
(vt).type_name = (name)
#define is_type_same(a, b) ((a).type_code == (b).type_code && (a).type_name == (b).type_name)
#define copy_type(a, b) \
(a).type_code = (b).type_code, \
(a).type_name = (b).type_name
struct parser_state {
LexState *ls;
struct ast_container *container;
struct ast_node *current_function;
struct block_scope *current_scope;
};
LUAMOD_API int raviopen_ast_library(lua_State *L);
void raviA_print_ast_node(membuff_t *buf, struct ast_node *node, int level); /* output the AST structure recusrively */
void raviA_ast_typecheck(struct ast_container *container); /* Perform type checks and assign types to AST */
#endif

@ -1,120 +0,0 @@
/******************************************************************************
* Copyright (C) 2015 Dibyendu Majumdar
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
#ifndef RAVI_LLVM_H
#define RAVI_LLVM_H
#ifdef USE_LLVM
#include "llvm/Config/llvm-config.h"
#if (LLVM_VERSION_MAJOR < 3 || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5 || LLVM_VERSION_MAJOR == 7)
#error Unsupported LLVM version
#endif
#if LLVM_VERSION_MAJOR >= 5
#define USE_ORC_JIT 1
#else
#define USE_ORC_JIT 0
#endif
#if LLVM_VERSION_MAJOR >= 8 && !defined(_WIN32)
#define USE_ORCv2_JIT 0
#else
#define USE_ORCv2_JIT 0
#endif
#if LLVM_VERSION_MAJOR >= 9
#define USE_ORCv2_JIT 0
#endif
// In lua.c we include this just to get version numbers
// We cannot have C++ headers in that case
#ifdef __cplusplus
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/Metadata.h"
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7
#include "llvm/PassManager.h"
#else
#include "llvm/IR/LegacyPassManager.h"
#endif
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/FormattedStream.h"
#if USE_ORC_JIT || USE_ORCv2_JIT
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Support/Error.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Scalar/GVN.h"
#if LLVM_VERSION_MAJOR >= 8
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#endif
#endif
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <memory>
#include <string>
#include <cstdio>
#include <vector>
#endif //__cplusplus
#endif //USE_LLVM
#endif

File diff suppressed because it is too large Load Diff

@ -1,51 +0,0 @@
/******************************************************************************
* Copyright (C) 2015-2020 Dibyendu Majumdar
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
#ifndef RAVI_OMRJIT_H
#define RAVI_OMRJIT_H
#include <ravi_jitshared.h>
#ifdef USE_OMRJIT
#include "dmr_c.h"
struct ravi_State {
JIT_ContextRef jit;
unsigned long long id; // counter to generate function names
unsigned int verbosity_ : 3;
unsigned int auto_ : 1; /* Should we auto compile what we can? */
unsigned int enabled_ : 1; /* is JIT enabled */
unsigned int opt_level_ : 3; /* optimization level */
unsigned int tracehook_enabled_ : 1; /* enable calls to luaG_traceexec() at every bytecode, this is expensive ! */
unsigned int validation_ : 1; /* Enable extra validation such as IL verification */
unsigned int compiling_; /* flag to help avoid recursion */
int min_code_size_; /* min code size for compilation */
int min_exec_count_; /* min execution count for compilation */
};
#ifdef __cplusplus
};
#endif
#endif /* USE_OMRJIT */
#endif /* RAVI_OMRJIT_H */

@ -1,42 +0,0 @@
LUA=$1
if [ "$LUA" = "" ]
then
echo "Please pass path to Lua"
exit 1
fi
# Run the interpreter tests first
$LUA -e"_port=true" all.lua
if [ $? != 0 ]
then
echo "all.lua interpreted failed"
exit 1
fi
# Run tests in JIT mode without support for the line hook
$LUA -e"_port=true; ravi.auto(true,1)" all.lua
if [ $? != 0 ]
then
echo "all.lua compiled without tracehook failed"
exit 1
fi
# Run tests in JIT mode with suppor for the line hook
$LUA -e"_port=true; ravi.tracehook(true); ravi.auto(true,1)" all.lua
if [ $? != 0 ]
then
echo "all.lua compiled with tracehook failed"
exit 1
fi
# Run tests in partial JIT mode, with line hook
$LUA -e"_port=true; ravi.tracehook(true); ravi.auto(true)" all.lua
if [ $? != 0 ]
then
echo "all.lua partially compiled with tracehook failed"
exit 1
fi
cd ../ravi-tests
. ./run_tests.sh "$LUA"
cd -

@ -1,26 +0,0 @@
LUA=$1
if [ "$LUA" = "" ]
then
echo "Please pass path to Lua"
exit 1
fi
# Run the interpreter tests first
$LUA -e"_port=true" all.lua
if [ $? != 0 ]
then
echo "all.lua interpreted failed"
exit 1
fi
# Run tests in JIT mode without support for the line hook
$LUA -e"_port=true; ravi.auto(true)" all.lua
if [ $? != 0 ]
then
echo "all.lua partially compiled with tracehook failed"
exit 1
fi
cd ../ravi-tests
. ./run_tests.sh "$LUA"
cd -

@ -1,18 +1,11 @@
project(mir)
enable_language(C)
cmake_minimum_required(VERSION 3.12)
project(mir LANGUAGES C)
message(STATUS "OS type is ${CMAKE_SYSTEM_NAME}")
message(STATUS "System processor is ${CMAKE_HOST_SYSTEM_PROCESSOR}")
message(STATUS "Build type is ${CMAKE_BUILD_TYPE}")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
set(TARGET x86_64)
else()
message(FATAL "Unsupported platform")
endif()
set(MIR_HEADERS
set(MIR_HEADERS
mir.h
mir-gen.h
mir-varr.h
@ -31,18 +24,48 @@ set(C2MIR_SRCS
c2mir/c2mir.c
)
set(LIBS dl)
set(LIBS ${CMAKE_DL_LIBS})
if (WIN32)
set(MIR_BUILD_TYPE STATIC)
else()
set(MIR_BUILD_TYPE SHARED)
endif()
add_definitions(-D${TARGET})
add_definitions(-DMIR_IO)
add_definitions(-DMIR_SCAN)
#add_definitions(-DMIR_NO_IO=0)
#add_definitions(-DMIR_NO_SCAN=1)
set_property(SOURCE ${MIR_SRCS} ${C2MIR_SRCS} ${MIR_JIT_SRCS}
APPEND
PROPERTY COMPILE_DEFINITIONS "MIR_NO_IO=0;MIR_NO_SCAN=1;MIR_NO_INTERP=1")
include_directories(".")
include_directories("./c2mir")
if ($ENV{CLION_IDE})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/c2mir)
endif()
include(CheckCCompilerFlag)
check_c_compiler_flag("-fsigned-char" COMPILER_OPT_SIGNED_CHAR_SUPPORTED)
if (COMPILER_OPT_SIGNED_CHAR_SUPPORTED AND NOT CMAKE_C_FLAGS MATCHES "-fsigned-char")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsigned-char")
endif()
check_c_compiler_flag("-fno-tree-sra" COMPILER_OPT_NO_TREE_SRA_SUPPORTED)
if (COMPILER_OPT_NO_TREE_SRA_SUPPORTED AND NOT CMAKE_C_FLAGS MATCHES "-fno-tree-sra")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-tree-sra")
endif()
check_c_compiler_flag("-fno-ipa-cp-clone" COMPILER_OPT_NO_IPA_CP_CLONE_SUPPORTED)
if (COMPILER_OPT_NO_IPA_CP_CLONE_SUPPORTED AND NOT CMAKE_C_FLAGS MATCHES "-fno-ipa-cp-clone")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-ipa-cp-clone")
endif()
add_library(c2mir
include(GNUInstallDirs)
add_library(c2mir ${MIR_BUILD_TYPE}
${MIR_HEADERS}
${MIR_SRCS}
${C2MIR_SRCS})
target_link_libraries(c2mir ${LIBS})
target_include_directories(c2mir PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/c2mir)
set_property(TARGET c2mir PROPERTY C_STANDARD 11)
install(TARGETS c2mir
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT mir_Runtime
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT mir_Development
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT mir_Runtime)

@ -43,11 +43,17 @@
their value
* `MIR_T_F` and `MIR_T_D` -- IEEE single and double precision floating point values
* `MIR_T_LD` - long double values. It is machine-dependent and can be IEEE double, x86 80-bit FP,
or IEEE quad precision FP values
or IEEE quad precision FP values. If it is the same as double, the double type will be used instead.
So please don't expect machine-independence of MIR code working with long double values
* `MIR_T_P` -- pointer values. Depending on the target pointer value is actually 32-bit or 64-bit integer value
* `MIR_T_BLK` .. `MIR_T_BLK + MIR_BLK_NUM - 1` -- block data with given case. This type can be used only
for argument of function. Different case numbers can denote different ways to pass the block data
on a particular target to implement the target call ABI. Currently there are 5 block
types (`MIR_BLK_NUM = 5`)
* `MIR_T_RBLK` -- return block data. This type can be used only for argument of function
* MIR textual representation of the types are correspondingly `i8`,
`u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `f`, `d`, `p`,
and `v`
`u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `f`, `d`, `ld`, `p`,
and `blk`
* Function `int MIR_int_type_p (MIR_type_t t)` returns TRUE if given type is an integer one (it includes pointer type too)
* Function `int MIR_fp_type_p (MIR_type_t t)` returns TRUE if given type is a floating point type
@ -78,6 +84,7 @@
only one result, have no arguments, not use any call or any instruction with memory
* The expression function is called during linking and its result is used to initialize the data
* **Memory segment**: `MIR_bss_item` with optional name (`MIR_item_t MIR_new_bss (MIR_context_t ctx, const char *name, size_t len)`)
* Long double data item is changed to double one, if long double coincides with double for given target or ABI
* Names of MIR functions, imports, and prototypes should be unique in a module
* API functions `MIR_output_item (MIR_context_t ctx, FILE *f, MIR_item_t item)`
and `MIR_output_module (MIR_context_t ctx, FILE *f, MIR_module_t module)` output item or module
@ -96,6 +103,8 @@
* A variable should have an unique name in the function
* A variable is represented by a structure of type `MIR_var_t`
* The structure contains variable name and its type
* The structure contains also type size for variable of block types (`MIR_T_BLK`..`MIR_T_BLK + MIR_BLK_NUM - 1`)
or `MIR_T_RBLK` type
* MIR function with its arguments is created through API function `MIR_item_t MIR_new_func (MIR_context_t ctx, const
char *name, size_t nres, MIR_type_t *res_types, size_t nargs, ...)`
or function `MIR_item_t MIR_new_func_arr (MIR_context_t ctx, const char *name, size_t nres, MIR_type_t *res_types, size_t nargs, MIR_var_t *arg_vars)`
@ -119,6 +128,12 @@
{<insn>}
endfun
```
* Textual presentation of block type argument in `func` has form `blk:<size>(<var_name>)`.
The corresponding argument in `call` insn should have analogous form
`blk:<the same size>(<local var name containing address of passed block data>)`
* Block data are passed by value. How they are exactly passed is machine-defined:
* they are always passed on stack for x86-64, aarch64, and s390x
* they can (partially) passed through registers and on stack for ppc64
* Non-argument function variables are created through API function
`MIR_reg_t MIR_new_func_reg (MIR_context_t ctx, MIR_func_t func, MIR_type_t type, const char *name)`
* The only permitted integer type for the variable is `MIR_T_I64` (or MIR_T_U64???)
@ -139,7 +154,9 @@
`MIR_op_t MIR_new_int_op (MIR_context_t ctx, int64_t v)` and `MIR_op_t MIR_new_uint_op (MIR_context_t ctx, uint64_t v)`
* In MIR text they are represented the same way as C integer numbers (e.g. octal, decimal, hexadecimal ones)
* **Float, double or long double value operands** created through API functions `MIR_op_t MIR_new_float_op (MIR_context_t ctx, float v)`,
`MIR_op_t MIR_new_double_op (MIR_context_t ctx, double v)`, and `MIR_op_t MIR_new_ldouble_op (MIR_context_t ctx, long double v)`
`MIR_op_t MIR_new_double_op (MIR_context_t ctx, double v)`,
and `MIR_op_t MIR_new_ldouble_op (MIR_context_t ctx, long double v)`.
Long double operand is changed to double one when long double coincides with double for given target or ABI
* In MIR text they are represented the same way as C floating point numbers
* **String operands** created through API functions `MIR_op_t MIR_new_str_op (MIR_context_t ctx, MIR_str_t str)`
* In MIR text they are represented by `typedef struct MIR_str {size_t len; const char *s;} MIR_str_t`
@ -184,6 +201,7 @@
* You can not use `MIR_new_insn` for the creation of call and ret insns as these insns have a variable number of operands.
To create such insns you should use `MIR_new_insn_arr` or special functions
`MIR_insn_t MIR_new_call_insn (MIR_context_t ctx, size_t nops, ...)` and `MIR_insn_t MIR_new_ret_insn (MIR_context_t ctx, size_t nops, ...)`
* Long double insns are changed by double ones if long double coincides with double for given target or ABI
* You can get insn name and number of insn operands through API functions
`const char *MIR_insn_name (MIR_context_t ctx, MIR_insn_code_t code)` and `size_t MIR_insn_nops (MIR_context_t ctx, MIR_insn_t insn)`
* You can add a created insn at the beginning or end of function insn list through API functions
@ -386,7 +404,7 @@
* The first insn saves the stack pointer in the operand
* The second insn restores stack pointer from the operand
### MIR_VA_START, MIR_VA_ARG, and MIR_VA_END insns
### MIR_VA_START, MIR_VA_ARG, MIR_VA_BLOCK_ARG, and MIR_VA_END insns
* These insns are only for variable number arguments functions
* `MIR_VA_START` and `MIR_VA_END` have one input operand, an address
of va_list structure (see C stdarg.h for more details). Unlike C
@ -394,6 +412,9 @@
* `MIR_VA_ARG` takes va_list and any memory operand and returns
address of the next argument in the 1st insn operand. The memory
operand type defines the type of the argument
* `MIR_VA_BLOCK_ARG` takes result address, va_list address, integer operand (size),
and block type (case) number and moves the next argument passed as block of given
size and type to the result address
* va_list operand can be memory with undefined type. In this case
address of the va_list is not in the memory but is the
memory address
@ -401,7 +422,7 @@
## MIR API example
* The following code on C creates MIR analog of C code
`int64_t loop (int64_t arg1) {int64_t count = 0; while (count < arg1) count++; return count;}`
```
```c
MIR_module_t m = MIR_new_module (ctx, "m");
MIR_item_t func = MIR_new_func (ctx, "loop", MIR_T_I64, 1, MIR_T_I64, "arg1");
MIR_reg_t COUNT = MIR_new_func_reg (ctx, func->u.func, MIR_T_I64, "count");
@ -423,9 +444,11 @@
MIR_finish_module (ctx);
```
## MIR text example
## MIR text examples
```
* Sieve of eratosthenes:
```mir
m_sieve: module
export sieve
sieve: func i32, i32:N
@ -466,6 +489,29 @@ ex100: func v
endmodule
```
* Example of block arguments and `va_stack_arg`
```mir
m0: module
f_p: proto i64, 16:blk(a), ...
f: func i64, 16:blk(a), ...
local i64:r, i64:va, i64:a2
alloca va, 32 # allocate enough space va_list
va_start va
va_stack_arg a2, va, 16 # get address of the 2nd blk arg
add r, i64:0(a), i64:8(a2)
ret r
main: func
local i64:a, i64:r
alloca a, 16
mov i64:0(a), 42
mov i64:8(a), 24
call f_p, f, r, blk:16(a), blk:16(a)
ret r
endfunc
endmodule
```
## Other MIR API functions
* MIR API can find a lot of errors. They are reported through a
error function of type `void (*MIR_error_func_t) (MIR_context ctx, MIR_error_type_t
@ -564,17 +610,23 @@ ex100: func v
works only on the same targets as MIR generator
# MIR generator (file mir-gen.h)
* Before use of MIR generator you should initialize it by API function `MIR_gen_init (MIR_context ctx)`
* API function `MIR_gen_finish (MIR_context ctx)` should be called last after any generator usage.
It frees all internal generator data
* API function `void *MIR_gen (MIR_context ctx, MIR_item_t func_item)` generates machine code of given MIR function
and returns an address to call it. You can call the code as usual C function by using this address
as the called function address
* API function `void MIR_gen_set_debug_file (MIR_context_t ctx, FILE *f)` sets up MIR generator debug file to `f`.
* Before use of MIR generator for given context you should initialize it by API function
`MIR_gen_init (MIR_context ctx, int gens_num)`. `gens_num` defines how many generator instances you need.
Each generator instance can be used in a different thread to compile different MIR functions from the same context.
If you pass a negative or zero number `gens_num`, it will have the same effect as value `1`
* API function `MIR_gen_finish (MIR_context ctx)` frees all internal generator data (and its instances) for the context.
If you want to generate code for the context again after the `MIR_gen_finish` call, you should call
`MIR_gen_init` again first
* API function `void *MIR_gen (MIR_context ctx, int gen_num, MIR_item_t func_item)` generates machine code
of given MIR function in generator instance `gen_num` and returns an address to call it. You can call
the code as usual C function by using this address as the called function address.
`gen_num` should be a number in the range `0` .. `gens_num - 1` from corresponding `MIR_gen_init`
* API function `void MIR_gen_set_debug_file (MIR_context_t ctx, int gen_num, FILE *f)` sets up MIR generator
debug file to `f` for generator instance `gen_num`.
If it is not NULL a lot of debugging and optimization information will be output to the file. It is useful mostly
for MIR developers
* API function `void MIR_gen_set_optimize_level (MIR_context_t ctx, unsigned int level)` sets up optimization
level for MIR generator:
* API function `void MIR_gen_set_optimize_level (MIR_context_t ctx, int gen_num, unsigned int level)` sets up optimization
level for MIR generator instance `gen_num`:
* `0` means only register allocator and machine code generator work
* `1` means additional code selection task. On this level MIR generator creates more compact and faster
code than on zero level with practically on the same speed

@ -3,3 +3,5 @@ project. Following changes have been made:
* A CMake build script added to create a library
* Unused files / tests have been removed to avoid clutter
Last update: 7th Jan 2021

@ -0,0 +1,98 @@
/* This file is a part of MIR project.
Copyright (C) 2018-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
aarch64 call ABI target specific code.
*/
typedef int target_arg_info_t;
static void target_init_arg_vars (c2m_ctx_t c2m_ctx, target_arg_info_t *arg_info) {}
static int target_return_by_addr_p (c2m_ctx_t c2m_ctx, struct type *ret_type) {
return ((ret_type->mode == TM_STRUCT || ret_type->mode == TM_UNION)
&& type_size (c2m_ctx, ret_type) > 2 * 8);
}
static int reg_aggregate_size (c2m_ctx_t c2m_ctx, struct type *type) {
int size;
if (type->mode != TM_STRUCT && type->mode != TM_UNION) return -1;
return (size = type_size (c2m_ctx, type)) <= 2 * 8 ? size : -1;
}
static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type,
target_arg_info_t *arg_info, VARR (MIR_type_t) * res_types,
VARR (MIR_var_t) * arg_vars) {
MIR_var_t var;
int size;
if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0) {
simple_add_res_proto (c2m_ctx, ret_type, arg_info, res_types, arg_vars);
return;
}
if (size == 0) return;
VARR_PUSH (MIR_type_t, res_types, MIR_T_I64);
if (size > 8) VARR_PUSH (MIR_type_t, res_types, MIR_T_I64);
}
static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type,
target_arg_info_t *arg_info, size_t call_arg_area_offset) {
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
MIR_context_t ctx = c2m_ctx->ctx;
int size;
if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0)
return simple_add_call_res_op (c2m_ctx, ret_type, arg_info, call_arg_area_offset);
if (size == 0) return -1;
VARR_PUSH (MIR_op_t, call_ops,
MIR_new_reg_op (ctx, get_new_temp (c2m_ctx, MIR_T_I64).mir_op.u.reg));
if (size > 8)
VARR_PUSH (MIR_op_t, call_ops,
MIR_new_reg_op (ctx, get_new_temp (c2m_ctx, MIR_T_I64).mir_op.u.reg));
return size <= 8 ? 1 : 2;
}
static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res,
MIR_insn_t call, size_t call_ops_start) {
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
int size;
if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0)
return simple_gen_post_call_res_code (c2m_ctx, ret_type, res, call, call_ops_start);
if (size != 0)
gen_multiple_load_store (c2m_ctx, ret_type, &VARR_ADDR (MIR_op_t, call_ops)[call_ops_start + 2],
res.mir_op, FALSE);
return res;
}
static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res) {
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
int i, size;
if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0) {
simple_add_ret_ops (c2m_ctx, ret_type, res);
return;
}
assert (res.mir_op.mode == MIR_OP_MEM && VARR_LENGTH (MIR_op_t, ret_ops) == 0 && size <= 2 * 8);
for (i = 0; size > 0; size -= 8, i++)
VARR_PUSH (MIR_op_t, ret_ops, get_new_temp (c2m_ctx, MIR_T_I64).mir_op);
gen_multiple_load_store (c2m_ctx, ret_type, VARR_ADDR (MIR_op_t, ret_ops), res.mir_op, TRUE);
}
static MIR_type_t target_get_blk_type (c2m_ctx_t c2m_ctx, struct type *arg_type) {
return MIR_T_BLK; /* one BLK is enough */
}
static void target_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
target_arg_info_t *arg_info, VARR (MIR_var_t) * arg_vars) {
simple_add_arg_proto (c2m_ctx, name, arg_type, arg_info, arg_vars);
}
static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type,
target_arg_info_t *arg_info, op_t arg) {
simple_add_call_arg_op (c2m_ctx, arg_type, arg_info, arg);
}
static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
decl_t param_decl, target_arg_info_t *arg_info) {
return FALSE;
}

@ -1,13 +1,18 @@
/* This file is a part of MIR project.
Copyright (C) 2020 Vladimir Makarov <vmakarov.gcc@gmail.com>.
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
*/
#include "../mirc.h"
#include "mirc-aarch64-linux.h"
#include "mirc_aarch64_linux.h"
static const char *standard_includes[] = {mirc, aarch64_mirc};
#include "mirc_aarch64_float.h"
#include "mirc_aarch64_limits.h"
#include "mirc_aarch64_stdarg.h"
#include "mirc_aarch64_stdint.h"
#include "mirc_aarch64_stddef.h"
static const char *standard_include_dirs[] = {"include/mirc/", "include/mirc/aarch64/"};
static string_include_t standard_includes[]
= {{NULL, mirc}, {NULL, aarch64_mirc}, TARGET_STD_INCLUDES};
#define MAX_ALIGNMENT 16

@ -1,5 +1,5 @@
/* This file is a part of MIR project.
Copyright (C) 2020 Vladimir Makarov <vmakarov.gcc@gmail.com>.
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
*/
#include <stdint.h>
@ -28,12 +28,17 @@ typedef uint16_t mir_ushort;
typedef uint32_t mir_uint;
typedef uint64_t mir_ulong;
typedef uint64_t mir_ullong;
typedef uint32_t mir_wchar;
typedef uint16_t mir_char16;
typedef uint32_t mir_char32;
#define MIR_UCHAR_MAX UINT8_MAX
#define MIR_USHORT_MAX UINT16_MAX
#define MIR_UINT_MAX UINT32_MAX
#define MIR_ULONG_MAX UINT64_MAX
#define MIR_ULLONG_MAX UINT64_MAX
#define MIR_WCHAR_MIN 0
#define MIR_WCHAR_MAX UINT32_MAX
typedef mir_schar mir_char;
#define MIR_CHAR_MIN MIR_SCHAR_MIN

@ -0,0 +1,60 @@
/* This file is a part of MIR project.
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
*/
/* See C11 5.2.4.2.2 */
static char float_str[]
= "#ifndef __FLOAT_H\n"
"#define __FLOAT_H\n"
"\n"
"#define FLT_RADIX 2\n"
"\n"
"#define FLT_MANT_DIG 24\n"
"#define DBL_MANT_DIG 53\n"
"#define LDBL_MANT_DIG DBL_MANT_DIG\n"
"\n"
"#define FLT_DECIMAL_DIG 9\n"
"#define DBL_DECIMAL_DIG 17\n"
"#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG\n"
"#define FLT_DIG FLT_DECIMAL_DIG\n"
"#define DBL_DIG DBL_DECIMAL_DIG\n"
"#define LDBL_DIG LDBL_DECIMAL_DIG\n"
"\n"
"#define DECIMAL_DIG LDBL_DECIMAL_DIG\n"
"\n"
"#define FLT_MIN_EXP -125\n"
"#define DBL_MIN_EXP -1021\n"
"#define LDBL_MIN_EXP DBL_MIN_EXP\n"
"\n"
"#define FLT_MIN_10_EXP -37\n"
"#define DBL_MIN_10_EXP -307\n"
"#define LDBL_MIN_10_EXP DBL_MIN_10_EXP\n"
"\n"
"#define FLT_MAX_EXP 128\n"
"#define DBL_MAX_EXP 1024\n"
"#define LDBL_MAX_EXP DBL_MAX_EXP\n"
"\n"
"#define FLT_MAX_10_EXP 38\n"
"#define DBL_MAX_10_EXP 308\n"
"#define LDBL_MAX_10_EXP DBL_MAX_10_EXP\n"
"\n"
"#define FLT_MAX 0x1.fffffep+127\n"
"#define DBL_MAX 0x1.fffffffffffffp+1023\n"
"#define LDBL_MAX DBL_MAX\n"
"\n"
"#define FLT_EPSILON 0x1p-23\n"
"#define DBL_EPSILON 0x1p-52\n"
"#define LDBL_EPSILON DBL_EPSILON\n"
"\n"
"#define FLT_MIN 0x1p-126\n"
"#define DBL_MIN 0x1p-1022\n"
"#define LDBL_MIN DBL_MIN\n"
"\n"
"#define FLT_TRUE_MIN 0x1p-149\n"
"#define DBL_TRUE_MIN 0x0.0000000000001p-1022\n"
"#define LDBL_TRUE_MIN DBL_TRUE_MIN\n"
"\n"
"#define FLT_EVAL_METHOD 0\n"
"#define FLT_ROUNDS 1 /* round to the nearest */\n"
"\n"
"#endif /* #ifndef __FLOAT_H */\n";

@ -0,0 +1,38 @@
/* This file is a part of MIR project.
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
*/
/* See 5.2.4.2 */
static char limits_str[]
= "#ifndef __LIMITS_H\n"
"#define __LIMITS_H\n"
"\n"
"#define CHAR_BIT 8\n"
"\n"
"#define SCHAR_MIN (-SCHAR_MAX - 1)\n"
"#define SCHAR_MAX 127\n"
"#define UCHAR_MAX (SCHAR_MAX * 2 + 1)\n"
"\n"
"#define MB_LEN_MAX 1\n"
"\n"
"#define SHRT_MIN (-SHRT_MAX - 1)\n"
"#define SHRT_MAX 32767\n"
"#define USHRT_MAX (SHRT_MAX * 2 + 1)\n"
"\n"
"#define INT_MIN (-INT_MAX - 1)\n"
"#define INT_MAX 2147483647\n"
"#define UINT_MAX (INT_MAX * 2u + 1u)\n"
"\n"
"#define LONG_MIN (-LONG_MAX - 1l)\n"
"#define LONG_MAX 9223372036854775807l\n"
"#define ULONG_MAX (LONG_MAX * 2ul + 1ul)\n"
"\n"
"#define LLONG_MIN LONG_MIN\n"
"#define LLONG_MAX LONG_MAX\n"
"#define ULLONG_MAX ULONG_MAX\n"
"\n"
"/* signed char by default */\n"
"#define CHAR_MIN SCHAR_MIN\n"
"#define CHAR_MAX SCHAR_MAX\n"
"\n"
"#endif /* #ifndef __LIMITS_H */\n";

@ -1,5 +1,5 @@
/* This file is a part of MIR project.
Copyright (C) 2020 Vladimir Makarov <vmakarov.gcc@gmail.com>.
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
*/
static char aarch64_mirc[]

@ -0,0 +1,27 @@
/* This file is a part of MIR project.
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
*/
static char stdarg_str[]
= "#ifndef __STDARG_H\n"
"#define __STDARG_H\n"
"\n"
"typedef struct {\n"
" void *__stack;\n"
" void *__gr_top;\n"
" void *__vr_top;\n"
" int __gr_offs;\n"
" int __vr_offs;\n"
"} va_list;\n"
"\n"
"#define va_start(ap, param) __builtin_va_start (ap)\n"
"#define va_arg(ap, type) __builtin_va_arg(ap, (type *) 0)\n"
"#define va_end(ap) 0\n"
"#define va_copy(dest, src) ((dest)[0] = (src)[0])\n"
"\n"
"/* For standard headers of a GNU system: */\n"
"#ifndef __GNUC_VA_LIST\n"
"#define __GNUC_VA_LIST 1\n"
"#endif\n"
"typedef va_list __gnuc_va_list;\n"
"#endif /* #ifndef __STDARG_H */\n";

@ -0,0 +1,19 @@
/* This file is a part of MIR project.
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
*/
/* See C11 7.19 */
static char stddef_str[]
= "#ifndef __STDDEF_H\n"
"#define __STDDEF_H\n"
"\n"
"typedef long ptrdiff_t;\n"
"typedef unsigned long size_t;\n"
"typedef long double max_align_t;\n"
"typedef unsigned int wchar_t;\n"
"\n"
"#define NULL ((void *) 0)\n"
"\n"
"#define offsetof(type, member_designator) ((size_t) & ((type *) 0)->member_designator)\n"
"\n"
"#endif /* #ifndef __STDDEF_H */\n";

@ -0,0 +1,130 @@
/* This file is a part of MIR project.
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
*/
/* See C11 7.20 */
static char stdint_str[]
= "#ifndef _STDINT_H\n"
"#define _STDINT_H 1\n"
"\n"
"#ifndef __int8_t_defined\n"
"#define __int8_t_defined\n"
"typedef signed char int8_t;\n"
"#endif\n"
"typedef short int int16_t;\n"
"typedef int int32_t;\n"
"typedef long int int64_t;\n"
"\n"
"typedef unsigned char uint8_t;\n"
"typedef unsigned short int uint16_t;\n"
"typedef unsigned int uint32_t;\n"
"typedef unsigned long int uint64_t;\n"
"\n"
"typedef signed char int_least8_t;\n"
"typedef short int int_least16_t;\n"
"typedef int int_least32_t;\n"
"typedef long int int_least64_t;\n"
"\n"
"typedef unsigned char uint_least8_t;\n"
"typedef unsigned short int uint_least16_t;\n"
"typedef unsigned int uint_least32_t;\n"
"typedef unsigned long int uint_least64_t;\n"
"\n"
"typedef signed char int_fast8_t;\n"
"typedef long int int_fast16_t;\n"
"typedef long int int_fast32_t;\n"
"typedef long int int_fast64_t;\n"
"\n"
"typedef unsigned char uint_fast8_t;\n"
"typedef unsigned long int uint_fast16_t;\n"
"typedef unsigned long int uint_fast32_t;\n"
"typedef unsigned long int uint_fast64_t;\n"
"\n"
"#define __intptr_t_defined\n"
"typedef long int intptr_t;\n"
"typedef unsigned long int uintptr_t;\n"
"\n"
"typedef long int intmax_t;\n"
"typedef unsigned long int uintmax_t;\n"
"\n"
"#define __INT64_C(c) c##L\n"
"#define __UINT64_C(c) c##UL\n"
"\n"
"#define INT8_MIN (-128)\n"
"#define INT16_MIN (-32768)\n"
"#define INT32_MIN (-2147483648)\n"
"#define INT64_MIN (-9223372036854775808l)\n"
"\n"
"#define INT8_MAX (127)\n"
"#define INT16_MAX (32767)\n"
"#define INT32_MAX (2147483647)\n"
"#define INT64_MAX (9223372036854775807l)\n"
"\n"
"#define UINT8_MAX (255)\n"
"#define UINT16_MAX (65535)\n"
"#define UINT32_MAX (4294967295u)\n"
"#define UINT64_MAX (18446744073709551615ul)\n"
"\n"
"#define INT_LEAST8_MIN (-128)\n"
"#define INT_LEAST16_MIN (-32768)\n"
"#define INT_LEAST32_MIN (-2147483648)\n"
"#define INT_LEAST64_MIN (-9223372036854775808L)\n"
"\n"
"#define INT_LEAST8_MAX (127)\n"
"#define INT_LEAST16_MAX (32767)\n"
"#define INT_LEAST32_MAX (2147483647)\n"
"#define INT_LEAST64_MAX (9223372036854775807L)\n"
"\n"
"#define UINT_LEAST8_MAX (255)\n"
"#define UINT_LEAST16_MAX (65535)\n"
"#define UINT_LEAST32_MAX (4294967295U)\n"
"#define UINT_LEAST64_MAX (18446744073709551615UL)\n"
"\n"
"#define INT_FAST8_MIN (-128)\n"
"#define INT_FAST16_MIN (-9223372036854775808L)\n"
"#define INT_FAST32_MIN (-9223372036854775808L)\n"
"#define INT_FAST64_MIN (-9223372036854775808L)\n"
"\n"
"#define INT_FAST8_MAX (127)\n"
"#define INT_FAST16_MAX (9223372036854775807L)\n"
"#define INT_FAST32_MAX (9223372036854775807L)\n"
"#define INT_FAST64_MAX (9223372036854775807L)\n"
"\n"
"#define UINT_FAST8_MAX (255)\n"
"#define UINT_FAST16_MAX (18446744073709551615UL)\n"
"#define UINT_FAST32_MAX (18446744073709551615UL)\n"
"#define UINT_FAST64_MAX (18446744073709551615UL)\n"
"\n"
"#define INTPTR_MIN (-9223372036854775808L)\n"
"#define INTPTR_MAX (9223372036854775807L)\n"
"#define UINTPTR_MAX (18446744073709551615UL)\n"
"\n"
"#define INTMAX_MIN (-9223372036854775808L)\n"
"#define INTMAX_MAX (9223372036854775807L)\n"
"#define UINTMAX_MAX (18446744073709551615UL)\n"
"\n"
"#define PTRDIFF_MIN (-9223372036854775808L)\n"
"#define PTRDIFF_MAX (9223372036854775807L)\n"
"\n"
"#define SIZE_MAX (18446744073709551615UL)\n"
"\n"
"/* For signed wchar_t and wint_t: */\n"
"#define WCHAR_MIN INT32_MIN\n"
"#define WCHAR_MAX INT32_MAX\n"
"#define WINT_MIN WCHAR_MIN\n"
"#define WINT_MAX WCHAR_MAX\n"
"\n"
"#define INT8_C(value) value\n"
"#define INT16_C(value) value\n"
"#define INT32_C(value) value\n"
"#define INT64_C(value) value##L\n"
"\n"
"#define UINT8_C(value) value\n"
"#define UINT16_C(value) value\n"
"#define UINT32_C(value) value##U\n"
"#define UINT64_C(value) value##UL\n"
"\n"
"#define INTMAX_C(value) value##L\n"
"#define UINTMAX_C(value) value##UL\n"
"\n"
"#endif /* #ifndef _STDINT_H */\n";

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save