Dibyendu Majumdar 4 years ago
parent 5834e4c78f
commit 352f03ad61

@ -5,21 +5,14 @@ project(Ravi VERSION 1.0.4 LANGUAGES C CXX)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
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)
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)")
set(MIR_JIT ON)
@ -33,7 +26,6 @@ if (MIR_JIT)
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 ()
@ -72,24 +64,9 @@ set(MIR_HEADERS mir/mir.h mir/mir-gen.h mir/mir-varr.h mir/mir-dlist.h mir/mir-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)
file(GLOB RAVI_HEADERS "${PROJECT_SOURCE_DIR}/include/*.h")
@ -116,7 +93,6 @@ if (COMPILER_OPT_NO_STACK_PROTECTOR_SUPPORTED AND NOT CMAKE_C_FLAGS MATCHES "-fn
endif()
set(EMBEDDED_DMRC ON)
if (LLVM_JIT)
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
@ -135,63 +111,12 @@ if (LLVM_JIT)
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}
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})
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}
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}"
)
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}
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})
@ -206,23 +131,8 @@ else ()
endif ()
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})
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})
endif ()
@ -303,11 +213,8 @@ add_library(${LIBRAVI_NAME} ${LIBRAVI_BUILD_TYPE}
${RAVI_HEADERS}
${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})
${JIT_SRCS})
target_link_libraries(${LIBRAVI_NAME} ${EXTRA_LIBRARIES} ${LLVM_LIBS} ${MIRJIT_LIBRARIES})
# Main Ravi executable
add_executable(ravi ${LUA_CMD_SRCS})
@ -318,9 +225,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)
@ -353,12 +257,6 @@ if (LLVM_JIT)
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)
set_property(
TARGET ${LIBRAVI_NAME} ravi
@ -379,12 +277,6 @@ if (NOT STATIC_BUILD)
else ()
set_target_properties(${LIBRAVI_NAME} PROPERTIES PREFIX "")
endif ()
if (EMBEDDED_DMRC)
set_property(
TARGET ${LIBRAVI_NAME} ravi
APPEND
PROPERTY COMPILE_DEFINITIONS "USE_DMR_C=1")
endif ()
if (APPLE)
set_property(
TARGET ${LIBRAVI_NAME} libravinojit_static

@ -5,8 +5,8 @@ Ravi Programming Language
: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.
features `MIR <https://github.com/vnmakarov/mir>`_ and `LLVM <http://www.llvm.org/>`_ 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.
@ -35,14 +35,12 @@ Features
* 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>`_.
@ -90,10 +88,10 @@ History
* 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)
- Embedded C compiler using dmrC project (C JIT compiler) (now discontinued)
- Additional type-annotations
* 2018
- Implemented Eclipse OMR JIT backend
- Implemented Eclipse OMR JIT backend (now discontinued)
- Created `Ravi with batteries <https://github.com/dibyendumajumdar/Suravi>`_.
* 2019
- New language feature - `defer` statement

@ -1,7 +0,0 @@
BasedOnStyle: LLVM
IndentWidth: 8
UseTab: Always
BreakBeforeBraces: Linux
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
ColumnLimit: 120

@ -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

@ -488,8 +488,6 @@ class RaviJITState {
// May slow down compilation
unsigned int validation_ : 1;
unsigned int use_dmrc_ : 1;
// min code size for compilation
int min_code_size_;
@ -589,7 +587,6 @@ class RaviJITState {
else
compiling_--;
}
int is_use_dmrc() const { return use_dmrc_; }
};
// A wrapper for LLVM Module
@ -891,12 +888,6 @@ class RaviCodeGenerator {
public:
RaviCodeGenerator(RaviJITState *jitState);
// Compile given function if possible
// The p->ravi_jit structure will be updated
// Note that if a function fails to compile then
// a flag is set so that it doesn't get compiled again
bool alt_compile(lua_State *L, Proto *p, std::shared_ptr<RaviJITModule> module, ravi_compile_options_t *options);
// Compile given function if possible
// The p->ravi_jit structure will be updated
// Note that if a function fails to compile then

@ -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 */

@ -14,9 +14,7 @@ Contents:
ravi-overview
ravi-reference
ravi-mir-instructions
ravi-omr-instructions
ravi-llvm-instructions
ravi-dmrc
lua-introduction
lua_bytecode_reference
lua-parser

@ -1,21 +0,0 @@
====================================
dmr_C embedded C parser and compiler
====================================
Ravi includes dmr_C, an embedded C parser and compiler. The C compiler supports LLVM and Eclipse OMR backends.
The following api is under development, but is not yet fully functional, and is subject to change.
``drmc.getsymbols(source)``
Parses the input and returns a table of symbols found.
``dmrc.compileC(source)``
Compiles the input source.
Examples
========
An example use of the C parser is `ravi-tests/dmrc_getsymbols.lua <https://github.com/dibyendumajumdar/ravi/blob/master/ravi-tests/dmrc_getsymbols.lua>`_.
For an example of invoking the C compiler with LLVM backend see `ravi-tests/dmrc_testllvm.lua <https://github.com/dibyendumajumdar/ravi/blob/master/ravi-tests/dmrc_testllvm.lua>`_.
Outstanding issues
==================
* The Eclipse OMR backend cannot automatically access C functions externally defined; these have to be pre-registered. A solution might be to expose the resolution of symbols from dynamic libraries.
* We need to validate that the compiled C function is callable from Lua. This is not as easy to do with Eclipse OMR backend as with the LLVM backend.

@ -1,150 +0,0 @@
===============================
Build Ravi with Eclipse OMR JIT
===============================
.. contents:: Table of Contents
:depth: 2
:backlinks: top
Overview
========
.. note:: The Eclipse OMR JIT backend is work in progress. The code generation is not yet optimal. In particular several bytecodes are not yet inlined.
Recently support has been added in Ravi to use the Eclipse OMR JIT backend.
A `trimmed down version of the Eclipse OMR JIT <https://github.com/dibyendumajumdar/nj>`_ is used to ensure that the resulting
binaries are smaller in size.
The main advantages / disadvantages of the OMR JIT backend over LLVM are:
* The OMR JIT backend is much smaller compared to LLVM. On my iMac it takes less than 3 minutes to compile and build the library.
* The OMR JIT engine contains an optimizing compiler, therefore the generated code is much better than say `NanoJIT <https://github.com/dibyendumajumdar/nanojit>`_,
although not perhaps as optimized as LLVM.
The approach taken with the OMR JIT backend is somewhat different compared with the LLVM backend.
* An intermediate C compiler is used; this is based on the `dmr_C <https://github.com/dibyendumajumdar/dmr_c>`_ project. Using a C intermediate layer makes
development of the JIT backend easier to evolve. In comparison the LLVM backed was written by hand, using the LLVM api.
* Users can view the intermediate C code for a Lua function by simply invoking ``ravi.dumpir(function)`` on any function:
::
Ravi 5.3.4
Copyright (C) 1994-2017 Lua.org, PUC-Rio
Portions Copyright (C) 2015-2017 Dibyendu Majumdar
Options assertions ltests omrjit
> x = function() print 'hello world' end
> ravi.dumpir(x)
Above results in (note that only the function code is shown below)::
int jit_function(lua_State *L) {
int error_code = 0;
lua_Integer i = 0;
lua_Integer ic = 0;
lua_Number n = 0.0;
lua_Number nc = 0.0;
int result = 0;
StkId ra = NULL;
StkId rb = NULL;
StkId rc = NULL;
lua_Unsigned ukey = 0;
lua_Integer *iptr = NULL;
lua_Number *nptr = NULL;
Table *t = NULL;
CallInfo *ci = L->ci;
LClosure *cl = clLvalue(ci->func);
TValue *k = cl->p->k;
StkId base = ci->u.l.base;
ra = R(0);
rc = K(0);
raviV_gettable_sskey(L, cl->upvals[0]->v, rc, ra);
base = ci->u.l.base;
ra = R(1);
rb = K(1);
setobj2s(L, ra, rb);
L->top = R(2);
ra = R(0);
result = luaD_precall(L, ra, 0, 1);
if (result) {
if (result == 1 && 0 >= 0)
L->top = ci->top;
}
else { /* Lua function */
result = luaV_execute(L);
if (result) L->top = ci->top;
}
base = ci->u.l.base;
ra = R(0);
if (cl->p->sizep > 0) luaF_close(L, base);
result = (1 != 0 ? 1 - 1 : cast_int(L->top - ra));
return luaD_poscall(L, ci, ra, result);
Lraise_error:
raise_error(L, error_code); /* does not return */
return 0;
}
Build Dependencies
==================
* `CMake <https://cmake.org/>`_ is required
* On Windows you will need Visual Studio 2017 Community edition
Build Instructions
==================
* Ravi uses a cut-down version of the `Eclipse OMR JIT engine <https://github.com/dibyendumajumdar/nj>`_. First build this library and install it.
* The Ravi CMake build assumes you have installed the OMR JIT library under ``\Software\omr`` on Windows and ``$HOME/Software/omr`` on Linux or Mac OSX.
* Now you can build Ravi as follows on Linux or Mac OSX:
::
cd build
cmake -DOMR_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" ..
make
If you did not use the default locations above to install OMR, then you will need to amend the file ``cmake/FindOMRJIT.cmake``.
JIT API for OMR backend
=======================
auto mode
in this mode the compiler decides when to compile a Lua function. The current implementation is very simple -
any Lua function call is checked to see if the bytecodes contained in it can be compiled. If this is true then
the function is compiled provided either a) function has a fornum loop, or b) it is largish (greater than 150 bytecodes)
or c) it is being executed many times (> 50). Because of the simplistic behaviour performance the benefit of JIT
compilation is only available if the JIT compiled functions will be executed many times so that the cost of JIT
compilation can be amortized.
manual mode
in this mode user must explicitly request compilation. This is the default mode. This mode is suitable for library
developers who can pre compile the functions in library module table.
A JIT api is available with following functions:
``ravi.jit([b])``
returns enabled setting of JIT compiler; also enables/disables the JIT compiler; defaults to true
``ravi.auto([b [, min_size [, min_executions]]])``
returns setting of auto compilation and compilation thresholds; also sets the new settings if values are supplied; defaults are false, 150, 50.
``ravi.compile(func_or_table[, options])``
compiles a Lua function (or functions if a table is supplied) if possible, returns ``true`` if compilation was
successful for at least one function.
``options`` is an optional table with compilation options - in particular,
``omitArrayGetRangeCheck`` if set true disables range checks in array get operations to improve performance in some cases.
``inlineLuaArithmeticOperators`` if set to true enables generation of inline code for Lua arithemtic op codes such as
``OP_ADD``, ``OP_MUL`` and ``OP_SUB``.
``ravi.iscompiled(func)``
returns the JIT status of a function
``ravi.dumplua(func)``
dumps the Lua bytecode of the function
``ravi.dumpir(func)``
dumps the C intermediate code for a Lua function
``ravi.optlevel([n])``
sets optimization level (0, 1, 2); defaults to 1.
``ravi.verbosity([b])``
If set to 1 then everytime a Lua function is compiled the C intermediate code will be dumped.
Compiler Trace Output from OMR
==============================
The OMR JIT backend can generate detailed compilation traces if you define following environment variable::
export TR_Options=traceIlGen,traceFull,log=trtrace.log
Note that the generated traces can be huge!

@ -5,8 +5,8 @@ Ravi Programming Language
: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.
features `MIR <https://github.com/vnmakarov/mir>`_ and `LLVM <http://www.llvm.org/>`_ 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.
@ -35,14 +35,12 @@ Features
* 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>`_.
@ -90,10 +88,10 @@ History
* 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)
- Embedded C compiler using dmrC project (C JIT compiler) (now discontinued)
- Additional type-annotations
* 2018
- Implemented Eclipse OMR JIT backend
- Implemented Eclipse OMR JIT backend (now discontinued)
- Created `Ravi with batteries <https://github.com/dibyendumajumdar/Suravi>`_.
* 2019
- New language feature - `defer` statement

@ -34,8 +34,6 @@
#include "lualib.h"
#include "lauxlib.h"
LUAMOD_API int raviopen_dmrcluaapi(lua_State *L);
/*
** these libs are loaded by lua.c and are readily available to any Lua
** program
@ -52,9 +50,6 @@ static const luaL_Reg loadedlibs[] = {
{LUA_UTF8LIBNAME, luaopen_utf8},
{LUA_DBLIBNAME, luaopen_debug},
{LUA_RAVILIBNAME, raviopen_jit},
#if USE_DMR_C
{ "dmrc", raviopen_dmrcluaapi },
#endif
#if defined(LUA_COMPAT_BITLIB)
{LUA_BITLIBNAME, luaopen_bit32},
#endif

@ -23,7 +23,6 @@
#include <ravi_jit.h>
#include <ravi_llvmcodegen.h>
#include <ravi_jitshared.h>
#include <dmr_c.h>
namespace ravi {
@ -1345,67 +1344,6 @@ llvm::Value *RaviCodeGenerator::emit_gep_upval_value(
#endif
}
// Alternative code generator uses dmrC based C front-end
// That the codegen emits C code that is then JIT compiled
// via dmrC and LLVM.
bool RaviCodeGenerator::alt_compile(lua_State *L, Proto *p,
std::shared_ptr<RaviJITModule> module,
ravi_compile_options_t *options) {
if (p->ravi_jit.jit_status != RAVI_JIT_NOT_COMPILED) {
return false;
}
if (module->owner()->get_compiling_flag()) return false;
if (!raviJ_cancompile(p)) {
p->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE;
return false;
}
auto M = module->module();
LLVMModuleRef moduleRef = llvm::wrap(M);
// Set flag so we can avoid recursive calls
module->owner()->set_compiling_flag(true);
membuff_t buf;
membuff_init(&buf, 4096);
const char *fname = unique_function_name();
if (!raviJ_codegen(L, p, options, fname, &buf)) {
p->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE;
}
else {
if (options->manual_request && module->owner()->get_verbosity()) {
ravi_writestring(L, buf.buf, strlen(buf.buf));
ravi_writeline(L);
}
char *argv[] = {(char *)fname, NULL};
if (!dmrC_llvmcompile(2, argv, moduleRef, buf.buf)) {
p->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE;
}
else {
p->ravi_jit.jit_function = nullptr;
std::unique_ptr<ravi::RaviJITFunction> func =
std::unique_ptr<RaviJITFunction>(new RaviJITFunction(&p->ravi_jit.jit_function, module, fname));
if (func->function() == nullptr) {
fprintf(stderr, "LLVM Compilation failed\n");
exit(1);
}
bool doVerify = module->owner()->get_validation() != 0;
if (doVerify && llvm::verifyFunction(*func->function(), &llvm::errs())) {
func->dump();
fprintf(stderr, "LLVM Code Verification failed\n");
exit(1);
}
ravi::RaviJITFunction *llvm_func = func.release();
p->ravi_jit.jit_data = reinterpret_cast<void *>(llvm_func);
p->ravi_jit.jit_status = RAVI_JIT_COMPILED;
}
}
membuff_free(&buf);
module->owner()->set_compiling_flag(false);
return p->ravi_jit.jit_status == RAVI_JIT_COMPILED;
}
bool RaviCodeGenerator::compile(lua_State *L, Proto *p,
std::shared_ptr<RaviJITModule> module,
ravi_compile_options_t *options) {

@ -182,7 +182,6 @@ RaviJITState::RaviJITState()
verbosity_(0),
tracehook_enabled_(false),
validation_(false),
use_dmrc_(false),
min_code_size_(150),
min_exec_count_(50),
allocated_modules_(0),
@ -200,8 +199,6 @@ RaviJITState::RaviJITState()
init++;
}
triple_ = llvm::sys::getProcessTriple();
if (::getenv("RAVI_USE_DMRC_LLVM"))
use_dmrc_ = true;
#if USE_ORCv2_JIT
@ -847,8 +844,7 @@ int raviV_compile(struct lua_State *L, struct Proto *p, ravi_compile_options_t *
}
if (doCompile) {
auto module = std::make_shared<ravi::RaviJITModule>(G->ravi_state->jit);
if (G->ravi_state->jit->is_use_dmrc() ? G->ravi_state->code_generator->alt_compile(L, p, module, options)
: G->ravi_state->code_generator->compile(L, p, module, options)) {
if (G->ravi_state->code_generator->compile(L, p, module, options)) {
module->runpasses();
module->finalize(G->ravi_state->jit->get_verbosity() == 3);
}
@ -866,8 +862,7 @@ int raviV_compile_n(struct lua_State *L, struct Proto *p[], int n, ravi_compile_
return 0;
auto module = std::make_shared<ravi::RaviJITModule>(G->ravi_state->jit);
for (int i = 0; i < n; i++) {
if (G->ravi_state->jit->is_use_dmrc() ? G->ravi_state->code_generator->alt_compile(L, p[i], module, options)
: G->ravi_state->code_generator->compile(L, p[i], module, options))
if (G->ravi_state->code_generator->compile(L, p[i], module, options))
count++;
}
if (count) {

@ -1,562 +0,0 @@
/******************************************************************************
* Copyright (C) 2018-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.
******************************************************************************/
#include <ravi_omrjit.h>
#include <ravi_jit.h>
#include <stddef.h>
#include <assert.h>
#define LUA_CORE
#include "lauxlib.h"
#include "lobject.h"
#include "lstate.h"
#include "lua.h"
static const char *errortext[] = {"integer expected",
"number expected",
"integer[] expected",
"number[] expected",
"table expected",
"upvalue of integer type, cannot be set to non integer value",
"upvalue of number type, cannot be set to non number value",
"upvalue of integer[] type, cannot be set to non integer[] value",
"upvalue of number[] type, cannot be set to non number[] value",
"upvalue of table type, cannot be set to non table value",
"for llimit must be a number",
"for step must be a number",
"for initial value must be a number",
"array index is out of bounds",
"string expected",
"closure expected",
"type mismatch: wrong userdata type",
NULL};
static void raise_error(lua_State *L, int errorcode) {
assert(errorcode >= 0 && errorcode < Error_type_mismatch);
luaG_runerror(L, errortext[errorcode]);
}
static void raise_error_with_info(lua_State *L, int errorcode, const char *info) {
assert(errorcode == Error_type_mismatch);
luaG_runerror(L, "type mismatch: expected %s", info);
}
static void register_builtin_arg1(JIT_ContextRef module, const char *name,
void *fp, JIT_Type return_type,
JIT_Type arg1) {
JIT_Type args[1];
args[0] = arg1;
JIT_RegisterFunction(module, name, return_type, 1, args, fp);
}
static void register_builtin_arg2(JIT_ContextRef module, const char *name,
void *fp, JIT_Type return_type,
JIT_Type arg1,
JIT_Type arg2) {
JIT_Type args[2];
args[0] = arg1;
args[1] = arg2;
JIT_RegisterFunction(module, name, return_type, 2, args, fp);
}
static void register_builtin_arg3(JIT_ContextRef module, const char *name,
void *fp, JIT_Type return_type,
JIT_Type arg1,
JIT_Type arg2,
JIT_Type arg3) {
JIT_Type args[3];
args[0] = arg1;
args[1] = arg2;
args[2] = arg3;
JIT_RegisterFunction(module, name, return_type, 3, args, fp);
}
static void register_builtin_arg4(JIT_ContextRef module, const char *name,
void *fp, JIT_Type return_type,
JIT_Type arg1,
JIT_Type arg2,
JIT_Type arg3,
JIT_Type arg4) {
JIT_Type args[4];
args[0] = arg1;
args[1] = arg2;
args[2] = arg3;
args[3] = arg4;
JIT_RegisterFunction(module, name, return_type, 4, args, fp);
}
static void register_builtin_arg5(JIT_ContextRef module, const char *name,
void *fp, JIT_Type return_type,
JIT_Type arg1,
JIT_Type arg2,
JIT_Type arg3,
JIT_Type arg4,
JIT_Type arg5) {
JIT_Type args[5];
args[0] = arg1;
args[1] = arg2;
args[2] = arg3;
args[3] = arg4;
args[4] = arg5;
JIT_RegisterFunction(module, name, return_type, 5, args, fp);
}
#if !RAVI_TARGET_X64
#error OMRJIT is currently only supported on X64 architecture
#endif
// Initialize the JIT State and attach it to the
// Global Lua State
// If a JIT State already exists then this function
// will return -1
int raviV_initjit(struct lua_State *L) {
global_State *G = G(L);
if (G->ravi_state != NULL) return -1;
ravi_State *jit = (ravi_State *)calloc(1, sizeof(ravi_State));
jit->auto_ = 0;
jit->enabled_ = 1;
jit->min_code_size_ = 150;
jit->min_exec_count_ = 50;
jit->opt_level_ = 1;
// The parameter true means we will be dumping stuff as we compile
jit->jit = JIT_CreateContext();
// FIXME Portability - following needs to handle 32-bit arch
//extern void luaF_close (lua_State *L, StkId level);
register_builtin_arg2(jit->jit, "luaF_close", luaF_close, JIT_NoType, JIT_Address, JIT_Address);
register_builtin_arg2(jit->jit, "raise_error", raise_error, JIT_NoType, JIT_Address, JIT_Int32);
register_builtin_arg3(jit->jit, "raise_error_with_info", raise_error_with_info, JIT_NoType, JIT_Address, JIT_Int32, JIT_Address);
//extern int luaV_tonumber_(const TValue *obj, lua_Number *n);
register_builtin_arg2(jit->jit, "luaV_tonumber_", luaV_tonumber_, JIT_Int32, JIT_Address, JIT_Address);
//extern int luaV_tointeger(const TValue *obj, lua_Integer *p, int mode);
register_builtin_arg3(jit->jit, "luaV_tointeger", luaV_tointeger, JIT_Int32, JIT_Address, JIT_Address, JIT_Int32);
//extern int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres);
register_builtin_arg4(jit->jit, "luaD_poscall", luaD_poscall, JIT_Int32, JIT_Address, JIT_Address, JIT_Address, JIT_Int32);
//extern int luaV_equalobj(lua_State *L, const TValue *t1, const TValue *t2);\n"
register_builtin_arg3(jit->jit, "luaV_equalobj", luaV_equalobj, JIT_Int32, JIT_Address, JIT_Address, JIT_Address);
//extern int luaV_lessthan(lua_State *L, const TValue *l, const TValue *r);\n"
register_builtin_arg3(jit->jit, "luaV_lessthan", luaV_lessthan, JIT_Int32, JIT_Address, JIT_Address, JIT_Address);
//extern int luaV_lessequal(lua_State *L, const TValue *l, const TValue *r);\n"
register_builtin_arg3(jit->jit, "luaV_lessequal", luaV_lessequal, JIT_Int32, JIT_Address, JIT_Address, JIT_Address);
//extern int luaV_execute(lua_State *L);
register_builtin_arg1(jit->jit, "luaV_execute", luaV_execute, JIT_Int32, JIT_Address);
//extern void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val)
register_builtin_arg4(jit->jit, "luaV_gettable", luaV_gettable, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Address);
//extern void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val);
register_builtin_arg4(jit->jit, "luaV_settable", luaV_settable, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Address);
//int luaD_precall (lua_State *L, StkId func, int nresults, int op_call);
register_builtin_arg4(jit->jit, "luaD_precall", luaD_precall, JIT_Int32, JIT_Address, JIT_Address, JIT_Int32, JIT_Int32);
//extern void raviV_op_newtable(lua_State *L, CallInfo *ci, TValue *ra, int b, int c)
register_builtin_arg5(jit->jit, "raviV_op_newtable", raviV_op_newtable, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32, JIT_Int32);
//extern void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, TValue *res);
register_builtin_arg5(jit->jit, "luaO_arith", luaO_arith, JIT_NoType, JIT_Address, JIT_Int32, JIT_Address, JIT_Address, JIT_Address);
//extern void raviV_op_newarrayint(lua_State *L, CallInfo *ci, TValue *ra);
register_builtin_arg3(jit->jit, "raviV_op_newarrayint", raviV_op_newarrayint, JIT_NoType, JIT_Address, JIT_Address, JIT_Address);
//extern void raviV_op_newarrayfloat(lua_State *L, CallInfo *ci, TValue *ra);
register_builtin_arg3(jit->jit, "raviV_op_newarrayfloat", raviV_op_newarrayfloat, JIT_NoType, JIT_Address, JIT_Address, JIT_Address);
//LUAI_FUNC void raviV_op_setlist(lua_State *L, CallInfo *ci, TValue *ra, int b, int c);
register_builtin_arg5(jit->jit, "raviV_op_setlist", raviV_op_setlist, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32, JIT_Int32);
//LUAI_FUNC void raviV_op_concat(lua_State *L, CallInfo *ci, int a, int b, int c);
register_builtin_arg5(jit->jit, "raviV_op_concat", raviV_op_concat, JIT_NoType, JIT_Address, JIT_Address, JIT_Int32, JIT_Int32, JIT_Int32);
//LUAI_FUNC void raviV_op_closure(lua_State *L, CallInfo *ci, LClosure *cl, int a, int Bx);
register_builtin_arg5(jit->jit, "raviV_op_closure", raviV_op_closure, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32, JIT_Int32);
//LUAI_FUNC void raviV_op_vararg(lua_State *L, CallInfo *ci, LClosure *cl, int a, int b);
register_builtin_arg5(jit->jit, "raviV_op_vararg", raviV_op_vararg, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32, JIT_Int32);
// void luaV_objlen (lua_State *L, StkId ra, const TValue *rb)
register_builtin_arg3(jit->jit, "luaV_objlen", luaV_objlen, JIT_NoType, JIT_Address, JIT_Address, JIT_Address);
//int luaV_forlimit(const TValue *obj, lua_Integer *p, lua_Integer step, int *stopnow);
register_builtin_arg4(jit->jit, "luaV_forlimit", luaV_forlimit, JIT_Int32, JIT_Address, JIT_Address, JIT_Int64, JIT_Address);
// void raviV_op_setupval(lua_State *L, LClosure *cl, TValue *ra, int b);
register_builtin_arg4(jit->jit, "raviV_op_setupval", raviV_op_setupval, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32);
register_builtin_arg4(jit->jit, "raviV_op_setupvali", raviV_op_setupvali, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32);
register_builtin_arg4(jit->jit, "raviV_op_setupvalf", raviV_op_setupvalf, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32);
register_builtin_arg4(jit->jit, "raviV_op_setupvalai", raviV_op_setupvalai, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32);
register_builtin_arg4(jit->jit, "raviV_op_setupvalaf", raviV_op_setupvalaf, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32);
register_builtin_arg4(jit->jit, "raviV_op_setupvalt", raviV_op_setupvalt, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Int32);
//extern void luaD_call (lua_State *L, StkId func, int nResults);
register_builtin_arg3(jit->jit, "luaD_call", luaD_call, JIT_NoType, JIT_Address, JIT_Address, JIT_Int32);
//"extern void raviH_set_int(lua_State *L, Table *t, lua_Unsigned key, lua_Integer value);\n"
register_builtin_arg4(jit->jit, "raviH_set_int", raviH_set_int, JIT_NoType, JIT_Address, JIT_Address, JIT_Int64, JIT_Int64);
//"extern void raviH_set_float(lua_State *L, Table *t, lua_Unsigned key, lua_Number value);\n"
register_builtin_arg4(jit->jit, "raviH_set_float", raviH_set_float, JIT_NoType, JIT_Address, JIT_Address, JIT_Int64, JIT_Double);
//int raviV_check_usertype(lua_State *L, TString *name, const TValue *o);
register_builtin_arg3(jit->jit, "raviV_check_usertype", raviV_check_usertype, JIT_Int32, JIT_Address, JIT_Address, JIT_Address);
// void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, TValue *res, TMS event);
register_builtin_arg5(jit->jit, "luaT_trybinTM", luaT_trybinTM, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Address, JIT_Int32);
// void raviV_gettable_sskey(lua_State *L, const TValue *t, TValue *key, StkId val);
register_builtin_arg4(jit->jit, "raviV_gettable_sskey", raviV_gettable_sskey, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Address);
// void raviV_settable_sskey(lua_State *L, const TValue *t, TValue *key, StkId val);
register_builtin_arg4(jit->jit, "raviV_settable_sskey", raviV_settable_sskey, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Address);
// void raviV_gettable_i(lua_State *L, const TValue *t, TValue *key, StkId val);
register_builtin_arg4(jit->jit, "raviV_gettable_i", raviV_gettable_i, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Address);
// void raviV_settable_i(lua_State *L, const TValue *t, TValue *key, StkId val);
register_builtin_arg4(jit->jit, "raviV_settable_i", raviV_settable_i, JIT_NoType, JIT_Address, JIT_Address, JIT_Address, JIT_Address);
//LUA_API int (lua_absindex)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_absindex", lua_absindex, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API int (lua_gettop)(lua_State *L);
register_builtin_arg1(jit->jit, "lua_gettop", lua_gettop, JIT_Int32, JIT_Address);
//LUA_API void (lua_pushvalue)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_pushvalue", lua_pushvalue, JIT_NoType, JIT_Address, JIT_Int32);
//LUA_API int (lua_isnumber)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_isnumber", lua_isnumber, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API int (lua_isstring)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_isstring", lua_isstring, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API int (lua_iscfunction)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_iscfunction", lua_iscfunction, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API int (lua_isinteger)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_isinteger", lua_isinteger, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API int (lua_isuserdata)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_isuserdata", lua_isuserdata, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API int (lua_type)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_type", lua_type, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API const char *(lua_typename)(lua_State *L, int tp);
register_builtin_arg2(jit->jit, "lua_typename", (void*)lua_typename, JIT_Address, JIT_Address, JIT_Int32);
//LUA_API const char * (ravi_typename)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "ravi_typename", (void*)ravi_typename, JIT_Address, JIT_Address, JIT_Int32);
//LUA_API lua_Number(lua_tonumberx) (lua_State *L, int idx, int *isnum);
register_builtin_arg3(jit->jit, "lua_tonumberx", lua_tonumberx, JIT_Double, JIT_Address, JIT_Int32, JIT_Address);
//LUA_API lua_Integer(lua_tointegerx) (lua_State *L, int idx, int *isnum);
register_builtin_arg3(jit->jit, "lua_tointegerx", lua_tointegerx, JIT_Int64, JIT_Address, JIT_Int32, JIT_Address);
//LUA_API int (lua_toboolean)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_toboolean", lua_toboolean, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API const char *(lua_tolstring)(lua_State *L, int idx, size_t *len);
register_builtin_arg3(jit->jit, "lua_tolstring", (void*)lua_tolstring, JIT_Address, JIT_Address, JIT_Int32, JIT_Address);
//LUA_API size_t(lua_rawlen) (lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_rawlen", lua_rawlen, JIT_Int64, JIT_Address, JIT_Int32);
//LUA_API lua_CFunction(lua_tocfunction) (lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_tocfunction", lua_tocfunction, JIT_Address, JIT_Address, JIT_Int32);
//LUA_API void *(lua_touserdata)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_touserdata", lua_touserdata, JIT_Address, JIT_Address, JIT_Int32);
//LUA_API lua_State *(lua_tothread)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_tothread", lua_tothread, JIT_Address, JIT_Address, JIT_Int32);
//LUA_API const void *(lua_topointer)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_topointer", (void *)lua_topointer, JIT_Address, JIT_Address, JIT_Int32);
//LUA_API void (lua_arith)(lua_State *L, int op);
register_builtin_arg2(jit->jit, "lua_arith", lua_arith, JIT_NoType, JIT_Address, JIT_Int32);
//LUA_API int (lua_rawequal)(lua_State *L, int idx1, int idx2);
register_builtin_arg3(jit->jit, "lua_rawequal", lua_rawequal, JIT_Int32, JIT_Address, JIT_Int32, JIT_Int32);
//LUA_API int (lua_compare)(lua_State *L, int idx1, int idx2, int op);
register_builtin_arg4(jit->jit, "lua_compare", lua_compare, JIT_Int32, JIT_Address, JIT_Int32, JIT_Int32, JIT_Int32);
//LUA_API void (lua_pushnil)(lua_State *L);
register_builtin_arg1(jit->jit, "lua_pushnil", lua_pushnil, JIT_NoType, JIT_Address);
//LUA_API void (lua_pushnumber)(lua_State *L, lua_Number n);
register_builtin_arg2(jit->jit, "lua_pushnumber", lua_pushnumber, JIT_NoType, JIT_Address, JIT_Double);
//LUA_API void (lua_pushinteger)(lua_State *L, lua_Integer n);
register_builtin_arg2(jit->jit, "lua_pushinteger", lua_pushinteger, JIT_NoType, JIT_Address, JIT_Int64);
//LUA_API const char *(lua_pushlstring)(lua_State *L, const char *s, size_t len);
register_builtin_arg3(jit->jit, "lua_pushlstring", (void*)lua_pushlstring, JIT_Address, JIT_Address, JIT_Address, JIT_Int64);
//LUA_API const char *(lua_pushstring)(lua_State *L, const char *s);
register_builtin_arg2(jit->jit, "lua_pushstring", (void*)lua_pushstring, JIT_Address, JIT_Address, JIT_Address);
//LUA_API void (lua_pushcclosure)(lua_State *L, lua_CFunction fn, int n);
register_builtin_arg3(jit->jit, "lua_pushcclosure", lua_pushcclosure, JIT_NoType, JIT_Address, JIT_Address, JIT_Int32);
// LUA_API void (lua_pushboolean)(lua_State *L, int b);
register_builtin_arg2(jit->jit, "lua_pushboolean", lua_pushboolean, JIT_NoType, JIT_Address, JIT_Int32);
//LUA_API void (lua_pushlightuserdata)(lua_State *L, void *p);
register_builtin_arg2(jit->jit, "lua_pushlightuserdata", lua_pushlightuserdata, JIT_NoType, JIT_Address, JIT_Address);
//LUA_API int (lua_pushthread)(lua_State *L);
register_builtin_arg1(jit->jit, "lua_pushthread", lua_pushthread, JIT_Int32, JIT_Address);
//LUA_API int (lua_getglobal)(lua_State *L, const char *name);
register_builtin_arg2(jit->jit, "lua_getglobal", lua_getglobal, JIT_Int32, JIT_Address, JIT_Address);
//LUA_API int (lua_gettable)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_gettable", lua_gettable, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API int (lua_getfield)(lua_State *L, int idx, const char *k);
register_builtin_arg3(jit->jit, "lua_getfield", lua_getfield, JIT_Int32, JIT_Address, JIT_Int32, JIT_Address);
//LUA_API int (lua_geti)(lua_State *L, int idx, lua_Integer n);
register_builtin_arg3(jit->jit, "lua_geti", lua_geti, JIT_Int32, JIT_Address, JIT_Int32, JIT_Int64);
//LUA_API int (lua_rawget)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_rawget", lua_rawget, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API int (lua_rawgeti)(lua_State *L, int idx, lua_Integer n);
register_builtin_arg3(jit->jit, "lua_rawgeti", lua_rawgeti, JIT_Int32, JIT_Address, JIT_Int32, JIT_Int64);
//LUA_API int (lua_rawgetp)(lua_State *L, int idx, const void *p);
register_builtin_arg3(jit->jit, "lua_rawgetp", lua_rawgetp, JIT_Int32, JIT_Address, JIT_Int32, JIT_Address);
//LUA_API void (lua_createtable)(lua_State *L, int narr, int nrec);
register_builtin_arg3(jit->jit, "lua_createtable", lua_createtable, JIT_NoType, JIT_Address, JIT_Int32, JIT_Int32);
//LUA_API void *(lua_newuserdata)(lua_State *L, size_t sz);
register_builtin_arg2(jit->jit, "lua_newuserdata", lua_newuserdata, JIT_Address, JIT_Address, JIT_Int64);
//LUA_API int (lua_getmetatable)(lua_State *L, int objindex);
register_builtin_arg2(jit->jit, "lua_getmetatable", lua_getmetatable, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API int (lua_getuservalue)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_getuservalue", lua_getuservalue, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API void (lua_setglobal)(lua_State *L, const char *name);
register_builtin_arg2(jit->jit, "lua_setglobal", lua_setglobal, JIT_NoType, JIT_Address, JIT_Address);
//LUA_API void (lua_settable)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_settable", lua_settable, JIT_NoType, JIT_Address, JIT_Int32);
//LUA_API void (lua_setfield)(lua_State *L, int idx, const char *k);
register_builtin_arg3(jit->jit, "lua_setfield", lua_setfield, JIT_NoType, JIT_Address, JIT_Int32, JIT_Address);
//LUA_API void (lua_seti)(lua_State *L, int idx, lua_Integer n);
register_builtin_arg3(jit->jit, "lua_seti", lua_seti, JIT_NoType, JIT_Address, JIT_Int32, JIT_Int64);
//LUA_API void (lua_rawset)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_rawset", lua_rawset, JIT_NoType, JIT_Address, JIT_Int32);
//LUA_API void (lua_rawseti)(lua_State *L, int idx, lua_Integer n);
register_builtin_arg3(jit->jit, "lua_rawseti", lua_rawseti, JIT_NoType, JIT_Address, JIT_Int32, JIT_Int64);
//LUA_API void (lua_rawsetp)(lua_State *L, int idx, const void *p);
register_builtin_arg3(jit->jit, "lua_rawsetp", lua_rawsetp, JIT_NoType, JIT_Address, JIT_Int32, JIT_Address);
//LUA_API int (lua_setmetatable)(lua_State *L, int objindex);
register_builtin_arg2(jit->jit, "lua_setmetatable", lua_setmetatable, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API void (lua_setuservalue)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_setuservalue", lua_setuservalue, JIT_NoType, JIT_Address, JIT_Int32);
#ifdef RAVI_DEFER_STATEMENT
//LUA_API void raviV_op_defer(lua_State *L, TValue *ra);
register_builtin_arg2(jit->jit, "raviV_op_defer", raviV_op_defer, JIT_NoType, JIT_Address, JIT_Address);
#endif
//LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
register_builtin_arg2(jit->jit, "luaV_shiftl", luaV_shiftl, JIT_Int64, JIT_Int64, JIT_Int64);
// extern void raviV_op_bnot(lua_State *L, TValue *ra, TValue *rb);
register_builtin_arg3(jit->jit, "raviV_op_bnot", raviV_op_bnot, JIT_NoType, JIT_Address, JIT_Address, JIT_Address);
G->ravi_state = jit;
return 0;
}
// Free up the JIT State
void raviV_close(struct lua_State *L) {
global_State *G = G(L);
if (G->ravi_state == NULL) return;
// All compiled functions will be deleted at this stage
JIT_DestroyContext(G->ravi_state->jit);
free(G->ravi_state);
}
// Dump the intermediate C code
void raviV_dumpIR(struct lua_State *L, struct Proto *p) {
global_State *G = G(L);
if (G->ravi_state == NULL)
return;
membuff_t buf;
membuff_init(&buf, 4096);
char fname[30];
snprintf(fname, sizeof fname, "%s", "jit_function");
ravi_compile_options_t options;
memset(&options, 0, sizeof options);
options.codegen_type = RAVI_CODEGEN_ALL;
if (raviJ_codegen(L, p, &options, fname, &buf)) {
ravi_writestring(L, buf.buf, strlen(buf.buf));
ravi_writeline(L);
}
membuff_free(&buf);
}
// Dump the LLVM ASM
void raviV_dumpASM(struct lua_State *L, struct Proto *p) {
(void)L;
(void)p;
}
void raviV_setminexeccount(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
G->ravi_state->min_exec_count_ = value;
}
int raviV_getminexeccount(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
return G->ravi_state->min_exec_count_;
}
void raviV_setmincodesize(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
G->ravi_state->min_code_size_ = value;
}
int raviV_getmincodesize(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
return G->ravi_state->min_code_size_;
}
void raviV_setauto(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
G->ravi_state->auto_ = value;
}
int raviV_getauto(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
return G->ravi_state->auto_;
}
// Turn on/off the JIT compiler
void raviV_setjitenabled(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
G->ravi_state->enabled_ = value;
}
int raviV_getjitenabled(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
return G->ravi_state->enabled_;
}
void raviV_setoptlevel(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
G->ravi_state->opt_level_ = value;
}
int raviV_getoptlevel(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
return G->ravi_state->opt_level_;
}
void raviV_setsizelevel(lua_State *L, int value) {
(void)L;
(void)value;
}
int raviV_getsizelevel(lua_State *L) {
(void)L;
return 0;
}
void raviV_setvalidation(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
G->ravi_state->validation_ = value;
}
int raviV_getvalidation(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
return G->ravi_state->validation_;
}
void raviV_setverbosity(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
G->ravi_state->verbosity_ = value;
}
int raviV_getverbosity(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
return G->ravi_state->verbosity_;
}
// Turn on/off the JIT compiler
void raviV_settraceenabled(lua_State *L, int value) {
(void)L;
(void)value;
}
int raviV_gettraceenabled(lua_State *L) {
(void)L;
return 0;
}
int raviV_compile_n(struct lua_State *L, struct Proto *p[], int n,
ravi_compile_options_t *options) {
int count = 0;
for (int i = 0; i < n; i++) {
if (raviV_compile(L, p[i], options)) count++;
}
return count > 0;
}
// Compile a Lua function
// If JIT is turned off then compilation is skipped
// Compilation occurs if either auto compilation is ON (subject to some
// thresholds)
// or if a manual compilation request was made
// Returns true if compilation was successful
int raviV_compile(struct lua_State *L, struct Proto *p, ravi_compile_options_t *options) {
if (p->ravi_jit.jit_status == RAVI_JIT_COMPILED)
return true;
else if (p->ravi_jit.jit_status == RAVI_JIT_CANT_COMPILE)
return false;
if (options == NULL) return false;
global_State *G = G(L);
if (G->ravi_state == NULL) return false;
JIT_ContextRef context = G->ravi_state->jit;
if (context == NULL) return false;
bool doCompile = (bool)(options && options->manual_request != 0);
if (!doCompile && G->ravi_state->auto_) {
if (p->ravi_jit.jit_flags == RAVI_JIT_FLAG_HASFORLOOP) /* function has fornum loop, so compile */
doCompile = true;
else if (p->sizecode > G->ravi_state->min_code_size_) /* function is long so compile */
doCompile = true;
else {
if (p->ravi_jit.execution_count < G->ravi_state->min_exec_count_) /* function has been executed many
times so compile */
p->ravi_jit.execution_count++;
else
doCompile = true;
}
}
if (!doCompile) { return false; }
if (!raviJ_cancompile(p)) {
p->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE;
return false;
}
if (G->ravi_state->compiling_) return false;
G->ravi_state->compiling_ = 1;
membuff_t buf;
membuff_init(&buf, 4096);
int (*fp)(lua_State * L) = NULL;
char fname[30];
snprintf(fname, sizeof fname, "jit%lld", G->ravi_state->id++);
char *argv[] = { fname, "-O1", NULL };
if (!raviJ_codegen(L, p, options, fname, &buf)) {
p->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE;
goto Lerror;
}
if (options->manual_request && G->ravi_state->verbosity_) {
ravi_writestring(L, buf.buf, strlen(buf.buf));
ravi_writeline(L);
}
int opt_level = G->ravi_state->opt_level_;
if (opt_level == 0)
argv[1] = "-O0";
else if (opt_level >= 2)
argv[1] = "-O2";
if (!dmrC_omrcompile(2, argv, context, buf.buf)) {
p->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE;
}
else {
fp = JIT_GetFunction(context, fname);
if (fp != NULL) {
p->ravi_jit.jit_data = NULL;
p->ravi_jit.jit_function = fp;
p->ravi_jit.jit_status = RAVI_JIT_COMPILED;
}
}
Lerror:
membuff_free(&buf);
G->ravi_state->compiling_ = 0;
return fp != NULL;
}
// Free the JIT compiled function
// Note that this is called by the garbage collector
void raviV_freeproto(struct lua_State *L, struct Proto *p) {
(void)L;
(void)p;
}

@ -1,188 +0,0 @@
#include <ravi_omrjit.h>
#include <ravi_jit.h>
#include <stddef.h>
#include <assert.h>
#define LUA_CORE
#include "lauxlib.h"
#include "lobject.h"
#include "lstate.h"
#include "lua.h"
static const char Lua_header[] = ""
"typedef __SIZE_TYPE__ size_t;\n"
"typedef long long ptrdiff_t;\n"
"typedef long long intptr_t;\n"
"typedef long long int64_t;\n"
"typedef unsigned long long uint64_t;\n"
"typedef int int32_t;\n"
"typedef unsigned int uint32_t;\n"
"typedef short int16_t;\n"
"typedef unsigned short uint16_t;\n"
"typedef char int8_t;\n"
"typedef unsigned char uint8_t;\n"
"typedef size_t lu_mem;\n"
"typedef ptrdiff_t l_mem;\n"
"typedef unsigned char lu_byte;\n"
"typedef uint16_t LuaType;\n"
"#define NULL ((void *)0)\n"
"typedef struct lua_State lua_State;\n"
"#define LUA_TNONE (-1)\n"
"#define LUA_TNIL 0\n"
"#define LUA_TBOOLEAN 1\n"
"#define LUA_TLIGHTUSERDATA 2\n"
"#define LUA_TNUMBER 3\n"
"#define LUA_TSTRING 4\n"
"#define LUA_TTABLE 5\n"
"#define LUA_TFUNCTION 6\n"
"#define LUA_TUSERDATA 7\n"
"#define LUA_TTHREAD 8\n"
"typedef double lua_Number;\n"
"typedef int64_t lua_Integer;\n"
"typedef uint64_t lua_Unsigned;\n"
"typedef int (*lua_CFunction) (lua_State *L);\n"
"extern int (lua_absindex)(lua_State *L, int idx);\n"
"extern int (lua_gettop)(lua_State *L);\n"
"extern void (lua_pushvalue)(lua_State *L, int idx);\n"
"extern int (lua_isnumber)(lua_State *L, int idx);\n"
"extern int (lua_isstring)(lua_State *L, int idx);\n"
"extern int (lua_iscfunction)(lua_State *L, int idx);\n"
"extern int (lua_isinteger)(lua_State *L, int idx);\n"
"extern int (lua_isuserdata)(lua_State *L, int idx);\n"
"extern int (lua_type)(lua_State *L, int idx);\n"
"extern const char *(lua_typename)(lua_State *L, int tp);\n"
"extern const char * (ravi_typename)(lua_State *L, int idx);\n"
"extern lua_Number(lua_tonumberx) (lua_State *L, int idx, int *isnum);\n"
"extern lua_Integer(lua_tointegerx) (lua_State *L, int idx, int *isnum);\n"
"extern int (lua_toboolean)(lua_State *L, int idx);\n"
"extern const char *(lua_tolstring)(lua_State *L, int idx, size_t *len);\n"
"extern size_t(lua_rawlen) (lua_State *L, int idx);\n"
"extern lua_CFunction(lua_tocfunction) (lua_State *L, int idx);\n"
"extern void *(lua_touserdata)(lua_State *L, int idx);\n"
"extern lua_State *(lua_tothread)(lua_State *L, int idx);\n"
"extern const void *(lua_topointer)(lua_State *L, int idx);\n"
"#define LUA_OPADD 0\n"
"#define LUA_OPSUB 1\n"
"#define LUA_OPMUL 2\n"
"#define LUA_OPMOD 3\n"
"#define LUA_OPPOW 4\n"
"#define LUA_OPDIV 5\n"
"#define LUA_OPIDIV 6\n"
"#define LUA_OPBAND 7\n"
"#define LUA_OPBOR 8\n"
"#define LUA_OPBXOR 9\n"
"#define LUA_OPSHL 10\n"
"#define LUA_OPSHR 11\n"
"#define LUA_OPUNM 12\n"
"#define LUA_OPBNOT 13\n"
"extern void (lua_arith)(lua_State *L, int op);\n"
"#define LUA_OPEQ 0\n"
"#define LUA_OPLT 1\n"
"#define LUA_OPLE 2\n"
"extern int (lua_rawequal)(lua_State *L, int idx1, int idx2);\n"
"extern int (lua_compare)(lua_State *L, int idx1, int idx2, int op);\n"
"extern void (lua_pushnil)(lua_State *L);\n"
"extern void (lua_pushnumber)(lua_State *L, lua_Number n);\n"
"extern void (lua_pushinteger)(lua_State *L, lua_Integer n);\n"
"extern const char *(lua_pushlstring)(lua_State *L, const char *s, size_t len);\n"
"extern const char *(lua_pushstring)(lua_State *L, const char *s);\n"
"extern void (lua_pushcclosure)(lua_State *L, lua_CFunction fn, int n);\n"
"extern void (lua_pushboolean)(lua_State *L, int b);\n"
"extern void (lua_pushlightuserdata)(lua_State *L, void *p);\n"
"extern int (lua_pushthread)(lua_State *L);\n"
"extern int (lua_getglobal)(lua_State *L, const char *name);\n"
"extern int (lua_gettable)(lua_State *L, int idx);\n"
"extern int (lua_getfield)(lua_State *L, int idx, const char *k);\n"
"extern int (lua_geti)(lua_State *L, int idx, lua_Integer n);\n"
"extern int (lua_rawget)(lua_State *L, int idx);\n"
"extern int (lua_rawgeti)(lua_State *L, int idx, lua_Integer n);\n"
"extern int (lua_rawgetp)(lua_State *L, int idx, const void *p);\n"
"extern void (lua_createtable)(lua_State *L, int narr, int nrec);\n"
"extern void *(lua_newuserdata)(lua_State *L, size_t sz);\n"
"extern int (lua_getmetatable)(lua_State *L, int objindex);\n"
"extern int (lua_getuservalue)(lua_State *L, int idx);\n"
"extern void (lua_setglobal)(lua_State *L, const char *name);\n"
"extern void (lua_settable)(lua_State *L, int idx);\n"
"extern void (lua_setfield)(lua_State *L, int idx, const char *k);\n"
"extern void (lua_seti)(lua_State *L, int idx, lua_Integer n);\n"
"extern void (lua_rawset)(lua_State *L, int idx);\n"
"extern void (lua_rawseti)(lua_State *L, int idx, lua_Integer n);\n"
"extern void (lua_rawsetp)(lua_State *L, int idx, const void *p);\n"
"extern int (lua_setmetatable)(lua_State *L, int objindex);\n"
"extern void (lua_setuservalue)(lua_State *L, int idx);\n"
;
enum {
MAX_ARGS = 50,
MAX_BUFFER = 4096
};
static int collect_args(lua_State *L, int tabindex, char *argv[], int maxargs,
char *buf, int buflen) {
char errormessage[128];
int len = lua_rawlen(L, tabindex);
if (len > maxargs) {
snprintf(errormessage, sizeof errormessage,
"Arguments exceed total count %d elements", maxargs);
luaL_argerror(L, 2, errormessage);
len = maxargs;
}
char *p = buf;
char *endp = buf + buflen;
int n = 0;
for (int i = 0; i < len; i++) {
lua_rawgeti(L, tabindex, i + 1);
size_t size = 0;
const char *argument = luaL_checklstring(L, -1, &size);
if (argument && size > 0) {
if (p + size + 1 >= endp) {
snprintf(errormessage, sizeof errormessage,
"Arguments exceed combined size of %d bytes", buflen);
luaL_argerror(L, 2, errormessage);
break;
}
strncpy(p, argument, size + 1);
argv[n] = p;
p += (size + 1);
n++;
}
}
assert(p <= endp);
return n;
}
int ravi_compile_C(lua_State *L) {
global_State *G = G(L);
if (G->ravi_state == NULL) return 0;
JIT_ContextRef context = G->ravi_state->jit;
if (context == NULL) return 0;
const char *codebuffer = NULL;
char *argv[MAX_ARGS + 1] = {NULL};
int argc = 0;
char buf[MAX_BUFFER + 1] = {0};
int guard = 0xfefefefe;
int codearg = 1;
if (lua_istable(L, 1)) {
argc = collect_args(L, 1, argv, MAX_ARGS, buf, sizeof buf);
assert(argc >= 0 && argc <= MAX_ARGS);
assert(argv[MAX_ARGS] == NULL);
assert(guard == 0xfefefefe);
codearg++;
}
codebuffer = luaL_checkstring(L, codearg);
membuff_t mbuf;
membuff_init(&mbuf, strlen(Lua_header) + 4096);
membuff_add_string(&mbuf, Lua_header);
membuff_add_string(&mbuf, codebuffer);
if (!dmrC_omrcompile(argc, argv, context, mbuf.buf)) {
lua_pushboolean(L, false);
}
else {
lua_pushboolean(L, true);
}
membuff_free(&mbuf);
return 1;
}
Loading…
Cancel
Save