diff --git a/CMakeLists.txt b/CMakeLists.txt
index d1d52ab..7dc03b4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/README.rst b/README.rst
index 28e4b5a..b52a869 100644
--- a/README.rst
+++ b/README.rst
@@ -5,8 +5,8 @@ Ravi Programming Language
:target: https://travis-ci.org/dibyendumajumdar/ravi
Ravi is a derivative/dialect of `Lua 5.3 `_ with limited optional static typing and
-features `MIR `_, `LLVM `_ and `Eclipse OMR `_
-powered JIT compilers. The name Ravi comes from the Sanskrit word for the Sun.
+features `MIR `_ and `LLVM `_ powered JIT compilers.
+The name Ravi comes from the Sanskrit word for the Sun.
Interestingly a precursor to Lua was `Sol `_ 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 `_; only Linux and x86-64 supported for now.
* `LLVM `_ powered JIT compiler
-* `Eclipse OMR `_ powered JIT compiler
* A `distribution with batteries `_.
Documentation
=============
* For the Lua extensions in Ravi see the `Reference Manual `_.
* `MIR JIT Build instructions `_.
-* `OMR JIT Build instructions `_.
* `LLVM JIT Build instructions `_.
* Also see `Ravi Documentation `_.
* and the slides I presented at the `Lua 2015 Workshop `_.
@@ -90,10 +88,10 @@ History
* 2016
- Implemented debugger for Ravi and Lua 5.3 for `Visual Studio Code `_
* 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 `_.
* 2019
- New language feature - `defer` statement
diff --git a/dmr_c/.clang-format b/dmr_c/.clang-format
deleted file mode 100644
index 04bafc9..0000000
--- a/dmr_c/.clang-format
+++ /dev/null
@@ -1,7 +0,0 @@
-BasedOnStyle: LLVM
-IndentWidth: 8
-UseTab: Always
-BreakBeforeBraces: Linux
-AllowShortIfStatementsOnASingleLine: false
-IndentCaseLabels: false
-ColumnLimit: 120
\ No newline at end of file
diff --git a/dmr_c/README.md b/dmr_c/README.md
deleted file mode 100644
index 5e32972..0000000
--- a/dmr_c/README.md
+++ /dev/null
@@ -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
diff --git a/dmr_c/llvm-backend/dmr_c.h b/dmr_c/llvm-backend/dmr_c.h
deleted file mode 100644
index e483731..0000000
--- a/dmr_c/llvm-backend/dmr_c.h
+++ /dev/null
@@ -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
-
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern bool dmrC_llvmcompile(int argc, char **argv, LLVMModuleRef module,
- const char *inputbuffer);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/dmr_c/llvm-backend/sparse-llvm.c b/dmr_c/llvm-backend/sparse-llvm.c
deleted file mode 100644
index 074b54f..0000000
--- a/dmr_c/llvm-backend/sparse-llvm.c
+++ /dev/null
@@ -1,2095 +0,0 @@
-/**
-* Sparse LLVM backend
-*
-* Original copyrights: Pekka Enberg and Jeff Garzik (https://lwn.net/Articles/456709/)
-* Additional copyrights: Dibyendu Majumdar and Luc Van Oostenryck
-*
-* 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
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-struct function {
- LLVMBuilderRef builder;
- LLVMTypeRef type;
- LLVMValueRef fn;
- LLVMModuleRef module;
- LLVMTypeRef return_type;
-};
-
-static LLVMTypeRef type_to_llvmtype(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym, struct symbol *sym_node);
-static LLVMValueRef constant_value(struct dmr_C *C, LLVMModuleRef module, unsigned long long val, LLVMTypeRef dtype);
-
-static const char *get_llvmtypekind_name(LLVMTypeKind kind) {
- switch (kind) {
- case LLVMVoidTypeKind: return "VoidType"; /**< type with no size */
- case LLVMHalfTypeKind: return "HalfFloatType"; /**< 16 bit floating point type */
- case LLVMFloatTypeKind: return "FloatType"; /**< 32 bit floating point type */
- case LLVMDoubleTypeKind: return "DoubleType"; /**< 64 bit floating point type */
- case LLVMX86_FP80TypeKind: return "LongDoubleType"; /**< 80 bit floating point type (X87) */
- case LLVMFP128TypeKind: return "128BitDoubleType"; /**< 128 bit floating point type (112-bit mantissa)*/
- case LLVMPPC_FP128TypeKind: return "128BitPPCDoubleType"; /**< 128 bit floating point type (two 64-bits) */
- case LLVMLabelTypeKind: return "LabelType"; /**< Labels */
- case LLVMIntegerTypeKind: return "IntegerType"; /**< Arbitrary bit width integers */
- case LLVMFunctionTypeKind: return "FunctionType"; /**< Functions */
- case LLVMStructTypeKind: return "StructType"; /**< Structures */
- case LLVMArrayTypeKind: return "ArrayType"; /**< Arrays */
- case LLVMPointerTypeKind: return "PointerType"; /**< Pointers */
- case LLVMVectorTypeKind: return "VectorType"; /**< SIMD 'packed' format, or other vector type */
- case LLVMMetadataTypeKind: return "MetadataType"; /**< Metadata */
- case LLVMX86_MMXTypeKind: return "MMXType"; /**< X86 MMX */
- case LLVMTokenTypeKind: return "TokenType"; /**< Tokens */
- default: assert(0);
- }
- return "";
-}
-
-static LLVMTypeRef get_symnode_type(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym)
-{
- assert(sym->type == SYM_NODE);
- return type_to_llvmtype(C, module, sym->ctype.base_type, sym);
-}
-
-static LLVMTypeRef get_symnode_or_basetype(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym)
-{
- if (sym->type == SYM_NODE) {
- assert(sym->ctype.base_type->type != SYM_NODE);
- return type_to_llvmtype(C, module, sym->ctype.base_type, sym);
- }
- return type_to_llvmtype(C, module, sym, NULL);
-}
-
-
-static LLVMTypeRef func_return_type(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym, struct symbol *sym_node)
-{
- return type_to_llvmtype(C, module, sym->ctype.base_type, sym_node);
-}
-
-static LLVMTypeRef sym_func_type(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym, struct symbol *sym_node)
-{
- LLVMTypeRef *arg_type;
- LLVMTypeRef func_type;
- LLVMTypeRef ret_type;
- struct symbol *arg;
- int n_arg = 0;
-
- /* to avoid strangeness with varargs [for now], we build
- * the function and type anew, for each call. This
- * is probably wrong. We should look up the
- * symbol declaration info.
- */
-
- ret_type = func_return_type(C, module, sym, sym_node);
- if (!ret_type)
- return NULL;
-
- /* count args, build argument type information */
- FOR_EACH_PTR(sym->arguments, arg) {
- n_arg++;
- } END_FOR_EACH_PTR(arg);
-
- arg_type = alloca(n_arg * sizeof(LLVMTypeRef));
-
- int idx = 0;
- FOR_EACH_PTR(sym->arguments, arg) {
- struct symbol *arg_sym = arg;
-
- arg_type[idx] = get_symnode_type(C, module, arg_sym);
- if (!arg_type[idx])
- return NULL;
- idx++;
- } END_FOR_EACH_PTR(arg);
- func_type = LLVMFunctionType(ret_type, arg_type, n_arg,
- sym->variadic);
-
- return func_type;
-}
-
-static LLVMTypeRef sym_array_type(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym, struct symbol *sym_node)
-{
- LLVMTypeRef elem_type;
- struct symbol *base_type;
-
- base_type = sym->ctype.base_type;
- /* empty struct is undefined [6.7.2.1(8)] */
- unsigned int array_bit_size = sym->bit_size;
- if (array_bit_size == 0 || (int)array_bit_size == -1) {
- if (sym_node != NULL)
- array_bit_size = sym_node->bit_size;
- }
- if (base_type->bit_size == 0 || base_type->bit_size == -1 || array_bit_size == 0 || (int)array_bit_size == -1) {
- fprintf(stderr, "array size can not be determined\n");
- return NULL;
- }
- elem_type = type_to_llvmtype(C, module, base_type, sym_node);
- if (!elem_type)
- return NULL;
-
- return LLVMArrayType(elem_type, array_bit_size / base_type->bit_size);
-}
-
-#define MAX_STRUCT_MEMBERS 256
-
-static LLVMTypeRef sym_struct_type(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym, struct symbol *sym_node)
-{
- LLVMTypeRef elem_types[MAX_STRUCT_MEMBERS];
- struct symbol *member;
- char buffer[256];
- LLVMTypeRef ret;
- unsigned nr = 0;
- (void)sym_node;
- snprintf(buffer, sizeof(buffer), "struct.%s", sym->ident ? sym->ident->name : "anno");
- ret = LLVMStructCreateNamed(LLVMGetModuleContext(module), buffer);
- /* set ->aux to avoid recursion */
- sym->aux = ret;
-
- FOR_EACH_PTR(sym->symbol_list, member) {
- LLVMTypeRef member_type;
-
- if (nr >= MAX_STRUCT_MEMBERS) {
- // TODO error message
- return NULL;
- }
-
- member_type = get_symnode_type(C, module, member);
- if (!member_type)
- return NULL;
-
- elem_types[nr++] = member_type;
- } END_FOR_EACH_PTR(member);
-
- LLVMStructSetBody(ret, elem_types, nr, 0 /* packed? */);
- return ret;
-}
-
-static LLVMTypeRef sym_union_type(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym, struct symbol *sym_node)
-{
- LLVMTypeRef elem_types[1];
- char buffer[256];
- LLVMTypeRef type;
- (void)C; (void)sym_node;
- snprintf(buffer, sizeof(buffer), "union.%s", sym->ident ? sym->ident->name : "anno");
- type = LLVMStructCreateNamed(LLVMGetModuleContext(module), buffer);
- /* set ->aux to avoid recursion */
- sym->aux = type;
-
- unsigned union_size;
-
- if (sym->bit_size > 0 && sym->bit_size != -1) {
- /*
- * There's no union support in the LLVM API so we treat unions as
- * opaque structs. The downside is that we lose type information on the
- * members but as LLVM doesn't care, neither do we.
- */
- union_size = sym->bit_size / 8;
- if (union_size > 0) {
- elem_types[0] = LLVMArrayType(LLVMInt8TypeInContext(LLVMGetModuleContext(module)), union_size);
-
- LLVMStructSetBody(type, elem_types, 1, 0 /* packed? */);
- }
- }
- return type;
-}
-
-static LLVMTypeRef sym_ptr_type(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym, struct symbol *sym_node)
-{
- LLVMTypeRef type;
-
- /* 'void *' is treated like 'char *' */
- if (dmrC_is_void_type(C->S, sym->ctype.base_type))
- type = LLVMInt8TypeInContext(LLVMGetModuleContext(module));
- else {
- type = type_to_llvmtype(C, module, sym->ctype.base_type, sym_node);
- if (!type)
- return NULL;
- }
- return LLVMPointerType(type, 0);
-}
-
-static LLVMTypeRef int_type_by_size(LLVMModuleRef module, int size)
-{
- LLVMTypeRef ret = NULL;
- switch (size) {
- case 1:
- ret = LLVMInt1TypeInContext(LLVMGetModuleContext(module));
- break;
- case 8:
- ret = LLVMInt8TypeInContext(LLVMGetModuleContext(module));
- break;
- case 16:
- ret = LLVMInt16TypeInContext(LLVMGetModuleContext(module));
- break;
- case 32:
- ret = LLVMInt32TypeInContext(LLVMGetModuleContext(module));
- break;
- case 64:
- ret = LLVMInt64TypeInContext(LLVMGetModuleContext(module));
- break;
- default:
- fprintf(stderr, "invalid bit size %d\n", size);
- }
- return ret;
-}
-
-static LLVMTypeRef sym_basetype_type(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym, struct symbol *sym_node)
-{
- LLVMTypeRef ret = NULL;
- (void)sym_node;
- if (dmrC_is_float_type(C->S, sym)) {
- switch (sym->bit_size) {
- case 32:
- ret = LLVMFloatTypeInContext(LLVMGetModuleContext(module));
- break;
- case 64:
- ret = LLVMDoubleTypeInContext(LLVMGetModuleContext(module));
- break;
- case 80:
- ret = LLVMX86FP80TypeInContext(LLVMGetModuleContext(module));
- break;
- default:
- fprintf(stderr, "invalid bit size %d for type %d\n", sym->bit_size, sym->type);
- return NULL;
- }
- }
- else {
- if (sym->bit_size == -1)
- ret = LLVMVoidTypeInContext(LLVMGetModuleContext(module));
- else
- ret = int_type_by_size(module, sym->bit_size);
- }
-
- return ret;
-}
-
-static int is_aggregate_type(struct symbol *sym)
-{
- if (sym->type == SYM_NODE)
- return is_aggregate_type(sym->ctype.base_type);
- switch (sym->type) {
- case SYM_UNION:
- case SYM_STRUCT:
- case SYM_ARRAY:
- return true;
- default:
- return false;
- }
-}
-
-static LLVMTypeRef type_to_llvmtype(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym, struct symbol *sym_node)
-{
- LLVMTypeRef ret = NULL;
-
- assert(sym->type != SYM_NODE);
- assert(sym_node == NULL || sym_node->type == SYM_NODE);
- if (sym->aux)
- return sym->aux;
-
- switch (sym->type) {
- case SYM_BITFIELD:
- ret = LLVMIntTypeInContext(LLVMGetModuleContext(module), sym->bit_size);
- break;
- case SYM_RESTRICT:
- case SYM_ENUM:
- ret = type_to_llvmtype(C, module, sym->ctype.base_type, sym_node);
- break;
- case SYM_BASETYPE:
- ret = sym_basetype_type(C, module, sym, sym_node);
- break;
- case SYM_PTR:
- ret = sym_ptr_type(C, module, sym, sym_node);
- break;
- case SYM_UNION:
- ret = sym_union_type(C, module, sym, sym_node);
- break;
- case SYM_STRUCT:
- ret = sym_struct_type(C, module, sym, sym_node);
- break;
- case SYM_ARRAY:
- ret = sym_array_type(C, module, sym, sym_node);
- break;
- case SYM_FN:
- ret = sym_func_type(C, module, sym, sym_node);
- break;
- default:
- return NULL;
- }
-
- /* cache the result */
- sym->aux = ret;
- return ret;
-}
-
-static LLVMTypeRef insn_symbol_type(struct dmr_C *C, LLVMModuleRef module, struct instruction *insn)
-{
- if (insn->type) {
- //printf("insn %s sym type %s\n", dmrC_show_instruction(C, insn), dmrC_get_type_name(insn->type->type));
- return get_symnode_or_basetype(C, module, insn->type);
- }
- LLVMTypeRef ret = int_type_by_size(module, insn->size);
- if (!ret) {
- dmrC_sparse_error(C, insn->pos, "invalid bit size %d", insn->size);
- }
- return ret;
-}
-
-static LLVMLinkage data_linkage(struct dmr_C *C, struct symbol *sym)
-{
- (void)C;
- if (sym->ctype.modifiers & MOD_STATIC)
- return LLVMPrivateLinkage;
- return LLVMExternalLinkage;
-}
-
-static LLVMLinkage function_linkage(struct dmr_C *C, struct symbol *sym)
-{
- (void)C;
- if (sym->ctype.modifiers & MOD_STATIC)
- return LLVMInternalLinkage;
- return LLVMExternalLinkage;
-}
-
-static LLVMValueRef build_cast(struct dmr_C *C, struct function *fn, LLVMValueRef val, LLVMTypeRef dtype, const char *target_name, int unsigned_cast)
-{
- LLVMTypeRef valtype = LLVMTypeOf(val);
- LLVMTypeKind valkind = LLVMGetTypeKind(valtype);
- LLVMTypeKind dkind = LLVMGetTypeKind(dtype);
- LLVMOpcode op;
- (void)C;
- switch (dkind) {
- case LLVMIntegerTypeKind: {
- switch (valkind) {
- case LLVMPointerTypeKind:
- op = LLVMPtrToInt;
- break;
- case LLVMIntegerTypeKind: {
- unsigned val_width = LLVMGetIntTypeWidth(valtype);
- unsigned target_width = LLVMGetIntTypeWidth(dtype);
- if (target_width < val_width)
- op = LLVMTrunc;
- else if (target_width == val_width)
- op = LLVMBitCast;
- else
- op = unsigned_cast ? LLVMZExt : LLVMSExt;
- break;
- }
- case LLVMFloatTypeKind:
- case LLVMDoubleTypeKind:
- op = LLVMFPToSI;
- break;
- default:
- fprintf(stderr, "unsupported value type %s in cast to integer value\n", get_llvmtypekind_name(valkind));
- return NULL;
- }
- break;
- }
- case LLVMPointerTypeKind: {
- switch (valkind) {
- case LLVMPointerTypeKind:
- op = LLVMBitCast;
- break;
- case LLVMIntegerTypeKind:
- op = LLVMIntToPtr;
- break;
- default:
- fprintf(stderr, "unsupported value type %s in cast to ptr\n", get_llvmtypekind_name(valkind));
- return NULL;
- }
- break;
- }
- case LLVMFloatTypeKind:
- case LLVMDoubleTypeKind: {
- switch (valkind) {
- case LLVMIntegerTypeKind:
- op = unsigned_cast ? LLVMUIToFP : LLVMSIToFP;
- break;
- case LLVMFloatTypeKind: {
- if (dkind == LLVMFloatTypeKind)
- op = LLVMBitCast;
- else
- op = LLVMFPExt;
- break;
- }
- case LLVMDoubleTypeKind: {
- if (dkind == LLVMFloatTypeKind)
- op = LLVMFPTrunc;
- else
- op = LLVMBitCast;
- break;
- }
- default:
- fprintf(stderr, "unsupported value type %s in cast to floating point value\n", get_llvmtypekind_name(valkind));
- return NULL;
- }
- break;
- }
- default:
- if (dkind == valkind)
- op = LLVMBitCast;
- else {
- fprintf(stderr, "unsupported target type %s in cast from value kind %s\n", get_llvmtypekind_name(dkind), get_llvmtypekind_name(valkind));
- return NULL;
- }
- }
- return LLVMBuildCast(fn->builder, op, val, dtype, target_name);
-}
-
-
-#define MAX_PSEUDO_NAME 64
-
-static const char * pseudo_name(struct dmr_C *C, pseudo_t pseudo, char *buf, size_t len)
-{
- (void)C;
- buf[0] = '\0';
- switch (pseudo->type) {
- case PSEUDO_REG:
- snprintf(buf, len, "R%d", pseudo->nr);
- break;
- case PSEUDO_PHI:
- snprintf(buf, len, "PHI%d", pseudo->nr);
- break;
- case PSEUDO_SYM:
- case PSEUDO_VAL:
- case PSEUDO_ARG:
- case PSEUDO_VOID:
- break;
- default:
- assert(0);
- }
-
- return buf;
-}
-
-static LLVMValueRef build_local(struct dmr_C *C, struct function *fn, struct symbol *sym)
-{
- const char *name = dmrC_show_ident(C, sym->ident);
- LLVMTypeRef type = get_symnode_type(C, fn->module, sym);
- LLVMValueRef result;
- char localname[256] = { 0 };
- snprintf(localname, sizeof localname, "%s_%p.", name, sym);
- if (dmrC_is_static(sym) || dmrC_is_extern(sym) || dmrC_is_toplevel(sym)) {
- result = LLVMGetNamedGlobal(fn->module, localname);
- if (!result) {
- result = LLVMAddGlobal(fn->module, type, localname);
- if (!dmrC_is_extern(sym))
- LLVMSetLinkage(result, LLVMInternalLinkage);
- else
- LLVMSetLinkage(result, LLVMExternalLinkage);
- }
- }
- else {
- /* insert alloca into entry block */
- /* LLVM requires allocas to be at the start */
- LLVMBasicBlockRef entrybbr = LLVMGetEntryBasicBlock(fn->fn);
- /* Use temporary Builder as we don't want to mess the function builder */
- LLVMBuilderRef tmp_builder = LLVMCreateBuilderInContext(LLVMGetModuleContext(fn->module));
- LLVMValueRef firstins = LLVMGetFirstInstruction(entrybbr);
- if (firstins)
- LLVMPositionBuilderBefore(tmp_builder, firstins);
- else
- LLVMPositionBuilderAtEnd(tmp_builder, entrybbr);
- /* Since multiple locals may have same name but in different scopes we
- append the symbol's address to make each variable unique */
- result = LLVMBuildAlloca(tmp_builder, type, localname);
- if (sym->initialized && is_aggregate_type(sym)) {
- LLVMValueRef memsetfunc = LLVMGetNamedFunction(fn->module, "llvm.memset.p0i8.i32");
- assert(memsetfunc);
- LLVMValueRef resulti8 = LLVMBuildBitCast(fn->builder, result, LLVMPointerType(LLVMInt8TypeInContext(LLVMGetModuleContext(fn->module)), 0), LLVMGetValueName(result));
- LLVMValueRef args[5];
- args[0] = resulti8;
- args[1] = LLVMConstInt(LLVMInt8TypeInContext(LLVMGetModuleContext(fn->module)), 0, 0);
- args[2] = LLVMConstInt(LLVMInt32TypeInContext(LLVMGetModuleContext(fn->module)), sym->bit_size / C->target->bits_in_char, 0);
- args[3] = LLVMConstInt(LLVMInt32TypeInContext(LLVMGetModuleContext(fn->module)), sym->ctype.alignment, 0);
- args[4] = LLVMConstInt(LLVMInt1TypeInContext(LLVMGetModuleContext(fn->module)), 0, 0);
- LLVMBuildCall(fn->builder, memsetfunc, args, 5, "");
- }
- LLVMDisposeBuilder(tmp_builder);
- }
- sym->priv = result;
- return result;
-}
-
-static LLVMValueRef get_sym_value(struct dmr_C *C, struct function *fn, pseudo_t pseudo)
-{
- LLVMValueRef result = NULL;
- struct symbol *sym = pseudo->sym;
- struct expression *expr;
-
- result = (LLVMValueRef)sym->priv;
- if (result)
- return result;
-
- assert(sym->bb_target == NULL);
-
- expr = sym->initializer;
- if (expr &&
- (!sym->ident ||
- (sym->ident && (expr->type == EXPR_VALUE || expr->type == EXPR_FVALUE)))) {
- switch (expr->type) {
- case EXPR_STRING: {
- const char *s = expr->string->data;
- LLVMValueRef indices[] = { LLVMConstInt(LLVMInt64TypeInContext(LLVMGetModuleContext(fn->module)), 0, 0),
- LLVMConstInt(LLVMInt64TypeInContext(LLVMGetModuleContext(fn->module)), 0, 0) };
- LLVMValueRef data;
-
- data = LLVMAddGlobal(fn->module, LLVMArrayType(LLVMInt8TypeInContext(LLVMGetModuleContext(fn->module)), strlen(s) + 1), ".str");
- LLVMSetLinkage(data, LLVMPrivateLinkage);
- LLVMSetGlobalConstant(data, 1);
- char *scopy = dmrC_allocator_allocate(&C->byte_allocator, strlen(s) + 1);
- strcpy(scopy, s);
- LLVMSetInitializer(data, LLVMConstStringInContext(LLVMGetModuleContext(fn->module), scopy, strlen(scopy) + 1, true));
-
- result = LLVMConstGEP(data, indices, ARRAY_SIZE(indices));
- sym->priv = result;
- break;
- }
- case EXPR_SYMBOL: {
- dmrC_sparse_error(C, expr->pos, "unresolved symbol reference in initializer\n");
- dmrC_show_expression(C, expr);
- return NULL;
- break;
- }
- case EXPR_VALUE: {
- LLVMTypeRef symtype = get_symnode_type(C, fn->module, sym);
- if (symtype == NULL) {
- dmrC_sparse_error(C, expr->pos, "invalid symbol type\n");
- dmrC_show_expression(C, expr);
- return NULL;
- }
- result = build_local(C, fn, sym);
- if (!result)
- return result;
- LLVMValueRef value = constant_value(C, fn->module, expr->value, symtype);
- if (dmrC_is_static(sym))
- LLVMSetInitializer(result, value);
- else
- LLVMBuildStore(fn->builder, value, result);
- sym->priv = result;
- break;
- }
- case EXPR_FVALUE: {
- LLVMTypeRef symtype = get_symnode_type(C, fn->module, sym);
- if (symtype == NULL) {
- dmrC_sparse_error(C, expr->pos, "invalid symbol type\n");
- dmrC_show_expression(C, expr);
- return NULL;
- }
- result = build_local(C, fn, sym);
- if (!result)
- return result;
- if (dmrC_is_static(sym))
- LLVMSetInitializer(result, LLVMConstReal(symtype, expr->fvalue));
- else
- LLVMBuildStore(fn->builder, LLVMConstReal(symtype, expr->fvalue), result);
- sym->priv = result;
- break;
- }
- default:
- dmrC_sparse_error(C, expr->pos, "unsupported expr type in initializer: %d\n", expr->type);
- dmrC_show_expression(C, expr);
- return NULL;
- }
- }
- else {
- const char *name = dmrC_show_ident(C, sym->ident);
- LLVMTypeRef type = get_symnode_type(C, fn->module, sym);
- if (LLVMGetTypeKind(type) == LLVMFunctionTypeKind) {
- result = LLVMGetNamedFunction(fn->module, name);
- if (!result)
- result = LLVMAddFunction(fn->module, name, type);
- sym->priv = result;
- }
- else if (dmrC_is_extern(sym) || dmrC_is_toplevel(sym)) {
- result = LLVMGetNamedGlobal(fn->module, name);
- if (!result) {
- result = LLVMAddGlobal(fn->module, type, name);
- if (dmrC_is_extern(sym))
- LLVMSetLinkage(result, LLVMExternalLinkage);
- }
- sym->priv = result;
- }
- else {
- if (dmrC_is_static(sym) && sym->initializer) {
- dmrC_sparse_error(C, sym->initializer->pos, "unsupported initializer for local static variable\n");
- dmrC_show_expression(C, sym->initializer);
- return NULL;
- }
- result = build_local(C, fn, sym);
- if (!result)
- return result;
- if (dmrC_is_static(sym)) {
- LLVMSetInitializer(result, LLVMConstNull(type));
- }
- sym->priv = result;
- }
- }
- return result;
-}
-
-static LLVMValueRef constant_value(struct dmr_C *C, LLVMModuleRef module, unsigned long long val, LLVMTypeRef dtype)
-{
- LLVMTypeRef itype;
- LLVMValueRef result;
-
- LLVMTypeKind kind = LLVMGetTypeKind(dtype);
- switch (kind) {
- case LLVMPointerTypeKind:
- itype = LLVMIntTypeInContext(LLVMGetModuleContext(module), C->target->bits_in_pointer);
- result = LLVMConstInt(itype, val, 0);
- result = LLVMConstIntToPtr(result, dtype);
- break;
- case LLVMIntegerTypeKind:
- result = LLVMConstInt(dtype, val, 0);
- break;
- case LLVMFloatTypeKind:
- case LLVMDoubleTypeKind:
- result = LLVMConstReal(dtype, (double)(long long)val);
- break;
- default:
- fprintf(stderr, "unsupported pseudo value kind %s\n", get_llvmtypekind_name(kind));
- return NULL;
- }
- return result;
-}
-
-static LLVMValueRef val_to_value(struct dmr_C *C, struct function *fn, unsigned long long val, struct symbol *ctype)
-{
- LLVMTypeRef dtype;
-
- if (!ctype)
- return NULL;
- dtype = get_symnode_or_basetype(C, fn->module, ctype);
- if (!dtype)
- return NULL;
- return constant_value(C, fn->module, val, dtype);
-}
-
-static LLVMValueRef pseudo_to_value(struct dmr_C *C, struct function *fn, struct symbol *ctype, pseudo_t pseudo)
-{
- LLVMValueRef result = NULL;
-
- switch (pseudo->type) {
- case PSEUDO_REG:
- result = pseudo->priv;
- break;
- case PSEUDO_SYM:
- result = get_sym_value(C, fn, pseudo);
- break;
- case PSEUDO_VAL:
- result = val_to_value(C, fn, pseudo->value, ctype);
- break;
- case PSEUDO_ARG:
- result = LLVMGetParam(fn->fn, pseudo->nr - 1);
- break;
- case PSEUDO_PHI:
- result = pseudo->priv;
- break;
- case PSEUDO_VOID:
- result = NULL;
- break;
- default:
- break;
- }
- if (!result) {
- fprintf(stderr, "error: no result for pseudo\n");
- return NULL;
- }
- return result;
-}
-
-static LLVMValueRef ptr_toint(struct dmr_C *C, struct function *fn, LLVMValueRef val)
-{
- if (LLVMGetTypeKind(LLVMTypeOf(val)) == LLVMPointerTypeKind) {
- LLVMTypeRef dtype = LLVMIntTypeInContext(LLVMGetModuleContext(fn->module), C->target->bits_in_pointer);
- val = LLVMBuildPtrToInt(fn->builder, val, dtype, LLVMGetValueName(val));
- }
- return val;
-}
-
-#if 0
-
-static LLVMValueRef calc_gep(struct dmr_C *C, struct function *fn, LLVMBuilderRef builder, LLVMValueRef base, LLVMValueRef off)
-{
- LLVMTypeRef type = LLVMTypeOf(base);
- unsigned int as = LLVMGetPointerAddressSpace(type);
- LLVMTypeRef bytep = LLVMPointerType(LLVMInt8TypeInContext(LLVMGetModuleContext(fn->module)), as);
- LLVMValueRef addr;
-
- /* convert base to char* type */
- base = LLVMBuildPointerCast(builder, base, bytep, "");
- /* addr = base + off */
- addr = LLVMBuildInBoundsGEP(builder, base, &off, 1, "");
- /* convert back to the actual pointer type */
- addr = LLVMBuildPointerCast(builder, addr, type, "");
- return addr;
-}
-
-#endif
-
-static LLVMRealPredicate translate_fop(int opcode)
-{
- static const LLVMRealPredicate trans_tbl[] = {
- [OP_SET_EQ] = LLVMRealOEQ,
- [OP_SET_NE] = LLVMRealUNE,
- [OP_SET_LE] = LLVMRealOLE,
- [OP_SET_GE] = LLVMRealOGE,
- [OP_SET_LT] = LLVMRealOLT,
- [OP_SET_GT] = LLVMRealOGT,
- /* Are these used with FP? */
- [OP_SET_B] = LLVMRealOLT,
- [OP_SET_A] = LLVMRealOGT,
- [OP_SET_BE] = LLVMRealOLE,
- [OP_SET_AE] = LLVMRealOGE,
- };
-
- return trans_tbl[opcode];
-}
-
-static LLVMIntPredicate translate_op(int opcode)
-{
- static const LLVMIntPredicate trans_tbl[] = {
- [OP_SET_EQ] = LLVMIntEQ,
- [OP_SET_NE] = LLVMIntNE,
- [OP_SET_LE] = LLVMIntSLE,
- [OP_SET_GE] = LLVMIntSGE,
- [OP_SET_LT] = LLVMIntSLT,
- [OP_SET_GT] = LLVMIntSGT,
- [OP_SET_B] = LLVMIntULT,
- [OP_SET_A] = LLVMIntUGT,
- [OP_SET_BE] = LLVMIntULE,
- [OP_SET_AE] = LLVMIntUGE,
- };
-
- return trans_tbl[opcode];
-}
-
-/**
-* Convert the pseudo to a value, and cast it to the expected type of the
-* instruction. If ptrtoint is true then convert pointer values to integers.
-*/
-static LLVMValueRef get_operand(struct dmr_C *C, struct function *fn, struct symbol *ctype, pseudo_t pseudo, bool ptrtoint, bool unsigned_cast)
-{
- LLVMValueRef target;
-
- LLVMTypeRef instruction_type = get_symnode_or_basetype(C, fn->module, ctype);
- if (instruction_type == NULL)
- return NULL;
- target = pseudo_to_value(C, fn, ctype, pseudo);
- if (!target)
- return NULL;
- if (ptrtoint && dmrC_is_ptr_type(ctype))
- target = ptr_toint(C, fn, target);
- else
- target = build_cast(C, fn, target, instruction_type, LLVMGetValueName(target), unsigned_cast);
- return target;
-}
-
-static LLVMValueRef output_op_binary(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef lhs, rhs, target;
- char target_name[64];
-
- LLVMTypeRef instruction_type = get_symnode_or_basetype(C, fn->module, insn->type);
-
- lhs = get_operand(C, fn, insn->type, insn->src1, 1, 0);
- if (!lhs)
- return NULL;
-
- rhs = get_operand(C, fn, insn->type, insn->src2, 1, 0);
- if (!rhs)
- return NULL;
-
- pseudo_name(C, insn->target, target_name, sizeof target_name);
-
- switch (insn->opcode) {
- /* Binary */
- case OP_ADD:
- if (dmrC_is_float_type(C->S, insn->type))
- target = LLVMBuildFAdd(fn->builder, lhs, rhs, target_name);
- else
- target = LLVMBuildAdd(fn->builder, lhs, rhs, target_name);
- break;
- case OP_SUB:
- if (dmrC_is_float_type(C->S, insn->type))
- target = LLVMBuildFSub(fn->builder, lhs, rhs, target_name);
- else
- target = LLVMBuildSub(fn->builder, lhs, rhs, target_name);
- break;
- case OP_MULU:
- if (dmrC_is_float_type(C->S, insn->type))
- target = LLVMBuildFMul(fn->builder, lhs, rhs, target_name);
- else
- target = LLVMBuildMul(fn->builder, lhs, rhs, target_name);
- break;
- case OP_MULS:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildMul(fn->builder, lhs, rhs, target_name);
- break;
- case OP_DIVU:
- if (dmrC_is_float_type(C->S, insn->type))
- target = LLVMBuildFDiv(fn->builder, lhs, rhs, target_name);
- else
- target = LLVMBuildUDiv(fn->builder, lhs, rhs, target_name);
- break;
- case OP_DIVS:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildSDiv(fn->builder, lhs, rhs, target_name);
- break;
- case OP_MODU:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildURem(fn->builder, lhs, rhs, target_name);
- break;
- case OP_MODS:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildSRem(fn->builder, lhs, rhs, target_name);
- break;
- case OP_SHL:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildShl(fn->builder, lhs, rhs, target_name);
- break;
- case OP_LSR:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildLShr(fn->builder, lhs, rhs, target_name);
- break;
- case OP_ASR:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildAShr(fn->builder, lhs, rhs, target_name);
- break;
-
- /* Logical */
- case OP_AND:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildAnd(fn->builder, lhs, rhs, target_name);
- break;
- case OP_OR:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildOr(fn->builder, lhs, rhs, target_name);
- break;
- case OP_XOR:
- assert(!dmrC_is_float_type(C->S, insn->type));
- target = LLVMBuildXor(fn->builder, lhs, rhs, target_name);
- break;
- case OP_AND_BOOL: {
- LLVMValueRef lhs_nz, rhs_nz;
- LLVMTypeRef dst_type;
-
- lhs_nz = LLVMBuildIsNotNull(fn->builder, lhs, "");
- rhs_nz = LLVMBuildIsNotNull(fn->builder, rhs, "");
- target = LLVMBuildAnd(fn->builder, lhs_nz, rhs_nz, target_name);
-
- dst_type = insn_symbol_type(C, fn->module, insn);
- if (!dst_type)
- return NULL;
- target = LLVMBuildZExt(fn->builder, target, dst_type, target_name);
- break;
- }
- case OP_OR_BOOL: {
- LLVMValueRef lhs_nz, rhs_nz;
- LLVMTypeRef dst_type;
-
- lhs_nz = LLVMBuildIsNotNull(fn->builder, lhs, "");
- rhs_nz = LLVMBuildIsNotNull(fn->builder, rhs, "");
- target = LLVMBuildOr(fn->builder, lhs_nz, rhs_nz, target_name);
-
- dst_type = insn_symbol_type(C, fn->module, insn);
- if (!dst_type)
- return NULL;
- target = LLVMBuildZExt(fn->builder, target, dst_type, target_name);
- break;
- }
-
- default:
- assert(0);
- return NULL;
- }
-
- target = build_cast(C, fn, target, instruction_type, target_name, 0);
- insn->target->priv = target;
-
- return target;
-}
-
-static inline struct symbol *pseudo_type(struct dmr_C *C, pseudo_t pseudo)
-{
- switch (pseudo->type) {
- case PSEUDO_SYM:
- case PSEUDO_ARG:
- return pseudo->sym;
- case PSEUDO_REG:
- case PSEUDO_PHI:
- return pseudo->def->type;
- case PSEUDO_VAL:
- return C->target->size_t_ctype;
- case PSEUDO_VOID:
- default:
- return &C->S->void_ctype;
- }
-}
-
-static LLVMValueRef output_op_compare(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef lhs, rhs, target;
- char target_name[64];
-
- if (insn->src1->type == PSEUDO_VAL)
- lhs = val_to_value(C, fn, insn->src1->value, pseudo_type(C, insn->src2));
- else
- lhs = pseudo_to_value(C, fn, insn->type, insn->src1);
- if (!lhs)
- return NULL;
- if (insn->src2->type == PSEUDO_VAL)
- rhs = val_to_value(C, fn, insn->src2->value, pseudo_type(C, insn->src1));
- else
- rhs = pseudo_to_value(C, fn, insn->type, insn->src2);
- if (!rhs)
- return NULL;
-
- pseudo_name(C, insn->target, target_name, sizeof target_name);
-
- LLVMTypeRef dst_type = insn_symbol_type(C, fn->module, insn);
- if (!dst_type)
- return NULL;
-
- switch (LLVMGetTypeKind(LLVMTypeOf(lhs))) {
- case LLVMPointerTypeKind: {
- lhs = LLVMBuildPtrToInt(fn->builder, lhs, LLVMIntTypeInContext(LLVMGetModuleContext(fn->module), C->target->bits_in_pointer), "");
- if (LLVMGetTypeKind(LLVMTypeOf(rhs)) == LLVMPointerTypeKind) {
- rhs = LLVMBuildPtrToInt(fn->builder, rhs, LLVMIntTypeInContext(LLVMGetModuleContext(fn->module), C->target->bits_in_pointer), "");
- }
- LLVMIntPredicate op = translate_op(insn->opcode);
- target = LLVMBuildICmp(fn->builder, op, lhs, rhs, target_name);
- break;
- }
-
- case LLVMIntegerTypeKind: {
- LLVMIntPredicate op = translate_op(insn->opcode);
- target = LLVMBuildICmp(fn->builder, op, lhs, rhs, target_name);
- break;
- }
-
- case LLVMHalfTypeKind:
- case LLVMFloatTypeKind:
- case LLVMDoubleTypeKind:
- case LLVMX86_FP80TypeKind:
- case LLVMFP128TypeKind:
- case LLVMPPC_FP128TypeKind: {
- LLVMRealPredicate op = translate_fop(insn->opcode);
-
- target = LLVMBuildFCmp(fn->builder, op, lhs, rhs, target_name);
- break;
- }
- default:
- assert(0);
- return NULL;
- }
-
- target = LLVMBuildZExt(fn->builder, target, dst_type, target_name);
-
- insn->target->priv = target;
-
- return target;
-}
-
-static LLVMValueRef output_op_ret(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- pseudo_t pseudo = insn->src;
-
- if (pseudo && pseudo != VOID_PSEUDO(C) && LLVMGetTypeKind(fn->return_type) != LLVMVoidTypeKind) {
- LLVMValueRef result = get_operand(C, fn, insn->type, pseudo, 0, 0);
- if (!result)
- return NULL;
- return LLVMBuildRet(fn->builder, result);
- }
- else
- return LLVMBuildRetVoid(fn->builder);
-}
-
-static LLVMValueRef calc_memop_addr(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMTypeRef int_type, addr_type;
- LLVMValueRef src, off, addr;
- unsigned int as;
-
- /* int type large enough to hold a pointer */
- int_type = LLVMIntTypeInContext(LLVMGetModuleContext(fn->module), C->target->bits_in_pointer);
- off = LLVMConstInt(int_type, (int)insn->offset, 0);
-
- /* convert src to the effective pointer type */
- src = pseudo_to_value(C, fn, insn->type, insn->src);
- if (!src)
- return NULL;
- as = LLVMGetPointerAddressSpace(LLVMTypeOf(src));
- LLVMTypeRef symtype = insn_symbol_type(C, fn->module, insn);
- if (!symtype)
- return NULL;
- addr_type = LLVMPointerType(symtype, as);
-#if 1
- src = ptr_toint(C, fn, src);
- addr = LLVMBuildAdd(fn->builder, src, off, "");
- addr = LLVMBuildIntToPtr(fn->builder, addr, addr_type, "");
-#else
- src = LLVMBuildPointerCast(fn->builder, src, addr_type, "");
-
- /* addr = src + off */
- addr = calc_gep(C, fn->builder, src, off);
-#endif
- return addr;
-}
-
-
-static LLVMValueRef output_op_load(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef addr, target;
- char name[MAX_PSEUDO_NAME];
-
- addr = calc_memop_addr(C, fn, insn);
- if (!addr)
- return NULL;
-
- /* perform load */
- pseudo_name(C, insn->target, name, sizeof name);
- target = LLVMBuildLoad(fn->builder, addr, name);
-
- insn->target->priv = target;
- return target;
-}
-
-static LLVMValueRef output_op_store(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef addr, target_in;
- LLVMTypeRef desttype;
-
- if (is_aggregate_type(insn->type)) {
- dmrC_sparse_error(C, insn->pos, "store to aggregate type is not yet supported, failure at insn %s\n", dmrC_show_instruction(C, insn));
- return NULL;
- }
-
- addr = calc_memop_addr(C, fn, insn);
- if (!addr)
- return NULL;
-
- target_in = pseudo_to_value(C, fn, insn->type, insn->target);
- if (!target_in)
- return NULL;
-
- desttype = insn_symbol_type(C, fn->module, insn);
- if (!desttype)
- return NULL;
-
- /* Cast to the right type - to resolve issue with union types */
- target_in = build_cast(C, fn, target_in, desttype, LLVMGetValueName(target_in), 0);
- if (!target_in)
- return NULL;
-
- /* perform store */
- return LLVMBuildStore(fn->builder, target_in, addr);
-}
-
-static LLVMValueRef bool_value(struct dmr_C *C, struct function *fn, LLVMValueRef value)
-{
- (void)C;
- LLVMTypeRef type = LLVMTypeOf(value);
- if (type != LLVMInt1TypeInContext(LLVMGetModuleContext(fn->module))) {
- LLVMTypeKind kind = LLVMGetTypeKind(type);
- switch (kind) {
- case LLVMPointerTypeKind:
- case LLVMIntegerTypeKind:
- value = LLVMBuildIsNotNull(fn->builder, value, "cond");
- break;
- case LLVMFloatTypeKind:
- case LLVMDoubleTypeKind:
- value = LLVMBuildFCmp(fn->builder, LLVMRealUNE, value, LLVMConstReal(type, 0.0), "cond");
- break;
- default:
- return NULL;
- }
- }
- return value;
-}
-
-static LLVMValueRef output_op_cbr(struct dmr_C *C, struct function *fn, struct instruction *br)
-{
- // FIXME - NEW_SSA changes appear to result in cond being PSEUDO_VAL in some cases
- // This is a workaround for VALUE PSEUDO appearing in cond
- struct symbol *ctype = br->type;
- if (!ctype && br->cond->type == PSEUDO_VAL)
- ctype = &C->S->llong_ctype;
- LLVMValueRef cond = pseudo_to_value(C, fn, ctype, br->cond);
- if (cond)
- cond = bool_value(C, fn, cond);
- if (!cond) {
- dmrC_sparse_error(C, br->pos, "failure at insn %s\n", dmrC_show_instruction(C, br));
- return NULL;
- }
- return LLVMBuildCondBr(fn->builder, cond,
- br->bb_true->priv,
- br->bb_false->priv);
-}
-
-static LLVMValueRef output_op_br(struct dmr_C *C, struct function *fn, struct instruction *br)
-{
- (void)C;
- return LLVMBuildBr(fn->builder, br->bb_true->priv);
-}
-
-
-static LLVMValueRef output_op_sel(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef target, src1, src2, src3;
- LLVMTypeRef desttype = insn_symbol_type(C, fn->module, insn);
- if (!desttype)
- return NULL;
-
- src1 = pseudo_to_value(C, fn, insn->type, insn->src1);
- if (!src1)
- return NULL;
- src1 = bool_value(C, fn, src1);
- if (!src1)
- return NULL;
-
- src2 = get_operand(C, fn, insn->type, insn->src2, 0, 0);
- if (!src2)
- return NULL;
- src3 = get_operand(C, fn, insn->type, insn->src3, 0, 0);
- if (!src3)
- return NULL;
-
- target = LLVMBuildSelect(fn->builder, src1, src2, src3, "select");
-
- insn->target->priv = target;
- return target;
-}
-
-static LLVMValueRef output_op_switch(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef sw_val, target;
- struct basic_block *def = NULL;
- struct multijmp *jmp;
- int n_jmp = 0;
-
- FOR_EACH_PTR(insn->multijmp_list, jmp) {
- if (jmp->begin <= jmp->end) { /* case M..N */
- n_jmp += (jmp->end - jmp->begin) + 1;
- }
- else /* default case */
- def = jmp->target;
- } END_FOR_EACH_PTR(jmp);
-
- sw_val = pseudo_to_value(C, fn, insn->type, insn->target);
- if (!sw_val)
- return NULL;
- target = LLVMBuildSwitch(fn->builder, sw_val,
- def ? def->priv : NULL, n_jmp);
-
- FOR_EACH_PTR(insn->multijmp_list, jmp) {
- long long val;
- for (val = jmp->begin; val <= jmp->end; val++) {
- LLVMValueRef value = LLVMConstInt(LLVMTypeOf(sw_val), val, 0);
- LLVMAddCase(target, value, jmp->target->priv);
- }
- } END_FOR_EACH_PTR(jmp);
-
- return target;
-}
-
-static struct symbol *get_function_basetype(struct symbol *type)
-{
- if (type->type == SYM_PTR)
- type = type->ctype.base_type;
- assert(type->type == SYM_FN);
- return type;
-}
-
-static LLVMValueRef output_op_call(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef target, func;
- int n_arg = 0, i;
- struct pseudo *arg;
- LLVMValueRef *args;
- char name[64];
-
- n_arg = ptrlist_size((struct ptr_list *)insn->arguments);
- args = alloca(n_arg * sizeof(LLVMValueRef));
- struct symbol *ftype = get_function_basetype(insn->fntype);
-
- i = 0;
- FOR_EACH_PTR(insn->arguments, arg) {
- LLVMValueRef value;
- struct symbol *atype;
-
- atype = dmrC_get_nth_symbol(ftype->arguments, i);
- value = NULL;
- if (arg->type == PSEUDO_VAL) {
- /* Value pseudos do not have type information. */
- /* Use the function prototype to get the type. */
- if (atype)
- value = val_to_value(C, fn, arg->value, atype);
- else {
- LLVMTypeRef type = int_type_by_size(fn->module, arg->size);
- if (!type) {
- dmrC_sparse_error(C, insn->pos, "pseudo value argument[%d] = %lld has invalid size %d\n", i+1, arg->value, arg->size);
- }
- else {
- value = constant_value(C, fn->module, arg->value, type);
- }
- }
- }
- else {
- value = pseudo_to_value(C, fn, atype, arg);
- }
- if (!value)
- return NULL;
- if (atype) {
- LLVMTypeRef argtype = get_symnode_type(C, fn->module, atype);
- if (!argtype)
- return NULL;
- value = build_cast(C, fn, value, argtype, LLVMGetValueName(value), 0);
- if (!value)
- return NULL;
- }
- args[i++] = value;
- } END_FOR_EACH_PTR(arg);
-
- func = pseudo_to_value(C, fn, insn->type, insn->func);
- if (!func)
- return NULL;
- pseudo_name(C, insn->target, name, sizeof name);
- LLVMTypeRef function_type = type_to_llvmtype(C, fn->module, ftype, NULL);
- if (!function_type)
- return NULL;
- LLVMTypeRef fptr_type = LLVMPointerType(function_type, 0);
- LLVMTypeRef bytep = LLVMPointerType(LLVMInt8TypeInContext(LLVMGetModuleContext(fn->module)), 0);
-
- target = LLVMBuildBitCast(fn->builder, func, bytep, name);
- target = LLVMBuildBitCast(fn->builder, target, fptr_type, name);
- target = LLVMBuildCall(fn->builder, target, args, n_arg, name);
-
- insn->target->priv = target;
-
- return target;
-}
-
-static LLVMValueRef output_op_phisrc(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef v;
- struct instruction *phi;
-
- assert(insn->target->priv == NULL);
-
- /* target = src */
- v = get_operand(C, fn, insn->type, insn->phi_src, 0, 0);
- if (!v)
- return NULL;
-
- FOR_EACH_PTR(insn->phi_users, phi) {
- LLVMValueRef load, ptr;
-
- assert(phi->opcode == OP_PHI);
- /* phi must be load from alloca */
- load = phi->target->priv;
- assert(load);
- if (!load)
- return NULL;
- assert(LLVMGetInstructionOpcode(load) == LLVMLoad);
- ptr = LLVMGetOperand(load, 0);
- /* store v to alloca */
- LLVMTypeRef phi_type = insn_symbol_type(C, fn->module, phi);
- if (!phi_type)
- return NULL;
- v = build_cast(C, fn, v, phi_type, "", 0);
- if (!v)
- return NULL;
- v = LLVMBuildStore(fn->builder, v, ptr);
- } END_FOR_EACH_PTR(phi);
- return v;
-}
-
-static LLVMValueRef output_op_phi(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef load = insn->target->priv;
- (void)C;
- assert(load);
- if (!load)
- return NULL;
-
- /* forward load */
- assert(LLVMGetInstructionOpcode(load) == LLVMLoad);
- /* forward load has no parent block */
- assert(!LLVMGetInstructionParent(load));
- /* finalize load in current block */
- LLVMInsertIntoBuilder(fn->builder, load);
- return load;
-}
-
-static LLVMValueRef output_op_ptrcast(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef src, target;
- LLVMTypeRef dtype;
- struct symbol *otype = insn->orig_type;
- char target_name[64];
-
- assert(dmrC_is_ptr_type(insn->type));
-
- src = insn->src->priv;
- if (!src)
- src = get_operand(C, fn, otype, insn->src, 1, 0);
- if (!src)
- return NULL;
-
- pseudo_name(C, insn->target, target_name, sizeof target_name);
-
- dtype = insn_symbol_type(C, fn->module, insn);
- if (!dtype)
- return NULL;
-
- target = build_cast(C, fn, src, dtype, target_name, 0);
- insn->target->priv = target;
-
- return target;
-}
-
-static LLVMValueRef output_op_cast(struct dmr_C *C, struct function *fn, struct instruction *insn, LLVMOpcode op)
-{
- LLVMValueRef src, target;
- LLVMTypeRef dtype;
- struct symbol *otype = insn->orig_type;
- char target_name[64];
-
- if (dmrC_is_ptr_type(insn->type)) {
- return output_op_ptrcast(C, fn, insn);
- }
-
- src = insn->src->priv;
- if (!src)
- src = pseudo_to_value(C, fn, insn->type, insn->src);
- if (dmrC_is_int_type(C->S, otype)) {
- LLVMTypeRef stype = get_symnode_or_basetype(C, fn->module, otype);
- src = build_cast(C, fn, src, stype, LLVMGetValueName(src), op == LLVMZExt);
- }
- if (!src)
- return NULL;
-
- pseudo_name(C, insn->target, target_name, sizeof target_name);
-
- assert(!dmrC_is_float_type(C->S, insn->type));
-
- dtype = insn_symbol_type(C, fn->module, insn);
- if (!dtype)
- return NULL;
- target = build_cast(C, fn, src, dtype, target_name, op == LLVMZExt);
- insn->target->priv = target;
-
- return target;
-}
-
-static LLVMValueRef output_op_fpcast(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef src, target;
- char target_name[64];
- LLVMTypeRef dtype;
- struct symbol *otype = insn->orig_type;
-
- src = insn->src->priv;
- if (!src)
- src = pseudo_to_value(C, fn, insn->type, insn->src);
- if (!src)
- return NULL;
-
- pseudo_name(C, insn->target, target_name, sizeof target_name);
-
- dtype = insn_symbol_type(C, fn->module, insn);
- if (!dtype)
- return NULL;
-
- target = build_cast(C, fn, src, dtype, target_name, !dmrC_is_signed_type(otype));
- insn->target->priv = target;
-
- return target;
-}
-
-
-static LLVMValueRef output_op_copy(struct dmr_C *C, struct function *fn, struct instruction *insn,
- pseudo_t pseudo)
-{
- LLVMValueRef src, target;
- LLVMTypeRef const_type;
- char target_name[64];
-
- pseudo_name(C, insn->target, target_name, sizeof target_name);
- src = pseudo_to_value(C, fn, insn->type, pseudo);
- if (!src)
- return NULL;
-
- const_type = insn_symbol_type(C, fn->module, insn);
- if (!const_type)
- return NULL;
-
- /*
- * This is nothing more than 'target = src'
- *
- * TODO: find a better way to provide an identity function,
- * than using "X + 0" simply to produce a new LLVM pseudo
- */
-
- if (dmrC_is_float_type(C->S, insn->type))
- target = LLVMBuildFAdd(fn->builder, src,
- LLVMConstReal(const_type, 0.0), target_name);
- else
- target = LLVMBuildAdd(fn->builder, src,
- LLVMConstInt(const_type, 0, 0), target_name);
-
- insn->target->priv = target;
- return target;
-}
-
-static LLVMValueRef output_op_setval(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- struct expression *expr = insn->val;
- char target_name[64];
- LLVMTypeRef const_type;
- LLVMValueRef target = NULL;
-
- if (!expr)
- return NULL;
-
- pseudo_name(C, insn->target, target_name, sizeof target_name);
- const_type = insn_symbol_type(C, fn->module, insn);
- if (!const_type)
- return NULL;
-
- switch (expr->type) {
- case EXPR_FVALUE:
- target = LLVMConstReal(const_type, expr->fvalue);
- break;
- case EXPR_LABEL:
- target = LLVMBlockAddress(fn->fn, expr->symbol->bb_target->priv);
- break;
- default:
- dmrC_sparse_error(C, insn->pos, "unsupported expression type %d in setval\n", expr->type);
- dmrC_show_expression(C, expr);
- return NULL;
- }
-
- insn->target->priv = target;
-
- return target;
-}
-
-static LLVMValueRef output_op_symaddr(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef res, src;
- LLVMTypeRef dtype;
- char name[64];
-
- src = pseudo_to_value(C, fn, insn->type, insn->symbol);
- if (!src)
- return NULL;
-
- dtype = get_symnode_or_basetype(C, fn->module, insn->type);
- if (!dtype)
- return NULL;
-
- pseudo_name(C, insn->target, name, sizeof name);
- res = LLVMBuildBitCast(fn->builder, src, dtype, name);
- insn->target->priv = res;
-
- return res;
-}
-
-static LLVMValueRef output_op_not(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef src, target;
- char target_name[64];
-
- src = pseudo_to_value(C, fn, insn->type, insn->src);
- if (!src)
- return NULL;
-
- pseudo_name(C, insn->target, target_name, sizeof target_name);
-
- target = LLVMBuildNot(fn->builder, src, target_name);
-
- insn->target->priv = target;
-
- return target;
-}
-
-static LLVMValueRef output_op_neg(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef src, target;
- char target_name[64];
-
- src = pseudo_to_value(C, fn, insn->type, insn->src);
- if (!src)
- return NULL;
-
- pseudo_name(C, insn->target, target_name, sizeof target_name);
-
- if (dmrC_is_float_type(C->S, insn->type))
- target = LLVMBuildFNeg(fn->builder, src, target_name);
- else
- target = LLVMBuildNeg(fn->builder, src, target_name);
-
- insn->target->priv = target;
-
- return target;
-}
-
-/* return 1 on success, 0 on failure */
-static int output_insn(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- LLVMValueRef v = NULL;
- switch (insn->opcode) {
- case OP_RET:
- v = output_op_ret(C, fn, insn);
- break;
- case OP_CBR:
- v = output_op_cbr(C, fn, insn);
- break;
- case OP_BR:
- v = output_op_br(C, fn, insn);
- break;
- case OP_SYMADDR:
- v = output_op_symaddr(C, fn, insn);
- break;
- case OP_SETVAL:
- v = output_op_setval(C, fn, insn);
- break;
- case OP_SWITCH:
- v = output_op_switch(C, fn, insn);
- break;
- case OP_COMPUTEDGOTO:
- dmrC_sparse_error(C, insn->pos, "computed goto not yet supported\n");
- return 0;
- case OP_PHISOURCE:
- v = output_op_phisrc(C, fn, insn);
- break;
- case OP_PHI:
- v = output_op_phi(C, fn, insn);
- break;
- case OP_LOAD:
- v = output_op_load(C, fn, insn);
- break;
- case OP_LNOP:
- dmrC_sparse_error(C, insn->pos, "lnop not yet supported\n");
- return 0;
- case OP_STORE:
- v = output_op_store(C, fn, insn);
- break;
- case OP_SNOP:
- dmrC_sparse_error(C, insn->pos, "snop not yet supported\n");
- return 0;
- case OP_CALL:
- v = output_op_call(C, fn, insn);
- break;
- case OP_CAST:
- v = output_op_cast(C, fn, insn, LLVMZExt);
- break;
- case OP_SCAST:
- v = output_op_cast(C, fn, insn, LLVMSExt);
- break;
- case OP_FPCAST:
- v = output_op_fpcast(C, fn, insn);
- break;
- case OP_PTRCAST:
- v = output_op_ptrcast(C, fn, insn);
- break;
- 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:
- v = output_op_binary(C, fn, insn);
- break;
- 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:
- v = output_op_compare(C, fn, insn);
- break;
- case OP_SEL:
- v = output_op_sel(C, fn, insn);
- break;
- case OP_SLICE:
- dmrC_sparse_error(C, insn->pos, "slice not yet supported\n");
- return 0;
- case OP_NOT:
- v = output_op_not(C, fn, insn);
- break;
- case OP_NEG:
- v = output_op_neg(C, fn, insn);
- break;
- case OP_CONTEXT:
- dmrC_sparse_error(C, insn->pos, "context not yet supported\n");
- return 0;
- case OP_RANGE:
- dmrC_sparse_error(C, insn->pos, "range not yet supported\n");
- return 0;
- case OP_NOP:
- dmrC_sparse_error(C, insn->pos, "nop not yet supported\n");
- return 0;
- case OP_DEATHNOTE:
- return 1;
- case OP_ASM:
- dmrC_sparse_error(C, insn->pos, "asm not yet supported\n");
- return 0;
- case OP_COPY:
- v = output_op_copy(C, fn, insn, insn->src);
- break;
- default:
- return 1;
- }
-
- if (v == NULL)
- dmrC_sparse_error(C, insn->pos, "failed to output instruction %s\n", dmrC_show_instruction(C, insn));
- return v != NULL;
-}
-
-/* return 1 on success, 0 on failure */
-static int output_bb(struct dmr_C *C, struct function *fn, struct basic_block *bb)
-{
- struct instruction *insn;
-
- FOR_EACH_PTR(bb->insns, insn) {
- if (!insn->bb)
- continue;
-
- if (!output_insn(C, fn, insn)) {
- dmrC_sparse_error(C, insn->pos, "failed to output %s\n", dmrC_show_instruction(C, insn));
- return 0;
- }
- }
- END_FOR_EACH_PTR(insn);
- return 1;
-}
-
-#define MAX_ARGS 64
-
-static LLVMValueRef output_fn(struct dmr_C *C, LLVMModuleRef module, struct entrypoint *ep)
-{
- struct symbol *sym = ep->name;
- struct symbol *base_type = sym->ctype.base_type;
- struct symbol *ret_type = sym->ctype.base_type->ctype.base_type;
- LLVMTypeRef arg_types[MAX_ARGS];
- LLVMTypeRef return_type;
- struct function function = { .module = module };
- struct basic_block *bb;
- struct symbol *arg;
- const char *name;
- int nr_args = 0;
-
- FOR_EACH_PTR(base_type->arguments, arg) {
- if (nr_args >= MAX_ARGS)
- return NULL;
- arg_types[nr_args] = get_symnode_type(C, module, arg);
- if (!arg_types[nr_args])
- return NULL;
- nr_args++;
- } END_FOR_EACH_PTR(arg);
-
- name = dmrC_show_ident(C, sym->ident);
-
- return_type = type_to_llvmtype(C, module, ret_type, NULL);
- if (!return_type)
- return NULL;
-
- function.return_type = return_type;
- function.fn = LLVMGetNamedFunction(module, name);
- if (!function.fn) {
- function.type = LLVMFunctionType(return_type, arg_types, nr_args, base_type->variadic);
- function.fn = LLVMAddFunction(module, name, function.type);
- LLVMSetLinkage(function.fn, function_linkage(C, sym));
- sym->priv = function.fn;
- }
- else {
- function.type = LLVMTypeOf(function.fn);
- }
-
- LLVMSetFunctionCallConv(function.fn, LLVMCCallConv);
-
- function.builder = LLVMCreateBuilderInContext(LLVMGetModuleContext(module));
-
- /* give a name to each argument */
- for (int i = 0; i < nr_args; i++) {
- char name[MAX_PSEUDO_NAME];
- LLVMValueRef arg;
-
- arg = LLVMGetParam(function.fn, i);
- snprintf(name, sizeof name, "ARG%d", i + 1);
- LLVMSetValueName(arg, name);
- }
-
- /* create the BBs */
- FOR_EACH_PTR(ep->bbs, bb) {
- static int nr_bb;
- LLVMBasicBlockRef bbr;
- char bbname[32];
- struct instruction *insn;
-
- sprintf(bbname, "L%d", nr_bb++);
- bbr = LLVMAppendBasicBlockInContext(LLVMGetModuleContext(module), function.fn, bbname);
-
- bb->priv = bbr;
-
- /* allocate alloca for each phi */
- FOR_EACH_PTR(bb->insns, insn) {
- LLVMBasicBlockRef entrybbr;
- LLVMTypeRef phi_type;
- LLVMValueRef ptr;
-
- if (!insn->bb || insn->opcode != OP_PHI)
- continue;
- /* insert alloca into entry block */
- entrybbr = LLVMGetEntryBasicBlock(function.fn);
- LLVMPositionBuilderAtEnd(function.builder, entrybbr);
- phi_type = insn_symbol_type(C, module, insn);
- if (!phi_type) {
- LLVMDisposeBuilder(function.builder);
- return NULL;
- }
- ptr = LLVMBuildAlloca(function.builder, phi_type, "");
- /* emit forward load for phi */
- LLVMClearInsertionPosition(function.builder);
- insn->target->priv = LLVMBuildLoad(function.builder, ptr, "phi");
- } END_FOR_EACH_PTR(insn);
- }
- END_FOR_EACH_PTR(bb);
-
- FOR_EACH_PTR(ep->bbs, bb) {
- LLVMPositionBuilderAtEnd(function.builder, bb->priv);
-
- if (!output_bb(C, &function, bb)) {
- LLVMDisposeBuilder(function.builder);
- return NULL;
- }
- }
- END_FOR_EACH_PTR(bb);
-
- LLVMDisposeBuilder(function.builder);
-
- return function.fn;
-}
-
-/* returns NULL on failure */
-static LLVMValueRef output_data(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym)
-{
- struct expression *initializer = sym->initializer;
- LLVMValueRef initial_value = NULL;
- LLVMValueRef data = NULL;
- const char *name;
-
- if (initializer) {
- switch (initializer->type) {
- case EXPR_VALUE:
- initial_value = constant_value(C, module, initializer->value, get_symnode_type(C, module, sym));
- break;
- case EXPR_FVALUE:
- initial_value = LLVMConstReal(get_symnode_type(C, module, sym), initializer->fvalue);
- break;
- case EXPR_SYMBOL: {
- struct symbol *sym = initializer->symbol;
- if (sym->ident)
- initial_value = LLVMGetNamedGlobal(module, dmrC_show_ident(C, sym->ident));
- if (!initial_value)
- initial_value = output_data(C, module, sym);
- break;
- }
- case EXPR_STRING: {
- const char *s = initializer->string->data;
- char *scopy = dmrC_allocator_allocate(&C->byte_allocator, strlen(s) + 1);
- strcpy(scopy, s);
- initial_value = LLVMConstStringInContext(LLVMGetModuleContext(module), scopy, strlen(scopy) + 1, true);
- break;
- }
- default:
- dmrC_sparse_error(C, initializer->pos, "unsupported expr type in global data initializer: %d\n", initializer->type);
- dmrC_show_expression(C, initializer);
- }
- if (!initial_value)
- return NULL;
- }
- else {
- LLVMTypeRef type = get_symnode_type(C, module, sym);
- if (type == NULL)
- return NULL;
- initial_value = LLVMConstNull(type);
- }
-
- name = dmrC_show_ident(C, sym->ident);
-
- if (!sym->priv) {
- if (sym->ident)
- data = LLVMGetNamedGlobal(module, name);
- if (!data)
- data = LLVMAddGlobal(module, LLVMTypeOf(initial_value), name);
-
- LLVMSetLinkage(data, data_linkage(C, sym));
- if (sym->ctype.modifiers & MOD_CONST)
- LLVMSetGlobalConstant(data, 1);
- if (sym->ctype.modifiers & MOD_TLS)
- LLVMSetThreadLocal(data, 1);
- if (sym->ctype.alignment)
- LLVMSetAlignment(data, sym->ctype.alignment);
-
- if (!(sym->ctype.modifiers & MOD_EXTERN))
- LLVMSetInitializer(data, initial_value);
-
- sym->priv = data;
- }
- else {
- data = sym->priv;
- if (!(sym->ctype.modifiers & MOD_EXTERN))
- LLVMSetInitializer(data, initial_value);
- }
- return data;
-}
-
-static LLVMValueRef output_prototype(struct dmr_C *C, LLVMModuleRef module, struct symbol *sym)
-{
- const char *name = dmrC_show_ident(C, sym->ident);
- struct symbol *base_type = sym;
- if (sym->type == SYM_NODE)
- base_type = sym->ctype.base_type;
- LLVMTypeRef ftype = sym_func_type(C, module, base_type, sym->type == SYM_NODE ? sym : NULL);
- if (!ftype)
- return NULL;
- LLVMValueRef result = LLVMGetNamedFunction(module, name);
- if (!result) {
- result = LLVMAddFunction(module, name, ftype);
- LLVMSetLinkage(result, function_linkage(C, sym));
- //LLVMSetFunctionCallConv(result, LLVMCCallConv);
- }
- sym->priv = result;
- return result;
-}
-
-/* returns 1 on success, 0 on failure */
-static int compile(struct dmr_C *C, LLVMModuleRef module, struct symbol_list *list)
-{
- struct symbol *sym;
-
- FOR_EACH_PTR(list, sym) {
- struct entrypoint *ep;
- dmrC_expand_symbol(C, sym);
-
- if (dmrC_is_prototype(sym)) {
- if (!output_prototype(C, module, sym))
- return 0;
- continue;
- }
-
- ep = dmrC_linearize_symbol(C, sym);
- LLVMValueRef result = NULL;
- if (ep)
- result = output_fn(C, module, ep);
- else
- result = output_data(C, module, sym);
- if (!result)
- return 0;
- }
- END_FOR_EACH_PTR(sym);
-
- return 1;
-}
-
-#if 0
-
-#ifndef LLVM_DEFAULT_TARGET_TRIPLE
-#define LLVM_DEFAULT_TARGET_TRIPLE LLVM_HOSTTRIPLE
-#endif
-
-#define X86_LINUX_LAYOUT \
- "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" \
- "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-" \
- "a0:0:64-f80:32:32-n8:16:32-S128"
-
-#define X86_64_LINUX_LAYOUT \
- "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" \
- "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" \
- "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
-
-static void set_target(struct dmr_C *C, LLVMModuleRef module)
-{
- char target[] = LLVM_DEFAULT_TARGET_TRIPLE;
- const char *arch, *vendor, *os, *env, *layout = NULL;
- char triple[256];
-
- arch = strtok(target, "-");
- vendor = strtok(NULL, "-");
- os = strtok(NULL, "-");
- env = strtok(NULL, "-");
-
- if (!os)
- return;
- if (!env)
- env = "unknown";
-
- if (!strcmp(arch, "x86_64") && !strcmp(os, "linux")) {
- if (C->arch_m64) {
- layout = X86_64_LINUX_LAYOUT;
- }
- else {
- arch = "i386";
- layout = X86_LINUX_LAYOUT;
- }
- }
-
- /* unsupported target */
- if (!layout)
- return;
-
- snprintf(triple, sizeof(triple), "%s-%s-%s-%s", arch, vendor, os, env);
- // FIXME - what do we do here?
- //LLVMSetTarget(module, triple);
- //LLVMSetDataLayout(module, layout);
-}
-
-#endif
-
-static void add_intrinsics(LLVMModuleRef module)
-{
- LLVMTypeRef param_types[] = { LLVMPointerType(LLVMInt8TypeInContext(LLVMGetModuleContext(module)), 0),
- LLVMInt8TypeInContext(LLVMGetModuleContext(module)),
- LLVMInt32TypeInContext(LLVMGetModuleContext(module)),
- LLVMInt32TypeInContext(LLVMGetModuleContext(module)),
- LLVMInt1TypeInContext(LLVMGetModuleContext(module)) };
- LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidTypeInContext(LLVMGetModuleContext(module)), param_types, 5, false);
- LLVMAddFunction(module, "llvm.memset.p0i8.i32", fn_type);
-}
-
-bool dmrC_llvmcompile(int argc, char **argv, LLVMModuleRef module,
- const char *inputbuffer)
-{
- struct string_list *filelist = NULL;
- struct symbol_list *symlist;
- char *file;
-
- struct dmr_C *C = new_dmr_C();
- C->codegen = 1; /* disables macros related to vararg processing */
-
- symlist = dmrC_sparse_initialize(C, argc, argv, &filelist);
- // set_target(C, module);
- add_intrinsics(module);
-
- int rc = 0; /* 0 means OK, non-zero means error */
- if (!setjmp(C->jmpbuf)) {
- if (compile(C, module, symlist)) {
- /* need ->phi_users */
- /* This flag enables call to dmrC_track_pseudo_death() in
- linearize.c which sets
- phi_users list on PHISOURCE instructions */
- C->dbg_dead = 1;
- FOR_EACH_PTR(filelist, file)
- {
- symlist = dmrC_sparse(C, file);
- if (C->die_if_error || !symlist) {
- rc = 1;
- break;
- }
- if (!compile(C, module, symlist)) {
- rc = 1;
- break;
- }
- }
- END_FOR_EACH_PTR(file);
-
- if (inputbuffer && rc == 0) {
- char *buffer = strdup(inputbuffer);
- if (!buffer)
- rc = 1;
- else {
- symlist = dmrC_sparse_buffer(C, "buffer", buffer, 0);
- free(buffer);
- if (C->die_if_error || !symlist) {
- rc = 1;
- }
- else if (!compile(C, module, symlist)) {
- rc = 1;
- }
- }
- }
- }
- else
- rc = 1;
- }
- else {
- rc = 1;
- }
- char *error_message = NULL;
- int dump_module = 0;
- if (rc == 1) {
- fprintf(stderr, "Failed to compile given inputs\n");
- }
- if (rc == 0 &&
- LLVMVerifyModule(module, LLVMPrintMessageAction, &error_message)) {
- dump_module = 1;
- rc = 1;
- }
- if (error_message) {
- if (strlen(error_message) > 0)
- fprintf(stderr, "%s\n\n", error_message);
- LLVMDisposeMessage(error_message);
- }
- if (rc == 0) {
- const char *filename = "out.bc";
- if (C->output_file_name[0])
- filename = C->output_file_name;
- LLVMWriteBitcodeToFile(module, filename);
- }
- else {
- if (dump_module)
- /* we only dump the LLVM module if verification fails */
- LLVMDumpModule(module);
- }
- destroy_dmr_C(C);
-
- return rc == 0;
-}
diff --git a/dmr_c/null-backend/dmr_c.h b/dmr_c/null-backend/dmr_c.h
deleted file mode 100644
index eb5f23e..0000000
--- a/dmr_c/null-backend/dmr_c.h
+++ /dev/null
@@ -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
diff --git a/dmr_c/omrjit-backend/dmr_c.h b/dmr_c/omrjit-backend/dmr_c.h
deleted file mode 100644
index 1a8e1b5..0000000
--- a/dmr_c/omrjit-backend/dmr_c.h
+++ /dev/null
@@ -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
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool dmrC_omrcompile(int argc, char **argv, JIT_ContextRef context,
- const char *inputbuffer);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/dmr_c/omrjit-backend/sparse-omrjit.c b/dmr_c/omrjit-backend/sparse-omrjit.c
deleted file mode 100644
index d101fde..0000000
--- a/dmr_c/omrjit-backend/sparse-omrjit.c
+++ /dev/null
@@ -1,2299 +0,0 @@
-/**
- * This is a backend code generator for dmr_C that uses
- * the JIT engine OMRJIT (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.
- */
-
-/*
-Define environment variable
-TR_Options=traceIlGen,traceFull,traceAliases,log=trtrace.log
-To obtain a nice trace of codegen
-*/
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/*
-Some Implementation Notes
-=========================
-
-1. Local aggregate variables are modelled as byte strings - the load/store ops
- take care of extracting / storing the right type of value
-
-2. Local primitives are modelled as temporaries.
-
-3. Phi values are modelled as temporaries - phisrc is implemented as store
- to temporary while phi is a load from temporary.
-
-4. We create all the blocks at the beginning based upon the blocks in
- Sparse IR - but we have to add an extra block for every CBR instruction
- as conditional branches in OMR fall through to the next block
-
-5. Local SymRefs are stored in Sparse Symbol->priv field.
-
-6. Pseudo SymRefs are stored in pseudo->priv2, whereas corresponding load
- is stored in pseudo->priv.
-
-7. If address of a local temporary is taken we need to let the compiler
- backend know this as otherwise the backend may not realize that the
- locals could change through the pointers. Strictly speaking this is a
- problem if the pointers escape (e.g. are passed to a function call)
- but we don't optimize for that yet.
-*/
-
-/*
-OMR has additional vector types which we do not support
-*/
-enum OMRTypeKind {
- RT_UNSUPPORTED = 0,
- RT_VOID = 1,
- RT_INT = 2, /* Sometimes Sparse IR contains int values with odd bit
- sizes; this type is used in that case */
- RT_INT8 = 3,
- RT_INT16 = 4,
- RT_INT32 = 5,
- RT_INT64 = 6,
- RT_FLOAT = 7,
- RT_DOUBLE = 8,
- RT_PTR = 9,
- RT_AGGREGATE = 10,
- RT_FUNCTION = 11
-};
-
-struct OMRType {
- enum OMRTypeKind type;
- struct OMRType *return_type;
- uint32_t bit_size;
-};
-
-static struct OMRType VoidType = {.type = RT_VOID, .return_type = NULL, .bit_size = 0};
-static struct OMRType Int8Type = {.type = RT_INT8, .return_type = NULL, .bit_size = sizeof(int8_t) * 8};
-static struct OMRType Int16Type = {.type = RT_INT16, .return_type = NULL, .bit_size = sizeof(int16_t) * 8};
-static struct OMRType Int32Type = {.type = RT_INT32, .return_type = NULL, .bit_size = sizeof(int32_t) * 8};
-static struct OMRType Int64Type = {.type = RT_INT64, .return_type = NULL, .bit_size = sizeof(int64_t) * 8};
-static struct OMRType FloatType = {.type = RT_FLOAT, .return_type = NULL, .bit_size = sizeof(float) * 8};
-static struct OMRType DoubleType = {.type = RT_DOUBLE, .return_type = NULL, .bit_size = sizeof(double) * 8};
-static struct OMRType PtrType = {.type = RT_PTR, .return_type = NULL, .bit_size = sizeof(void *) * 8};
-// static struct OMRType PtrIntType = {
-// .type = RT_INT64,.return_type = NULL,.bit_size = sizeof(intptr_t) * 8 };
-static struct OMRType BadType = {.type = RT_UNSUPPORTED, .return_type = NULL, .bit_size = 0};
-
-struct function {
- struct dmr_C *C;
- JIT_ILInjectorRef injector;
- JIT_FunctionBuilderRef builder;
- JIT_ContextRef context;
- struct entrypoint *ep;
- struct allocator type_allocator;
- struct OMRType *return_type;
-};
-
-/* Arbitrary limit ... FIXME */
-#define JIT_MaxArgs 16
-
-static struct OMRType *alloc_OMRtype(struct function *fn, enum OMRTypeKind kind, unsigned int bit_size)
-{
- struct OMRType *type = dmrC_allocator_allocate(&fn->type_allocator, 0);
- type->type = kind;
- type->bit_size = bit_size;
- type->return_type = NULL;
- return type;
-}
-
-static struct OMRType *int_type_by_size(struct function *fn, int size)
-{
- switch (size) {
- case -1:
- return NULL;
- case 8:
- return &Int8Type;
- case 16:
- return &Int16Type;
- case 32:
- return &Int32Type;
- case 64:
- return &Int64Type;
- default:
- /* Sometimes Sparse IR has non-standard bit sizes espcially in
- * bitwise ops */
- return alloc_OMRtype(fn, RT_INT, size);
- }
-}
-
-static struct OMRType *sym_basetype_type(struct dmr_C *C, struct function *fn, struct symbol *sym,
- struct symbol *sym_node)
-{
- (void)sym_node;
- if (dmrC_is_float_type(C->S, sym)) {
- switch (sym->bit_size) {
- case 32:
- return &FloatType;
- case 64:
- return &DoubleType;
- default:
- fprintf(stderr, "invalid bit size %d for type %d\n", sym->bit_size, sym->type);
- return &BadType;
- }
- } else {
- switch (sym->bit_size) {
- case -1:
- return &VoidType;
- default:
- return int_type_by_size(fn, sym->bit_size);
- }
- }
-}
-
-static int is_aggregate_type(struct symbol *sym)
-{
- if (sym->type == SYM_NODE)
- return is_aggregate_type(sym->ctype.base_type);
- switch (sym->type) {
- case SYM_UNION:
- case SYM_STRUCT:
- case SYM_ARRAY:
- return true;
- default:
- return false;
- }
-}
-
-static struct OMRType *type_to_OMRtype(struct dmr_C *C, struct function *fn, struct symbol *sym,
- struct symbol *sym_node);
-
-static struct OMRType *get_symnode_type(struct dmr_C *C, struct function *fn, struct symbol *sym)
-{
- assert(sym->type == SYM_NODE);
- return type_to_OMRtype(C, fn, sym->ctype.base_type, sym);
-}
-
-static struct OMRType *get_symnode_or_basetype(struct dmr_C *C, struct function *fn, struct symbol *sym)
-{
- if (sym->type == SYM_NODE) {
- assert(sym->ctype.base_type->type != SYM_NODE);
- return type_to_OMRtype(C, fn, sym->ctype.base_type, sym);
- }
- return type_to_OMRtype(C, fn, sym, NULL);
-}
-
-static struct OMRType *func_return_type(struct dmr_C *C, struct function *fn, struct symbol *sym,
- struct symbol *sym_node)
-{
- return type_to_OMRtype(C, fn, sym->ctype.base_type, sym_node);
-}
-
-static struct OMRType *sym_func_type(struct dmr_C *C, struct function *fn, struct symbol *sym, struct symbol *sym_node)
-{
- struct OMRType *ret_type;
-
- // TODO we probably need a better way to encode function type
-
- ret_type = func_return_type(C, fn, sym, sym_node);
- struct OMRType *type = alloc_OMRtype(fn, RT_FUNCTION, 0);
- type->return_type = ret_type;
- return type;
-}
-
-static struct OMRType *sym_array_type(struct dmr_C *C, struct function *fn, struct symbol *sym, struct symbol *sym_node)
-{
- struct symbol *base_type;
-
- (void)C;
- base_type = sym->ctype.base_type;
- /* empty struct is undefined [6.7.2.1(8)] */
- int array_bit_size = sym->bit_size;
- if (array_bit_size == 0 || array_bit_size == -1) {
- if (sym_node != NULL)
- array_bit_size = sym_node->bit_size;
- }
- if (base_type->bit_size == 0 || base_type->bit_size == -1 || array_bit_size == 0 || array_bit_size == -1) {
- fprintf(stderr, "array size cannot be determined\n");
- return &BadType;
- }
- return alloc_OMRtype(fn, RT_AGGREGATE, array_bit_size);
-}
-
-static struct OMRType *sym_struct_type(struct dmr_C *C, struct function *fn, struct symbol *sym,
- struct symbol *sym_node)
-{
- (void)C;
- (void)sym_node;
- unsigned int bit_size = 0;
- if (sym->bit_size > 0 && sym->bit_size != -1) {
- bit_size = sym->bit_size;
- }
- return alloc_OMRtype(fn, RT_AGGREGATE, bit_size);
-}
-
-static struct OMRType *sym_ptr_type(struct dmr_C *C, struct function *fn, struct symbol *sym, struct symbol *sym_node)
-{
- (void)C;
- (void)fn;
- (void)sym_node;
- (void)sym;
- return &PtrType;
-}
-
-static struct OMRType *type_to_OMRtype(struct dmr_C *C, struct function *fn, struct symbol *sym,
- struct symbol *sym_node)
-{
- assert(sym->type != SYM_NODE);
- assert(sym_node == NULL || sym_node->type == SYM_NODE);
- switch (sym->type) {
- case SYM_BITFIELD: {
- return alloc_OMRtype(fn, RT_INT, sym->bit_size);
- }
- case SYM_RESTRICT:
- case SYM_ENUM:
- return type_to_OMRtype(C, fn, sym->ctype.base_type, sym_node);
- case SYM_BASETYPE:
- return sym_basetype_type(C, fn, sym, sym_node);
- case SYM_PTR:
- return sym_ptr_type(C, fn, sym, sym_node);
- case SYM_UNION:
- case SYM_STRUCT:
- return sym_struct_type(C, fn, sym, sym_node);
- case SYM_ARRAY:
- return sym_array_type(C, fn, sym, sym_node);
- case SYM_FN:
- return sym_func_type(C, fn, sym, sym_node);
- default:
- return &BadType;
- }
-}
-
-/*
-If the instruction has a type uses that to determine the OMR type
-else returns an OMR int type that matches the instruction size.
-*/
-static struct OMRType *insn_symbol_type(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- if (insn->type) {
- return get_symnode_or_basetype(C, fn, insn->type);
- }
- return int_type_by_size(fn, insn->size);
-}
-
-static JIT_Type check_supported_argtype(struct dmr_C *C, struct symbol *sym)
-{
- if (dmrC_is_ptr_type(sym))
- return JIT_Address;
- if (dmrC_is_int_type(C->S, sym)) {
- switch (sym->bit_size) {
- case 8:
- return JIT_Int8;
- case 16:
- return JIT_Int16;
- case 32:
- return JIT_Int32;
- case 64:
- return JIT_Int64;
- default:
- fprintf(stderr, "Unsupported type in function argument\n");
- return JIT_NoType;
- }
- } else {
- // TODO assert float type
- switch (sym->bit_size) {
- case 32:
- return JIT_Float;
- case 64:
- return JIT_Double;
- default:
- fprintf(stderr, "Unsupported type in function argument\n");
- return JIT_NoType;
- }
- }
- return 0;
-}
-
-static struct OMRType *check_supported_returntype(struct dmr_C *C, struct OMRType *type)
-{
- (void)C;
- if (type->type == RT_AGGREGATE || type->type == RT_FUNCTION || type->type == RT_INT ||
- type->type == RT_UNSUPPORTED)
- return &BadType;
- return type;
-}
-
-static int32_t instruction_size_in_bytes(struct dmr_C *C, struct instruction *insn)
-{
- return insn->size / C->target->bits_in_char;
-}
-
-static JIT_Type map_OMRtype(struct OMRType *type)
-{
- switch (type->type) {
- case RT_DOUBLE:
- return JIT_Double;
- case RT_FLOAT:
- return JIT_Float;
- case RT_INT8:
- return JIT_Int8;
- case RT_INT16:
- return JIT_Int16;
- case RT_INT32:
- return JIT_Int32;
- case RT_INT64:
- return JIT_Int64;
- case RT_PTR:
- return JIT_Address;
- case RT_AGGREGATE:
- return JIT_Aggregate;
- default:
- return JIT_NoType;
- }
-}
-
-static JIT_SymbolRef OMR_alloca(struct function *fn, struct OMRType *type, int32_t size, bool reg)
-{
- (void)reg;
- JIT_Type omr_type = map_OMRtype(type);
- // In OMR there is no explicit alloca IL I believe
- // Instead we create a local symbol of appropriate size
- // We treat all locals as byte arrays - the load/store
- // is done at specific offsets as required
- if (omr_type == JIT_Aggregate)
- return JIT_CreateLocalByteArray(fn->injector, (uint32_t)size);
- else
- // phi nodes get created as temporaries
- return JIT_CreateTemporary(fn->injector, omr_type);
-}
-
-static JIT_NodeRef constant_value(struct dmr_C *C, struct function *fn, unsigned long long val, struct OMRType *dtype)
-{
- JIT_NodeRef result = NULL;
-
- (void)C;
- (void)fn;
-
- switch (dtype->type) {
- case RT_INT8:
- result = JIT_ConstInt8((int8_t)val);
- break;
- case RT_INT16:
- result = JIT_ConstInt16((int16_t)val);
- break;
- case RT_INT:
- case RT_INT32:
- assert(dtype->bit_size <= Int32Type.bit_size);
- result = JIT_ConstInt32((int32_t)val);
- break;
- case RT_INT64:
- result = JIT_ConstInt64(val);
- break;
- case RT_PTR:
- result = JIT_ConstAddress((void *)val);
- break;
- case RT_DOUBLE:
- result = JIT_ConstDouble((double)(long long)val);
- break;
- case RT_FLOAT:
- result = JIT_ConstFloat((float)(long long)val);
- break;
- default:
- fprintf(stderr, "unsupported pseudo value kind %d\n", dtype->type);
- break;
- }
- return result;
-}
-
-static JIT_NodeRef constant_fvalue(struct dmr_C *C, struct function *fn, double val, struct OMRType *dtype)
-{
- JIT_NodeRef result = NULL;
-
- (void)C;
- (void)fn;
- if (dtype->type == RT_DOUBLE) {
- result = JIT_ConstDouble(val);
- } else if (dtype->type == RT_FLOAT) {
- result = JIT_ConstFloat((float)val);
- } else {
- fprintf(stderr, "unsupported pseudo value kind %d\n", dtype->type);
- return NULL;
- }
- return result;
-}
-
-/*
- * We do not support globals or aggregate locals with initializers
- */
-static JIT_SymbolRef build_local(struct dmr_C *C, struct function *fn, struct symbol *sym)
-{
- const char *name = dmrC_show_ident(C, sym->ident);
- struct OMRType *type = get_symnode_type(C, fn, sym);
- char localname[256] = {0};
- snprintf(localname, sizeof localname, "%s_%p.", name, sym);
- if (dmrC_is_static(sym) || dmrC_is_extern(sym) || dmrC_is_toplevel(sym)) {
- return NULL;
- } else {
- if (sym->initialized && is_aggregate_type(sym)) {
- return NULL;
- }
- JIT_SymbolRef result = OMR_alloca(fn, type, type->bit_size / C->target->bits_in_char, false);
- sym->priv = result;
- return result;
- }
-}
-
-static void build_store(struct dmr_C *C, struct function *fn, JIT_NodeRef v, JIT_SymbolRef symbol)
-{
- (void)C;
-
- if (JIT_IsTemporary(fn->injector, symbol)) {
- JIT_StoreToTemporary(fn->injector, symbol, v);
- } else {
- assert(false);
- JIT_ArrayStoreAt(fn->injector, 0, JIT_LoadAddress(fn->injector, symbol), 0, v);
- }
-}
-
-static JIT_SymbolRef get_sym_value(struct dmr_C *C, struct function *fn, pseudo_t pseudo, bool do_init)
-{
- JIT_SymbolRef result = NULL;
- struct symbol *sym = pseudo->sym;
- struct expression *expr;
-
- result = (JIT_SymbolRef)sym->priv;
- if (result)
- return result;
-
- assert(sym->bb_target == NULL);
-
- expr = sym->initializer;
- if (expr && (!sym->ident || (sym->ident && (expr->type == EXPR_VALUE || expr->type == EXPR_FVALUE)))) {
- switch (expr->type) {
- case EXPR_STRING: {
- dmrC_sparse_error(C, expr->pos, "unsupported string reference in initializer\n");
- dmrC_show_expression(C, expr);
- return NULL;
- break;
- }
- case EXPR_SYMBOL: {
- dmrC_sparse_error(C, expr->pos, "unresolved symbol reference in initializer\n");
- dmrC_show_expression(C, expr);
- return NULL;
- break;
- }
- case EXPR_VALUE: {
- if (dmrC_is_static(sym)) {
- dmrC_sparse_error(C, expr->pos, "unsupported symbol reference\n");
- dmrC_show_expression(C, expr);
- return NULL;
- }
- struct OMRType *symtype = get_symnode_type(C, fn, sym);
- if (symtype == NULL) {
- dmrC_sparse_error(C, expr->pos, "invalid symbol type\n");
- dmrC_show_expression(C, expr);
- return NULL;
- }
- result = build_local(C, fn, sym);
- if (!result)
- return result;
- if (do_init) {
- JIT_NodeRef value = constant_value(C, fn, expr->value, symtype);
- build_store(C, fn, value, result);
- }
- sym->priv = result;
- break;
- }
- case EXPR_FVALUE: {
- if (dmrC_is_static(sym)) {
- dmrC_sparse_error(C, expr->pos, "unsupported symbol reference\n");
- dmrC_show_expression(C, expr);
- return NULL;
- }
- struct OMRType *symtype = get_symnode_type(C, fn, sym);
- if (symtype == NULL) {
- dmrC_sparse_error(C, expr->pos, "invalid symbol type\n");
- dmrC_show_expression(C, expr);
- return NULL;
- }
- result = build_local(C, fn, sym);
- if (!result)
- return result;
- if (do_init) {
- JIT_NodeRef value = constant_fvalue(C, fn, expr->fvalue, symtype);
- build_store(C, fn, value, result);
- }
- sym->priv = result;
- break;
- }
- default:
- dmrC_sparse_error(C, expr->pos, "unsupported expr type in initializer: %d\n", expr->type);
- dmrC_show_expression(C, expr);
- return NULL;
- }
- } else {
- const char *name = dmrC_show_ident(C, sym->ident);
- struct OMRType *type = get_symnode_type(C, fn, sym);
- if (type->type == RT_FUNCTION) {
- result = JIT_GetFunctionSymbol(fn->injector, name);
- if (!result) {
- dmrC_sparse_error(C, sym->pos, "unsupported symbol reference for '%s'\n", name);
- dmrC_debug_symbol(C, sym);
- return NULL;
- }
- } else if (dmrC_is_extern(sym) || dmrC_is_toplevel(sym)) {
- dmrC_sparse_error(C, sym->pos, "unsupported symbol reference for '%s'\n", name);
- dmrC_debug_symbol(C, sym);
- return NULL;
- } else {
- if (dmrC_is_static(sym)) {
- dmrC_sparse_error(C, sym->pos, "unsupported symbol reference for '%s'\n", name);
- dmrC_debug_symbol(C, sym);
- return NULL;
- }
- if (dmrC_is_static(sym) && sym->initializer) {
- dmrC_sparse_error(C, sym->initializer->pos,
- "unsupported initializer for "
- "local static variable\n");
- dmrC_show_expression(C, sym->initializer);
- return NULL;
- }
- result = build_local(C, fn, sym);
- if (!result) {
- dmrC_sparse_error(C, sym->initializer->pos,
- "unsupported initializer for "
- "local variable because zero initialization is not yet done\n");
- dmrC_show_expression(C, sym->initializer);
- return result;
- }
- sym->priv = result;
- }
- }
- return result;
-}
-
-static JIT_NodeRef val_to_value(struct dmr_C *C, struct function *fn, long long value, struct symbol *ctype)
-{
- (void)C;
- (void)fn;
-
- switch (ctype->bit_size) {
- case 8:
- return JIT_ConstInt8((int8_t)value);
- case 16:
- return JIT_ConstInt16((int16_t)value);
- case 32:
- return JIT_ConstInt32((int32_t)value);
- case 64:
- return JIT_ConstInt64((int64_t)value);
- }
- fprintf(stderr, "Cannot create a constant of size %d\n", ctype->bit_size);
- return NULL;
-}
-
-static JIT_NodeRef pseudo_to_value(struct dmr_C *C, struct function *fn, struct symbol *ctype, pseudo_t pseudo)
-{
- JIT_NodeRef result = NULL;
-
- switch (pseudo->type) {
- case PSEUDO_REG:
- result = pseudo->priv;
- break;
- case PSEUDO_SYM: {
- JIT_SymbolRef sym = get_sym_value(C, fn, pseudo, true);
- if (!sym)
- return NULL;
- return JIT_LoadAddress(fn->injector, sym);
- }
- case PSEUDO_VAL:
- result = val_to_value(C, fn, pseudo->value, ctype);
- break;
- case PSEUDO_ARG:
- result = JIT_LoadParameter(fn->injector, pseudo->nr - 1);
- break;
- case PSEUDO_PHI:
- result = pseudo->priv;
- break;
- case PSEUDO_VOID:
- result = NULL;
- break;
- }
- if (!result) {
- fprintf(stderr, "error: no result for pseudo\n");
- return NULL;
- } else if (JIT_GetNodeType(result) == JIT_NoType) {
- fprintf(stderr, "error: no result for pseudo\n");
- return NULL;
- }
- return result;
-}
-
-static JIT_NodeRef truncate_intvalue(struct dmr_C *C, struct function *fn, JIT_NodeRef val, struct OMRType *dtype,
- int unsigned_cast)
-{
- (void)C;
- (void)fn;
- (void)unsigned_cast;
-
- if (JIT_GetNodeType(val) == JIT_Int64 && dtype->bit_size <= 64) {
- if (dtype->bit_size == 64)
- return val;
- uint64_t mask = (1ULL << dtype->bit_size) - 1;
- return JIT_CreateNode2C(OP_land, val, JIT_ConstUInt64(mask));
- } else if (JIT_GetNodeType(val) == JIT_Int32 && dtype->bit_size <= 32) {
- if (dtype->bit_size == 32)
- return val;
- uint32_t mask = (1U << dtype->bit_size) - 1;
- return JIT_CreateNode2C(OP_iand, val, JIT_ConstUInt32(mask));
- } else {
- return NULL;
- }
-}
-
-static JIT_NodeRef convert_to(struct function *fn, JIT_NodeRef val, JIT_Type target_type, int unsigned_cast)
-{
- if (target_type == JIT_NoType)
- return NULL;
- JIT_NodeRef node = JIT_ConvertTo(fn->injector, val, target_type, unsigned_cast);
- if (JIT_GetNodeType(node) == JIT_NoType)
- return NULL;
- return node;
-}
-
-static JIT_NodeRef build_cast(struct dmr_C *C, struct function *fn, JIT_NodeRef val, struct OMRType *dtype,
- int unsigned_cast)
-{
- if (dtype->type == RT_INT)
- return truncate_intvalue(C, fn, val, dtype, unsigned_cast);
-
- JIT_Type target_type = map_OMRtype(dtype);
- return convert_to(fn, val, target_type, unsigned_cast);
-}
-
-static JIT_NodeRef output_op_phi(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_SymbolRef ptr = insn->target->priv2;
- (void)C;
-
- if (!ptr)
- return NULL;
-
- // Unlike LLVM version which creates the Load instruction
- // early on and inserts it into the IR stream here, we
- // create the Load instruction here.
- JIT_NodeRef load = NULL;
- // Model phi values as temporaries
- load = JIT_LoadTemporary(fn->injector, ptr);
- if (load == NULL)
- return NULL;
- assert(JIT_GetNodeType(load) != JIT_NoType);
- insn->target->priv = load;
- return load;
-}
-
-static JIT_NodeRef output_op_load(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef ptr = pseudo_to_value(C, fn, insn->type, insn->src);
- JIT_NodeRef load = NULL;
-
- if (!ptr)
- return NULL;
-
- if (insn->orig_type && dmrC_is_simple_type(C->S, insn->orig_type) && !dmrC_is_ptr_type(insn->orig_type)) {
- JIT_SymbolRef symref = insn->orig_type->priv;
- if (symref && JIT_IsTemporary(fn->injector, symref))
- load = JIT_LoadTemporary(fn->injector, symref);
- }
-
- if (!load) {
- // JIT_SymbolRef symref = NULL;
- uint64_t symref = (uint64_t)insn->orig_type;
-
- // JIT_NodeRef index = JIT_ConstInt64((int64_t)insn->offset);
- int64_t index = (int64_t)insn->offset;
- switch (insn->size) {
- case 8:
- // TODO do we need to do unsigned here?
- load = JIT_ArrayLoadAt(fn->injector, symref, ptr, index, JIT_Int8);
- break;
- case 16:
- // TODO do we need to do unsigned here?
- load = JIT_ArrayLoadAt(fn->injector, symref, ptr, index, JIT_Int16);
- break;
- case 32:
- if (dmrC_is_float_type(C->S, insn->type))
- load = JIT_ArrayLoadAt(fn->injector, symref, ptr, index, JIT_Float);
- else
- load = JIT_ArrayLoadAt(fn->injector, symref, ptr, index, JIT_Int32);
- break;
- case 64:
- if (dmrC_is_float_type(C->S, insn->type))
- load = JIT_ArrayLoadAt(fn->injector, symref, ptr, index, JIT_Double);
- else if (dmrC_is_ptr_type(insn->type))
- load = JIT_ArrayLoadAt(fn->injector, symref, ptr, index, JIT_Address);
- else
- load = JIT_ArrayLoadAt(fn->injector, symref, ptr, index, JIT_Int64);
- break;
- }
- }
- if (load == NULL)
- return NULL;
- assert(JIT_GetNodeType(load) != JIT_NoType);
- insn->target->priv = load;
- return load;
-}
-
-static JIT_NodeRef output_op_store(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef ptr, target_in;
-
- if (is_aggregate_type(insn->type)) {
- dmrC_sparse_error(C, insn->pos,
- "store to aggregate type is "
- "not yet supported, failure at "
- "insn %s\n",
- dmrC_show_instruction(C, insn));
- return NULL;
- }
-
- target_in = pseudo_to_value(C, fn, insn->type, insn->target);
- if (!target_in)
- return NULL;
-
- if (insn->orig_type && dmrC_is_simple_type(C->S, insn->orig_type) && !dmrC_is_ptr_type(insn->orig_type)) {
- JIT_SymbolRef symref = insn->orig_type->priv;
- if (symref && JIT_IsTemporary(fn->injector, symref)) {
- JIT_StoreToTemporary(fn->injector, symref, target_in);
- return target_in;
- }
- }
-
- /* Following causes test failures -- To be investgated */
- //if (insn->src->type == PSEUDO_SYM) {
- // JIT_SymbolRef symref = get_sym_value(C, fn, insn->src, true);
- // if (symref && JIT_IsTemporary(fn->injector, symref)) {
- // JIT_StoreToTemporary(fn->injector, symref, target_in);
- // return target_in;
- // }
- //}
-
- ptr = pseudo_to_value(C, fn, insn->type, insn->src);
- if (!ptr)
- return NULL;
- ptr = build_cast(C, fn, ptr, &PtrType, 0);
- int64_t index = (int64_t)insn->offset;
- assert(JIT_GetNodeType(ptr) == JIT_Address);
- uint64_t symref = (uint64_t)insn->orig_type;
- JIT_ArrayStoreAt(fn->injector, symref, ptr, index, target_in);
- return target_in;
-}
-
-static JIT_NodeRef output_op_phisrc(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef v;
- struct instruction *phi;
-
- assert(insn->target->priv == NULL);
-
- /* target = src */
- v = pseudo_to_value(C, fn, insn->type, insn->phi_src);
- if (!v)
- return NULL;
-
- FOR_EACH_PTR(insn->phi_users, phi)
- {
- JIT_SymbolRef symref;
-
- assert(phi->opcode == OP_PHI);
- /* phi must be load from alloca */
- symref = phi->target->priv2;
- if (!symref)
- return NULL;
- /* We do the convert below because Sparse treats pointers and
- integers as interchangeable - but OMR doesn't - so saving to a
- pointer can fail due to type mismatch */
- JIT_StoreToTemporary(fn->injector, symref, convert_to(fn, v, JIT_GetSymbolType(symref), true));
- }
- END_FOR_EACH_PTR(phi);
- return v;
-}
-
-/**
- * Convert the pseudo to a value, and cast it to the expected type of the
- * instruction. If ptrtoint is true then convert pointer values to integers.
- */
-static JIT_NodeRef get_operand(struct dmr_C *C, struct function *fn, struct symbol *ctype, pseudo_t pseudo,
- bool ptrtoint, bool unsigned_cast)
-{
- JIT_NodeRef target;
- struct OMRType *instruction_type = get_symnode_or_basetype(C, fn, ctype);
- (void)ptrtoint;
- (void)unsigned_cast;
- if (instruction_type == NULL)
- return NULL;
- target = pseudo_to_value(C, fn, ctype, pseudo);
- if (!target)
- return NULL;
- return target;
-}
-
-static struct symbol *pseudo_type(struct dmr_C *C, pseudo_t pseudo)
-{
- switch (pseudo->type) {
- case PSEUDO_SYM:
- case PSEUDO_ARG:
- return pseudo->sym;
- case PSEUDO_REG:
- case PSEUDO_PHI:
- return pseudo->def->type;
- case PSEUDO_VAL:
- return C->target->size_t_ctype;
- case PSEUDO_VOID:
- default:
- return &C->S->void_ctype;
- }
-}
-
-static JIT_NodeRef output_op_cbr(struct dmr_C *C, struct function *fn, struct instruction *br)
-{
- JIT_NodeRef value = pseudo_to_value(C, fn, br->type, br->cond);
- if (!value)
- return NULL;
- // JIT_GenerateTreeTop(fn->injector, value);
- JIT_BlockRef true_block = JIT_GetBlock(fn->injector, br->bb_true->nr);
- JIT_BlockRef false_block = JIT_GetBlock(fn->injector, br->bb_false->nr);
- JIT_NodeRef if_node = JIT_IfNotZeroValue(fn->injector, value, true_block);
- // OMR expects the code to fall through to next block here
- // which is assumed to be the else block
- // But we want to handle false block explicitly
- // During the initial scan we already accounted for extra block here
- int fallthrough_blocknum = br->bb->nr + 1; // Next block is meant to be a fallthrough block
- JIT_BlockRef fallthrough_block = JIT_GetBlock(fn->injector, fallthrough_blocknum);
- // Add an edge from current block to fallthrough block
- JIT_CFGAddEdge(fn->injector, JIT_BlockAsCFGNode(JIT_GetCurrentBlock(fn->injector)),
- JIT_BlockAsCFGNode(fallthrough_block));
- // Switch to fallthrough block
- JIT_SetCurrentBlock(fn->injector, fallthrough_blocknum);
- // In the fallthrough block we only need a goto
- JIT_Goto(fn->injector, false_block);
- return if_node;
-}
-
-static JIT_NodeRef is_neq_zero(struct dmr_C *C, struct function *fn, JIT_NodeRef value)
-{
- JIT_NodeRef cond = NULL;
- JIT_Type value_type = JIT_GetNodeType(value);
- (void)C;
- switch (value_type) {
- case JIT_Int32:
- cond = JIT_CreateNode2C(OP_icmpne, value, JIT_ZeroValue(fn->injector, JIT_Int32));
- break;
-
- case JIT_Int64:
- cond = JIT_CreateNode2C(OP_lcmpne, value, JIT_ZeroValue(fn->injector, JIT_Int64));
- break;
-
- case JIT_Int16:
- cond = JIT_CreateNode2C(OP_scmpne, value, JIT_ZeroValue(fn->injector, JIT_Int16));
- break;
-
- case JIT_Int8:
- cond = JIT_CreateNode2C(OP_bcmpne, value, JIT_ZeroValue(fn->injector, JIT_Int8));
- break;
-
- case JIT_Address:
- cond = JIT_CreateNode2C(OP_acmpne, value, JIT_ZeroValue(fn->injector, JIT_Address));
- break;
-
- case JIT_Double:
- cond = JIT_CreateNode2C(OP_dcmpneu, value, JIT_ZeroValue(fn->injector, JIT_Double));
- break;
-
- case JIT_Float:
- cond = JIT_CreateNode2C(OP_fcmpneu, value, JIT_ZeroValue(fn->injector, JIT_Float));
- break;
- default:
- fprintf(stderr, "Cannot construct a zero object of JIT type %d\n", value_type);
- break;
- }
- return cond;
-}
-
-static JIT_NodeRef output_op_compare(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef lhs, rhs, target = NULL;
-
- if (insn->src1->type == PSEUDO_VAL)
- lhs = val_to_value(C, fn, insn->src1->value, pseudo_type(C, insn->src2));
- else
- lhs = pseudo_to_value(C, fn, insn->type, insn->src1);
- if (!lhs)
- return NULL;
- if (insn->src2->type == PSEUDO_VAL)
- rhs = val_to_value(C, fn, insn->src2->value, pseudo_type(C, insn->src1));
- else
- rhs = pseudo_to_value(C, fn, insn->type, insn->src2);
- if (!rhs)
- return NULL;
-
- struct OMRType *dst_type = insn_symbol_type(C, fn, insn);
- if (!dst_type)
- return NULL;
-
- JIT_Type op_type = JIT_GetNodeType(lhs);
-
- switch (insn->opcode) {
- case OP_SET_LT:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmplt, lhs, rhs);
- else if (op_type == JIT_Float)
- target = JIT_CreateNode2C(OP_fcmplt, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lcmplt, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_icmplt, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_scmplt, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bcmplt, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmplt, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- case OP_SET_B:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmplt, lhs, rhs);
- else if (op_type == JIT_Float)
- target = JIT_CreateNode2C(OP_fcmplt, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lucmplt, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_iucmplt, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_sucmplt, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bucmplt, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmplt, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- case OP_SET_LE:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmple, lhs, rhs);
- else if (op_type == JIT_Float)
- target = JIT_CreateNode2C(OP_fcmple, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lcmple, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_icmple, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_scmple, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bcmple, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmple, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- case OP_SET_BE:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmple, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_fcmple, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lucmple, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_iucmple, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_sucmple, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bucmple, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmple, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- case OP_SET_GT:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmpgt, lhs, rhs);
- else if (op_type == JIT_Float)
- target = JIT_CreateNode2C(OP_fcmpgt, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lcmpgt, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_icmpgt, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_scmpgt, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bcmpgt, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmpgt, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- case OP_SET_A:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmpgt, lhs, rhs);
- else if (op_type == JIT_Float)
- target = JIT_CreateNode2C(OP_fcmpgt, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lucmpgt, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_iucmpgt, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_sucmpgt, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bucmpgt, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmpgt, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- case OP_SET_GE:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmpge, lhs, rhs);
- else if (op_type == JIT_Float)
- target = JIT_CreateNode2C(OP_fcmpge, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lcmpge, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_icmpge, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_scmpge, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bcmpge, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmpge, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- case OP_SET_AE:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmpge, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_fcmpge, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lucmpge, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_iucmpge, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_sucmpge, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bucmpge, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmpge, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- case OP_SET_EQ:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmpeq, lhs, rhs);
- else if (op_type == JIT_Float)
- target = JIT_CreateNode2C(OP_fcmpeq, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lcmpeq, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_icmpeq, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_scmpeq, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bcmpeq, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmpeq, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- case OP_SET_NE:
- if (op_type == JIT_Double)
- target = JIT_CreateNode2C(OP_dcmpneu, lhs, rhs);
- else if (op_type == JIT_Float)
- target = JIT_CreateNode2C(OP_fcmpneu, lhs, rhs);
- else if (op_type == JIT_Int64)
- target = JIT_CreateNode2C(OP_lcmpne, lhs, rhs);
- else if (op_type == JIT_Int32)
- target = JIT_CreateNode2C(OP_icmpne, lhs, rhs);
- else if (op_type == JIT_Int16)
- target = JIT_CreateNode2C(OP_scmpne, lhs, rhs);
- else if (op_type == JIT_Int8)
- target = JIT_CreateNode2C(OP_bcmpne, lhs, rhs);
- else if (op_type == JIT_Address)
- target = JIT_CreateNode2C(OP_acmpne, convert_to(fn, lhs, JIT_Address, true),
- convert_to(fn, rhs, JIT_Address, true));
- break;
- default:
- break;
- }
- assert(JIT_GetNodeType(target) != JIT_NoType);
- insn->target->priv = target;
- return target;
-}
-
-static JIT_NodeRef output_op_binary(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef lhs, rhs, target = NULL;
-
- // TODO is this enough or do we need special unsigned opcodes?
- bool unsigned_op = insn->opcode == OP_MULU || insn->opcode == OP_DIVU || insn->opcode == OP_MODU;
-
- lhs = get_operand(C, fn, insn->type, insn->src1, 1, unsigned_op);
- if (!lhs)
- return NULL;
-
- rhs = get_operand(C, fn, insn->type, insn->src2, 1, unsigned_op);
- if (!rhs)
- return NULL;
-
- switch (insn->opcode) {
- /* Binary */
- case OP_ADD:
- switch (insn->size) {
- case 64:
- if (dmrC_is_float_type(C->S, insn->type))
- target = JIT_CreateNode2C(OP_dadd, lhs, rhs);
- else {
- if (JIT_GetNodeType(lhs) == JIT_Address) {
- if (JIT_GetNodeType(rhs) == JIT_Int64) {
- target = JIT_CreateNode2C(OP_aladd, lhs, rhs);
- } else if (JIT_GetNodeType(rhs) == JIT_Int32) {
- target = JIT_CreateNode2C(OP_aiadd, lhs, rhs);
- } else {
- dmrC_sparse_error(C, insn->pos,
- "The add operand for a "
- "pointer value must be "
- "int64 or int32\n");
- }
- } else if (JIT_GetNodeType(rhs) == JIT_Address) {
- if (JIT_GetNodeType(lhs) == JIT_Int64) {
- target = JIT_CreateNode2C(OP_aladd, rhs, lhs);
- } else if (JIT_GetNodeType(lhs) == JIT_Int32) {
- target = JIT_CreateNode2C(OP_aiadd, rhs, lhs);
- } else {
- dmrC_sparse_error(C, insn->pos,
- "The add operand for a "
- "pointer value must be "
- "int64 or int32\n");
- }
- } else
- target = JIT_CreateNode2C(OP_ladd, lhs, rhs);
- }
- break;
- case 32:
- if (dmrC_is_float_type(C->S, insn->type))
- target = JIT_CreateNode2C(OP_fadd, lhs, rhs);
- else
- target = JIT_CreateNode2C(OP_iadd, lhs, rhs);
- break;
- }
- break;
- case OP_SUB:
- switch (insn->size) {
- case 64:
- if (dmrC_is_float_type(C->S, insn->type))
- target = JIT_CreateNode2C(OP_dsub, lhs, rhs);
- else {
- if (JIT_GetNodeType(lhs) == JIT_Address && JIT_GetNodeType(rhs) == JIT_Address) {
- // target = JIT_CreateNode2C(OP_asub,
- // lhs, rhs);
- // For some reason above is returning
- // NoType?
- target =
- JIT_CreateNode2C(OP_lsub, JIT_ConvertTo(fn->injector, lhs, JIT_Int64, true),
- JIT_ConvertTo(fn->injector, rhs, JIT_Int64, true));
- assert(JIT_GetNodeType(target) != JIT_NoType);
- }
- /* Since OMR only supports adding integer to a
- pointer, but C allows integer subtraction as
- well - we convert the op to an pointer add with
- negative offset. C allows the
- address to lhs or rhs - meaning is the same */
- else if (JIT_GetNodeType(lhs) == JIT_Address) {
- if (JIT_GetNodeType(rhs) == JIT_Int64) {
- target =
- JIT_CreateNode2C(OP_aladd, lhs, JIT_CreateNode1C(OP_lneg, rhs));
- assert(JIT_GetNodeType(target) != JIT_NoType);
- } else if (JIT_GetNodeType(rhs) == JIT_Int32) {
- target =
- JIT_CreateNode2C(OP_aiadd, lhs, JIT_CreateNode1C(OP_ineg, rhs));
- assert(JIT_GetNodeType(target) != JIT_NoType);
- } else {
- dmrC_sparse_error(C, insn->pos,
- "The add operand for a "
- "pointer value must be "
- "int64 or int32\n");
- }
- } else if (JIT_GetNodeType(rhs) == JIT_Address) {
- if (JIT_GetNodeType(lhs) == JIT_Int64) {
- target =
- JIT_CreateNode2C(OP_aladd, rhs, JIT_CreateNode1C(OP_lneg, lhs));
- assert(JIT_GetNodeType(target) != JIT_NoType);
- } else if (JIT_GetNodeType(lhs) == JIT_Int32) {
- target =
- JIT_CreateNode2C(OP_aiadd, rhs, JIT_CreateNode1C(OP_ineg, lhs));
- assert(JIT_GetNodeType(target) != JIT_NoType);
- } else {
- dmrC_sparse_error(C, insn->pos,
- "The add operand for a "
- "pointer value must be "
- "int64 or int32\n");
- }
- } else {
- target = JIT_CreateNode2C(OP_lsub, lhs, rhs);
- assert(JIT_GetNodeType(target) != JIT_NoType);
- }
- }
- break;
- case 32:
- if (dmrC_is_float_type(C->S, insn->type))
- target = JIT_CreateNode2C(OP_fsub, lhs, rhs);
- else
- target = JIT_CreateNode2C(OP_isub, lhs, rhs);
- break;
- }
- break;
- case OP_MULU:
- assert(JIT_GetNodeType(lhs) != JIT_Address && JIT_GetNodeType(rhs) != JIT_Address);
- switch (insn->size) {
- case 64:
- if (dmrC_is_float_type(C->S, insn->type))
- target = JIT_CreateNode2C(OP_dmul, lhs, rhs);
- else
- target = JIT_CreateNode2C(OP_lmul, lhs, rhs);
- break;
- case 32:
- if (dmrC_is_float_type(C->S, insn->type))
- target = JIT_CreateNode2C(OP_fmul, lhs, rhs);
- else
- target = JIT_CreateNode2C(OP_iumul, lhs, rhs);
- break;
- }
- break;
- case OP_MULS:
- assert(JIT_GetNodeType(lhs) != JIT_Address && JIT_GetNodeType(rhs) != JIT_Address);
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_lmul, lhs, rhs);
- break;
- case 32:
- target = JIT_CreateNode2C(OP_imul, lhs, rhs);
- break;
- }
- break;
- case OP_DIVU:
- assert(JIT_GetNodeType(lhs) != JIT_Address && JIT_GetNodeType(rhs) != JIT_Address);
- switch (insn->size) {
- case 64:
- if (dmrC_is_float_type(C->S, insn->type))
- target = JIT_CreateNode2C(OP_ddiv, lhs, rhs);
- else
- target = JIT_CreateNode2C(OP_ludiv, lhs, rhs);
- break;
- case 32:
- if (dmrC_is_float_type(C->S, insn->type))
- target = JIT_CreateNode2C(OP_fdiv, lhs, rhs);
- else
- target = JIT_CreateNode2C(OP_iudiv, lhs, rhs);
- break;
- }
- break;
- case OP_DIVS:
- assert(JIT_GetNodeType(lhs) != JIT_Address && JIT_GetNodeType(rhs) != JIT_Address);
- switch (insn->size) {
- case 64:
- if (JIT_GetNodeType(lhs) != JIT_Int64 || JIT_GetNodeType(rhs) != JIT_Int64) {
- target = NULL;
- } else
- target = JIT_CreateNode2C(OP_ldiv, lhs, rhs);
- break;
- case 32:
- target = JIT_CreateNode2C(OP_idiv, lhs, rhs);
- break;
- }
- break;
-
- case OP_MODS:
- case OP_MODU:
- assert(!dmrC_is_float_type(C->S, insn->type));
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_lrem, lhs, rhs);
- break;
- case 32:
- target = JIT_CreateNode2C(OP_irem, lhs, rhs);
- break;
- }
- break;
- case OP_SHL:
- assert(!dmrC_is_float_type(C->S, insn->type));
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_lshl, lhs, rhs);
- break;
- case 32:
- target = JIT_CreateNode2C(OP_ishl, lhs, rhs);
- break;
- }
- break;
- case OP_LSR:
- assert(!dmrC_is_float_type(C->S, insn->type));
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_lshr, lhs, rhs);
- break;
- case 32:
- target = JIT_CreateNode2C(OP_ishr, lhs, rhs);
- break;
- }
- break;
- case OP_ASR:
- assert(!dmrC_is_float_type(C->S, insn->type));
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_lshr, lhs, rhs);
- break;
- case 32:
- target = JIT_CreateNode2C(OP_ishr, lhs, rhs);
- break;
- }
- break;
-
- /* Logical */
- case OP_AND:
- assert(!dmrC_is_float_type(C->S, insn->type));
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_land, lhs, rhs);
- break;
- case 32:
- target = JIT_CreateNode2C(OP_iand, lhs, rhs);
- break;
- }
- break;
- case OP_OR:
- assert(!dmrC_is_float_type(C->S, insn->type));
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_lor, lhs, rhs);
- break;
- case 32:
- target = JIT_CreateNode2C(OP_ior, lhs, rhs);
- break;
- }
- break;
- case OP_XOR:
- assert(!dmrC_is_float_type(C->S, insn->type));
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_lxor, lhs, rhs);
- break;
- case 32:
- target = JIT_CreateNode2C(OP_ixor, lhs, rhs);
- break;
- }
- break;
- case OP_AND_BOOL: {
- JIT_NodeRef lhs_nz, rhs_nz;
- struct OMRType *dst_type;
-
- lhs_nz = is_neq_zero(C, fn, lhs);
- rhs_nz = is_neq_zero(C, fn, rhs);
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_land, lhs_nz, rhs_nz);
- break;
- case 1:
- case 32:
- target = JIT_CreateNode2C(OP_iand, lhs_nz, rhs_nz);
- break;
- }
- if (!target)
- return NULL;
- dst_type = insn_symbol_type(C, fn, insn);
- if (!dst_type)
- return NULL;
- target = build_cast(C, fn, target, dst_type, 1);
- break;
- }
- case OP_OR_BOOL: {
- JIT_NodeRef lhs_nz, rhs_nz;
- struct OMRType *dst_type;
-
- lhs_nz = is_neq_zero(C, fn, lhs);
- rhs_nz = is_neq_zero(C, fn, rhs);
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_lor, lhs_nz, rhs_nz);
- break;
- case 1:
- case 32:
- target = JIT_CreateNode2C(OP_ior, lhs_nz, rhs_nz);
- break;
- }
- if (!target)
- return NULL;
- dst_type = insn_symbol_type(C, fn, insn);
- if (!dst_type)
- return NULL;
- target = build_cast(C, fn, target, dst_type, 1);
- break;
- }
- }
- assert(JIT_GetNodeType(target) != JIT_NoType);
- insn->target->priv = target;
-
- return target;
-}
-
-static JIT_NodeRef output_op_setval(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- struct expression *expr = insn->val;
- struct OMRType *const_type;
- JIT_NodeRef target = NULL;
-
- if (!expr)
- return NULL;
-
- const_type = insn_symbol_type(C, fn, insn);
- if (!const_type)
- return NULL;
-
- switch (expr->type) {
- case EXPR_FVALUE:
- target = constant_fvalue(C, fn, expr->fvalue, const_type);
- break;
- default:
- dmrC_sparse_error(C, insn->pos, "unsupported expression type %d in setval\n", expr->type);
- dmrC_show_expression(C, expr);
- return NULL;
- }
- assert(JIT_GetNodeType(target) != JIT_NoType);
- insn->target->priv = target;
-
- return target;
-}
-
-static JIT_NodeRef output_op_symaddr(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef res, src;
- struct OMRType *dtype;
- JIT_SymbolRef sym;
-
- src = pseudo_to_value(C, fn, insn->type, insn->symbol);
- if (!src)
- return NULL;
-
- /* We need to tell the backend if a local var has had its
- address taken */
- if (insn->symbol->type == PSEUDO_SYM) {
- sym = get_sym_value(C, fn, insn->symbol, true);
- if (sym)
- JIT_SetAutoAddressTaken(fn->injector, sym);
- }
-
- dtype = get_symnode_or_basetype(C, fn, insn->type);
- if (!dtype)
- return NULL;
-
- res = build_cast(C, fn, src, dtype, 0);
- assert(JIT_GetNodeType(res) != JIT_NoType);
- insn->target->priv = res;
-
- return res;
-}
-
-static struct symbol *get_function_basetype(struct symbol *type)
-{
- if (type->type == SYM_PTR)
- type = type->ctype.base_type;
- assert(type->type == SYM_FN);
- return type;
-}
-
-static JIT_NodeRef output_op_call(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef target;
- int n_arg = 0, i;
- struct pseudo *arg;
- JIT_NodeRef *args;
-
- n_arg = ptrlist_size((struct ptr_list *)insn->arguments);
- args = alloca(n_arg * sizeof(JIT_NodeRef));
- struct symbol *ftype = get_function_basetype(insn->fntype);
-
- i = 0;
- FOR_EACH_PTR(insn->arguments, arg)
- {
- JIT_NodeRef value;
- struct symbol *atype;
-
- atype = dmrC_get_nth_symbol(ftype->arguments, i);
- value = NULL;
- if (arg->type == PSEUDO_VAL) {
- /* Value pseudos do not have type information. */
- /* Use the function prototype to get the type. */
- if (atype)
- value = val_to_value(C, fn, arg->value, atype);
- else {
- struct OMRType *type = int_type_by_size(fn, arg->size);
- if (!type) {
- dmrC_sparse_error(C, insn->pos,
- "pseudo value argument[%d] = %lld "
- "has invalid size %d\n",
- i + 1, arg->value, arg->size);
- } else {
- value = constant_value(C, fn, arg->value, type);
- }
- }
- } else {
- value = pseudo_to_value(C, fn, atype, arg);
- }
- if (!value)
- return NULL;
- if (atype) {
- struct OMRType *argtype = get_symnode_type(C, fn, atype);
- if (!argtype)
- return NULL;
- value = build_cast(C, fn, value, argtype, 0);
- if (!value)
- return NULL;
- }
- args[i++] = value;
- }
- END_FOR_EACH_PTR(arg);
-
- if (insn->func->type == PSEUDO_SYM) {
- struct symbol *sym = insn->func->sym;
- const char *name = dmrC_show_ident(C, sym->ident);
- struct OMRType *type = get_symnode_type(C, fn, sym);
- if (type->type != RT_FUNCTION) {
- return NULL;
- }
- target = JIT_Call(fn->injector, name, i, args);
- }
- else {
- JIT_NodeRef funcptr = pseudo_to_value(C, fn, insn->type, insn->func);
- if (funcptr == NULL || JIT_GetNodeType(funcptr) != JIT_Address) {
- return NULL;
- }
- struct OMRType *function_type = type_to_OMRtype(C, fn, ftype, NULL);
- JIT_Type jit_return_type = map_OMRtype(function_type->return_type);
- target = JIT_IndirectCall(fn->injector, funcptr, jit_return_type, i, args);
- }
- if (JIT_GetNodeType(target) != JIT_NoType)
- insn->target->priv = target;
- return target;
-}
-
-static JIT_NodeRef output_op_not(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef src, target;
-
- src = pseudo_to_value(C, fn, insn->type, insn->src);
- if (!src)
- return NULL;
-
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode2C(OP_lxor, src, JIT_ConstInt64(0xFFFFFFFFFFFFFFFFLL));
- break;
- case 32:
- target = JIT_CreateNode2C(OP_ixor, src, JIT_ConstInt32(0xFFFFFFFF));
- break;
- case 16:
- target = JIT_CreateNode2C(OP_sxor, src, JIT_ConstInt16(0xFFFF));
- break;
- case 8:
- target = JIT_CreateNode2C(OP_bxor, src, JIT_ConstInt8(0xFF));
- break;
- }
- assert(JIT_GetNodeType(target) != JIT_NoType);
- insn->target->priv = target;
-
- return target;
-}
-
-static JIT_NodeRef output_op_neg(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef src, target;
-
- src = pseudo_to_value(C, fn, insn->type, insn->src);
- if (!src)
- return NULL;
-
- target = NULL;
- if (dmrC_is_float_type(C->S, insn->type)) {
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode1C(OP_dneg, src);
- break;
- case 32:
- target = JIT_CreateNode1C(OP_fneg, src);
- break;
- }
- } else {
- switch (insn->size) {
- case 64:
- target = JIT_CreateNode1C(OP_lneg, src);
- break;
- case 32:
- target = JIT_CreateNode1C(OP_ineg, src);
- break;
- case 16:
- target = JIT_CreateNode1C(OP_sneg, src);
- break;
- case 8:
- target = JIT_CreateNode1C(OP_bneg, src);
- break;
- }
- }
- assert(JIT_GetNodeType(target) != JIT_NoType);
- insn->target->priv = target;
-
- return target;
-}
-
-static JIT_NodeRef output_op_sel(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef target, src1, src2, src3;
-
- src1 = pseudo_to_value(C, fn, insn->type, insn->src1);
- if (!src1)
- return NULL;
-
- src1 = is_neq_zero(C, fn, src1);
- if (!src1)
- return NULL;
-
- src2 = get_operand(C, fn, insn->type, insn->src2, 0, 0);
- if (!src2)
- return NULL;
- src3 = get_operand(C, fn, insn->type, insn->src3, 0, 0);
- if (!src3)
- return NULL;
-
- struct OMRType *insntype = insn_symbol_type(C, fn, insn);
- JIT_Type target_type = map_OMRtype(insntype);
- JIT_NodeOpCode op_code;
- switch (target_type) {
- case JIT_Int32:
- op_code = OP_iternary;
- break;
- case JIT_Int64:
- op_code = OP_lternary;
- break;
- case JIT_Int16:
- op_code = OP_sternary;
- break;
- case JIT_Int8:
- op_code = OP_bternary;
- break;
- case JIT_Address:
- op_code = OP_aternary;
- break;
- case JIT_Float:
- op_code = OP_fternary;
- break;
- case JIT_Double:
- op_code = OP_dternary;
- break;
- default:
- // TODO error message
- return NULL;
- }
- target = JIT_CreateNode3C(op_code, src1, src2, src3);
- assert(JIT_GetNodeType(target) != JIT_NoType);
- insn->target->priv = target;
- return target;
-}
-
-static JIT_NodeRef output_op_fpcast(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef src, target;
- struct OMRType *dtype;
- struct symbol *otype = insn->orig_type;
-
- src = insn->src->priv;
- if (!src)
- src = pseudo_to_value(C, fn, insn->type, insn->src);
- if (!src)
- return NULL;
-
- dtype = insn_symbol_type(C, fn, insn);
- if (!dtype)
- return NULL;
-
- target = build_cast(C, fn, src, dtype, !dmrC_is_signed_type(otype));
- assert(JIT_GetNodeType(target) != JIT_NoType);
- insn->target->priv = target;
-
- return target;
-}
-
-static JIT_NodeRef output_op_switch(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef switch_value;
- struct basic_block *default_bb = NULL;
- struct multijmp *jmp;
- int n_jmp = 0;
-
- FOR_EACH_PTR(insn->multijmp_list, jmp)
- {
- if (jmp->begin <= jmp->end) { /* case M..N */
- n_jmp += (int)(jmp->end - jmp->begin) + 1;
- } else /* default case */
- default_bb = jmp->target;
- }
- END_FOR_EACH_PTR(jmp);
-
- if (!default_bb)
- return NULL;
-
- switch_value = pseudo_to_value(C, fn, insn->type, insn->target);
- if (!switch_value)
- return NULL;
-
- int32_t *values = alloca(n_jmp * sizeof(int32_t));
- JIT_BlockRef *blocks = alloca(n_jmp * sizeof(JIT_BlockRef));
-
- int i = 0;
- FOR_EACH_PTR(insn->multijmp_list, jmp)
- {
- long long val;
- for (val = jmp->begin; val <= jmp->end; val++) {
- if (val < INT_MIN || val > INT_MAX)
- return NULL;
-
- values[i] = (int32_t)val;
- blocks[i] = JIT_GetBlock(fn->injector, jmp->target->nr);
- i++;
- }
- }
- END_FOR_EACH_PTR(jmp);
-
- return JIT_Switch(fn->injector, switch_value, JIT_GetBlock(fn->injector, default_bb->nr), n_jmp, blocks,
- values);
-}
-
-static JIT_NodeRef output_op_ptrcast(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef src, target;
- struct OMRType *dtype;
- struct symbol *otype = insn->orig_type;
-
- assert(dmrC_is_ptr_type(insn->type));
-
- src = insn->src->priv;
- if (!src)
- src = get_operand(C, fn, otype, insn->src, 1, 0);
- if (!src)
- return NULL;
-
- dtype = insn_symbol_type(C, fn, insn);
- if (!dtype)
- return NULL;
-
- target = build_cast(C, fn, src, dtype, false);
- assert(JIT_GetNodeType(target) != JIT_NoType);
- insn->target->priv = target;
-
- return target;
-}
-
-static JIT_NodeRef output_op_cast(struct dmr_C *C, struct function *fn, struct instruction *insn, bool unsignedcast)
-{
- JIT_NodeRef src, target;
- struct OMRType *dtype;
- struct symbol *otype = insn->orig_type;
-
- if (dmrC_is_ptr_type(insn->type)) {
- return output_op_ptrcast(C, fn, insn);
- }
-
- src = insn->src->priv;
- if (!src)
- src = pseudo_to_value(C, fn, insn->type, insn->src);
- if (dmrC_is_int_type(C->S, otype)) {
- struct OMRType *stype = get_symnode_or_basetype(C, fn, otype);
- src = build_cast(C, fn, src, stype, unsignedcast);
- }
- if (!src)
- return NULL;
-
- assert(!dmrC_is_float_type(C->S, insn->type));
-
- dtype = insn_symbol_type(C, fn, insn);
- if (!dtype)
- return NULL;
- target = build_cast(C, fn, src, dtype, unsignedcast);
- assert(JIT_GetNodeType(target) != JIT_NoType);
- insn->target->priv = target;
-
- return target;
-}
-
-static JIT_NodeRef output_op_ret(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- pseudo_t pseudo = insn->src;
-
- if (pseudo && pseudo != VOID_PSEUDO(C)) {
- JIT_NodeRef result = pseudo_to_value(C, fn, insn->type, pseudo);
- if (!result)
- return NULL;
- return JIT_ReturnValue(fn->injector, result);
- } else
- return JIT_ReturnNoValue(fn->injector);
-}
-
-static JIT_NodeRef output_op_br(struct dmr_C *C, struct function *fn, struct instruction *br)
-{
- (void)C;
- JIT_BlockRef target_block = JIT_GetBlock(fn->injector, br->bb_true->nr);
- return JIT_Goto(fn->injector, target_block);
-}
-
-/* return 1 on success, 0 on failure */
-static int output_insn(struct dmr_C *C, struct function *fn, struct instruction *insn)
-{
- JIT_NodeRef v = NULL;
- switch (insn->opcode) {
- case OP_RET:
- v = output_op_ret(C, fn, insn);
- break;
- case OP_BR:
- v = output_op_br(C, fn, insn);
- break;
- case OP_CBR:
- v = output_op_cbr(C, fn, insn);
- break;
- case OP_PHISOURCE:
- v = output_op_phisrc(C, fn, insn);
- break;
- case OP_PHI:
- v = output_op_phi(C, fn, insn);
- break;
- case OP_LOAD:
- v = output_op_load(C, fn, insn);
- break;
- case OP_SYMADDR:
- v = output_op_symaddr(C, fn, insn);
- break;
- case OP_SETVAL:
- v = output_op_setval(C, fn, insn);
- break;
-
- case OP_SWITCH:
- v = output_op_switch(C, fn, insn);
- break;
-
- case OP_COMPUTEDGOTO:
- dmrC_sparse_error(C, insn->pos, "computed goto is not supported\n");
- return 0;
-
- case OP_LNOP:
- return 0;
-
- case OP_STORE:
- v = output_op_store(C, fn, insn);
- break;
-
- case OP_SNOP:
- return 0;
-
- case OP_CALL:
- v = output_op_call(C, fn, insn);
- break;
- case OP_CAST:
- v = output_op_cast(C, fn, insn, true);
- break;
- case OP_SCAST:
- v = output_op_cast(C, fn, insn, false);
- break;
- case OP_FPCAST:
- v = output_op_fpcast(C, fn, insn);
- break;
- case OP_PTRCAST:
- v = output_op_ptrcast(C, fn, insn);
- break;
-
- 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:
- v = output_op_binary(C, fn, insn);
- break;
-
- 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:
- v = output_op_compare(C, fn, insn);
- break;
-
- case OP_SEL:
- v = output_op_sel(C, fn, insn);
- break;
-
- case OP_SLICE:
- return 0;
-
- case OP_NOT:
- v = output_op_not(C, fn, insn);
- break;
-
- case OP_NEG:
- v = output_op_neg(C, fn, insn);
- break;
-
- case OP_CONTEXT:
- case OP_RANGE:
- case OP_NOP:
- case OP_ASM:
- return 0;
-
- default:
- return 1;
- }
-
- if (v == NULL)
- dmrC_sparse_error(C, insn->pos, "failed to output instruction %s\n", dmrC_show_instruction(C, insn));
- return v != NULL;
-}
-
-/* return 1 on success, 0 on failure */
-static int output_bb(struct dmr_C *C, struct function *fn, struct basic_block *bb)
-{
- struct instruction *insn;
-
- JIT_SetCurrentBlock(fn->injector, bb->nr);
- FOR_EACH_PTR(bb->insns, insn)
- {
- if (!insn->bb)
- continue;
-
- // Useful for debugging
- // fprintf(stderr, "Instruction %s\n",
- // dmrC_show_instruction(C, insn));
-
- if (!output_insn(C, fn, insn)) {
- dmrC_sparse_error(C, insn->pos, "failed to output %s\n", dmrC_show_instruction(C, insn));
- return 0;
- }
- }
- END_FOR_EACH_PTR(insn);
-
- return 1;
-}
-
-static bool JIT_ILBuilderImpl(JIT_ILInjectorRef injector, void *userdata)
-{
- struct function *fn = (struct function *)userdata;
- struct entrypoint *ep = fn->ep;
- struct dmr_C *C = fn->C;
- struct basic_block *bb;
- pseudo_t pseudo;
-
- fn->injector = injector;
-
- /*
- Count and number the basic blocks.
- Whenever a basic block ends with CBR instruction we will
- need an extra block in OMR so we count such blocks as 2.
- The block numbers will be directly used to access corresponding
- OMR blocks.
- */
- unsigned int bbnr = 0;
- FOR_EACH_PTR(ep->bbs, bb)
- {
- bool saw_cbr = false;
- struct instruction *insn;
- FOR_EACH_PTR(bb->insns, insn)
- {
- if (!insn->bb || insn->opcode != OP_CBR)
- continue;
- saw_cbr = true;
- break;
- }
- END_FOR_EACH_PTR(insn);
- /* The bb->nr field is not used by the
- frontend anymore so we can use it to
- decide which the order of basic blocks.
- */
- bb->nr = bbnr++;
- if (saw_cbr)
- bbnr++; /* Allow an extra block here because of the way
- OMR does conditional branching (see CBR
- codegen) */
- }
- END_FOR_EACH_PTR(bb);
-
- /* Number of basic blocks we need - complicated by how OMRJIT handles
- * branching */
- JIT_CreateBlocks(fn->injector, bbnr);
- /* At this point we are at block 0 */
- FOR_EACH_PTR(ep->bbs, bb)
- {
- struct instruction *insn;
- /* allocate stack storage for each phi */
- FOR_EACH_PTR(bb->insns, insn)
- {
- if (!insn->bb || insn->opcode != OP_PHI)
- continue;
-
- /* insert alloca into entry block */
- JIT_SymbolRef symref = OMR_alloca(fn, insn_symbol_type(fn->C, fn, insn),
- instruction_size_in_bytes(fn->C, insn), true);
- if (!symref)
- goto Efailed;
-
- // Unlike the Sparse LLVM version we
- // save the symbol reference here and perform the load
- // when we encounter the PHI instructions
- // NOTE therefore priv2 is always a JIT_SymbolRef
- insn->target->priv2 = symref;
- insn->target->priv = NULL;
- }
- END_FOR_EACH_PTR(insn);
- }
- END_FOR_EACH_PTR(bb);
-
- /* Try to do allocas for all declared local symbols up front */
- FOR_EACH_PTR(ep->accesses, pseudo)
- {
- if (pseudo->type == PSEUDO_SYM) {
- if (dmrC_is_extern(pseudo->sym) || dmrC_is_static(pseudo->sym) || dmrC_is_toplevel(pseudo->sym))
- continue;
- if (!get_sym_value(C, fn, pseudo, false))
- goto Efailed;
- }
- }
- END_FOR_EACH_PTR(arg);
-
- /*
- Now generate IL for each block
- */
- FOR_EACH_PTR(ep->bbs, bb)
- {
- if (!output_bb(C, fn, bb)) {
- goto Efailed;
- }
- }
- END_FOR_EACH_PTR(bb);
-
- // The following flag triggers loop optimizations at O2
- JIT_SetMayHaveLoops(fn->injector);
-
- return true;
-
-Efailed:
- return false;
-}
-
-static bool output_fn(struct dmr_C *C, JIT_ContextRef module, struct entrypoint *ep)
-{
- bool success = false;
- struct symbol *sym = ep->name;
- struct symbol *base_type = sym->ctype.base_type;
- struct symbol *ret_type = sym->ctype.base_type->ctype.base_type;
- struct function function;
- const char *name;
- struct symbol *arg;
- int nr_args = 0;
-
- memset(&function, 0, sizeof function);
- function.C = C;
- function.context = module;
- function.ep = ep;
- if (base_type->variadic) {
- fprintf(stderr, "Variadic functions are not supported\n");
- return false;
- }
-
- dmrC_allocator_init(&function.type_allocator, "OMRtypes", sizeof(struct OMRType), __alignof__(struct OMRType),
- CHUNK);
-
- JIT_Type argtypes[JIT_MaxArgs];
-
- FOR_EACH_PTR(base_type->arguments, arg)
- {
- struct symbol *arg_base_type = arg->ctype.base_type;
- if (nr_args >= JIT_MaxArgs) {
- fprintf(stderr, "Only upto %d arguments supported\n", JIT_MaxArgs);
- goto Ereturn;
- }
- argtypes[nr_args] = check_supported_argtype(C, arg_base_type);
- if (argtypes[nr_args] == JIT_NoType) // Unsupported
- goto Ereturn;
- nr_args++;
- }
- END_FOR_EACH_PTR(arg);
-
- name = dmrC_show_ident(C, sym->ident);
- char function_name[128];
- snprintf(function_name, sizeof function_name, "%s", name);
-
- struct OMRType *function_type = type_to_OMRtype(C, &function, ret_type, NULL);
- function.return_type = check_supported_returntype(C, function_type);
- if (function.return_type == &BadType) {
- fprintf(stderr, "Function '%s' has unsupported return type\n", name);
- goto Ereturn;
- }
-
- JIT_Type freturn = map_OMRtype(function.return_type);
-
- function.builder =
- JIT_CreateFunctionBuilder(module, function_name, freturn, nr_args, argtypes, JIT_ILBuilderImpl, &function);
-
- void *p = JIT_Compile(function.builder, C->optimize);
- if (p)
- success = true;
-
- JIT_DestroyFunctionBuilder(function.builder);
-
-Ereturn:
- dmrC_allocator_destroy(&function.type_allocator);
-
- return success;
-}
-
-static int is_prototype(struct symbol *sym)
-{
- if (sym->type == SYM_NODE)
- sym = sym->ctype.base_type;
- return sym && sym->type == SYM_FN && !sym->stmt;
-}
-
-/* returns 1 on success, 0 on failure */
-static int compile(struct dmr_C *C, JIT_ContextRef module, struct symbol_list *list)
-{
- struct symbol *sym;
-
- FOR_EACH_PTR(list, sym)
- {
- struct entrypoint *ep;
- dmrC_expand_symbol(C, sym);
-
- if (is_prototype(sym)) {
- continue;
- }
-
- ep = dmrC_linearize_symbol(C, sym);
- if (ep) {
- if (!output_fn(C, module, ep))
- return 0;
- } else {
- fprintf(stderr, "Global data is not supported\n");
- return 0;
- }
- }
- END_FOR_EACH_PTR(sym);
-
- return 1;
-}
-
-char *safe_strdup(const char *in) {
- size_t len = strlen(in);
- char *buf = calloc(1, len+1);
- if (buf == NULL) {
- fprintf(stderr, "Out of memory\n");
- exit(1);
- }
- strncpy(buf, in, len+1);
- buf[len] = 0;
- return buf;
-}
-
-
-bool dmrC_omrcompile(int argc, char **argv, JIT_ContextRef module, const char *inputbuffer)
-{
- struct string_list *filelist = NULL;
- struct symbol_list *symlist;
- char *file;
-
- struct dmr_C *C = new_dmr_C();
- C->optimize = 1; /* Default */
- C->codegen = 1; /* Disables macros related to vararg processing */
- C->Wdecl = 0;
-
- int rc = 0;
- char *buffer = NULL;
- if (!setjmp(C->jmpbuf)) {
- symlist = dmrC_sparse_initialize(C, argc, argv, &filelist);
- if (compile(C, module, symlist)) {
- /* We need ->phi_users */
- /* This flag enables call to dmrC_track_pseudo_death() in
- linearize.c which sets
- phi_users list on PHISOURCE instructions */
- C->dbg_dead = 1;
- FOR_EACH_PTR(filelist, file)
- {
- symlist = dmrC_sparse(C, file);
- if (C->die_if_error || !symlist) {
- rc = 1;
- break;
- }
- if (!compile(C, module, symlist)) {
- rc = 1;
- break;
- }
- }
- END_FOR_EACH_PTR(file);
- if (inputbuffer && rc == 0) {
- buffer = safe_strdup(inputbuffer);
- if (!buffer)
- rc = 1;
- else {
- symlist = dmrC_sparse_buffer(C, "buffer", buffer, 0);
- if (C->die_if_error || !symlist) {
- rc = 1;
- } else if (!compile(C, module, symlist)) {
- rc = 1;
- }
- }
- }
- } else
- rc = 1;
- }
- else {
- rc = 1;
- }
- if (rc == 1) {
- fprintf(stderr, "Failed to compile given inputs\n");
- }
- if (buffer != NULL) free(buffer);
- destroy_dmr_C(C);
-
- return rc == 0;
-}
diff --git a/dmr_c/src/README.md b/dmr_c/src/README.md
deleted file mode 100644
index 82391ef..0000000
--- a/dmr_c/src/README.md
+++ /dev/null
@@ -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
diff --git a/dmr_c/src/allocate.c b/dmr_c/src/allocate.c
deleted file mode 100644
index 803a7ba..0000000
--- a/dmr_c/src/allocate.c
+++ /dev/null
@@ -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
-
-#include
-#include
-#include
-#include
-
-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;
-}
diff --git a/dmr_c/src/allocate.h b/dmr_c/src/allocate.h
deleted file mode 100644
index 0709535..0000000
--- a/dmr_c/src/allocate.h
+++ /dev/null
@@ -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
-
-#include
-#include
-#include
-#include
-
-#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
\ No newline at end of file
diff --git a/dmr_c/src/builtin.c b/dmr_c/src/builtin.c
deleted file mode 100644
index a0568c1..0000000
--- a/dmr_c/src/builtin.c
+++ /dev/null
@@ -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
-#include
-#include
-#include
-#include
-
-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;
- }
-}
diff --git a/dmr_c/src/char.c b/dmr_c/src/char.c
deleted file mode 100644
index a5111ad..0000000
--- a/dmr_c/src/char.c
+++ /dev/null
@@ -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
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-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;
-}
diff --git a/dmr_c/src/char.h b/dmr_c/src/char.h
deleted file mode 100644
index 2092127..0000000
--- a/dmr_c/src/char.h
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/dmr_c/src/cse.c b/dmr_c/src/cse.c
deleted file mode 100644
index 5b3ae68..0000000
--- a/dmr_c/src/cse.c
+++ /dev/null
@@ -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
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-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;
-}
diff --git a/dmr_c/src/evaluate.c b/dmr_c/src/evaluate.c
deleted file mode 100644
index 51b340d..0000000
--- a/dmr_c/src/evaluate.c
+++ /dev/null
@@ -1,3579 +0,0 @@
-/*
- * sparse/evaluate.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.
- *
- * Evaluate constant expressions.
- */
- /*
- * This version is part of the dmr_c project.
- * Copyright (C) 2017 Dibyendu Majumdar
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-static struct symbol *degenerate(struct dmr_C *C, struct expression *expr);
-static struct symbol *evaluate_symbol(struct dmr_C *C, struct symbol *sym);
-static void examine_fn_arguments(struct dmr_C *C, struct symbol *fn);
-static struct symbol *cast_to_bool(struct dmr_C *C, struct expression *expr);
-
-static struct symbol *evaluate_symbol_expression(struct dmr_C *C, struct expression *expr)
-{
- struct expression *addr;
- struct symbol *sym = expr->symbol;
- struct symbol *base_type;
-
- if (!sym) {
- dmrC_expression_error(C, expr, "undefined identifier '%s'", dmrC_show_ident(C, expr->symbol_name));
- return NULL;
- }
-
- dmrC_examine_symbol_type(C->S, sym);
-
- base_type = dmrC_get_base_type(C->S, sym);
- if (!base_type) {
- dmrC_expression_error(C, expr, "identifier '%s' has no type", dmrC_show_ident(C, expr->symbol_name));
- return NULL;
- }
-
- addr = dmrC_alloc_expression(C, expr->pos, EXPR_SYMBOL);
- addr->symbol = sym;
- addr->symbol_name = expr->symbol_name;
- addr->ctype = &C->S->lazy_ptr_ctype; /* Lazy evaluation: we need to do a proper job if somebody does &sym */
- expr->type = EXPR_PREOP;
- expr->op = '*';
- expr->unop = addr;
-
- /* The type of a symbol is the symbol itself! */
- expr->ctype = sym;
- return sym;
-}
-
-static struct symbol *evaluate_string(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *sym = dmrC_alloc_symbol(C->S, expr->pos, SYM_NODE);
- struct symbol *array = dmrC_alloc_symbol(C->S, expr->pos, SYM_ARRAY);
- struct expression *addr = dmrC_alloc_expression(C, expr->pos, EXPR_SYMBOL);
- struct expression *initstr = dmrC_alloc_expression(C, expr->pos, EXPR_STRING);
- unsigned int length = expr->string->length;
-
- sym->array_size = dmrC_alloc_const_expression(C, expr->pos, length);
- sym->bit_size = dmrC_bytes_to_bits(C->target, length);
- sym->ctype.alignment = 1;
- sym->string = 1;
- sym->ctype.modifiers = MOD_STATIC;
- sym->ctype.base_type = array;
- sym->initializer = initstr;
-
- initstr->ctype = sym;
- initstr->string = expr->string;
-
- array->array_size = sym->array_size;
- array->bit_size = dmrC_bytes_to_bits(C->target, length);
- array->ctype.alignment = 1;
- array->ctype.modifiers = MOD_STATIC;
- array->ctype.base_type = &C->S->char_ctype;
-
- addr->symbol = sym;
- addr->ctype = &C->S->lazy_ptr_ctype;
-
- expr->type = EXPR_PREOP;
- expr->op = '*';
- expr->unop = addr;
- expr->ctype = sym;
- return sym;
-}
-
-/* type has come from classify_type and is an integer type */
-static inline struct symbol *integer_promotion(struct dmr_C *C, struct symbol *type)
-{
- unsigned long mod = type->ctype.modifiers;
- int width = type->bit_size;
-
- /*
- * Bitfields always promote to the base type,
- * even if the bitfield might be bigger than
- * an "int".
- */
- if (type->type == SYM_BITFIELD) {
- type = type->ctype.base_type;
- }
- mod = type->ctype.modifiers;
- if (width < C->target->bits_in_int)
- return &C->S->int_ctype;
-
- /* If char/short has as many bits as int, it still gets "promoted" */
- if (mod & (MOD_CHAR | MOD_SHORT)) {
- if (mod & MOD_UNSIGNED)
- return &C->S->uint_ctype;
- return &C->S->int_ctype;
- }
- return type;
-}
-
-/*
- * integer part of usual arithmetic conversions:
- * integer promotions are applied
- * if left and right are identical, we are done
- * if signedness is the same, convert one with lower rank
- * unless unsigned argument has rank lower than signed one, convert the
- * signed one.
- * if signed argument is bigger than unsigned one, convert the unsigned.
- * otherwise, convert signed.
- *
- * Leaving aside the integer promotions, that is equivalent to
- * if identical, don't convert
- * if left is bigger than right, convert right
- * if right is bigger than left, convert right
- * otherwise, if signedness is the same, convert one with lower rank
- * otherwise convert the signed one.
- */
-static struct symbol *bigger_int_type(struct dmr_C *C, struct symbol *left, struct symbol *right)
-{
- unsigned long lmod, rmod;
-
- left = integer_promotion(C, left);
- right = integer_promotion(C, right);
-
- if (left == right)
- goto left;
-
- if (left->bit_size > right->bit_size)
- goto left;
-
- if (right->bit_size > left->bit_size)
- goto right;
-
- lmod = left->ctype.modifiers;
- rmod = right->ctype.modifiers;
- if ((lmod ^ rmod) & MOD_UNSIGNED) {
- if (lmod & MOD_UNSIGNED)
- goto left;
- } else if ((lmod & ~rmod) & (MOD_LONG_ALL))
- goto left;
-right:
- left = right;
-left:
- return left;
-}
-
-static int same_cast_type(struct dmr_C *C, struct symbol *orig, struct symbol *news)
-{
- (void)C;
- return orig->bit_size == news->bit_size &&
- orig->bit_offset == news->bit_offset;
-}
-
-static struct symbol *base_type(struct symbol *node, unsigned long *modp, unsigned long *asp)
-{
- unsigned long mod, as;
-
- mod = 0; as = 0;
- while (node) {
- mod |= node->ctype.modifiers;
- as |= node->ctype.as;
- if (node->type == SYM_NODE) {
- node = node->ctype.base_type;
- continue;
- }
- break;
- }
- *modp = mod & ~MOD_IGNORE;
- *asp = as;
- return node;
-}
-
-static int is_same_type(struct dmr_C *C, struct expression *expr, struct symbol *news)
-{
- struct symbol *old = expr->ctype;
- unsigned long oldmod, newmod, oldas, newas;
-
- old = base_type(old, &oldmod, &oldas);
- news = base_type(news, &newmod, &newas);
-
- /* Same base type, same address space? */
- if (old == news && oldas == newas) {
- unsigned long difmod;
-
- /* Check the modifier bits. */
- difmod = (oldmod ^ newmod) & ~MOD_NOCAST;
-
- /* Exact same type? */
- if (!difmod)
- return 1;
-
- /*
- * Not the same type, but differs only in "const".
- * Don't warn about MOD_NOCAST.
- */
- if (difmod == MOD_CONST)
- return 0;
- }
- if ((oldmod | newmod) & MOD_NOCAST) {
- const char *tofrom = "to/from";
- if (!(newmod & MOD_NOCAST))
- tofrom = "from";
- if (!(oldmod & MOD_NOCAST))
- tofrom = "to";
- dmrC_warning(C, expr->pos, "implicit cast %s nocast type", tofrom);
- }
- return 0;
-}
-
-static void
-warn_for_different_enum_types (struct dmr_C *C, struct position pos,
- struct symbol *typea,
- struct symbol *typeb)
-{
- if (!C->Wenum_mismatch)
- return;
- if (typea->type == SYM_NODE)
- typea = typea->ctype.base_type;
- if (typeb->type == SYM_NODE)
- typeb = typeb->ctype.base_type;
-
- if (typea == typeb)
- return;
-
- if (typea->type == SYM_ENUM && typeb->type == SYM_ENUM) {
- dmrC_warning(C, pos, "mixing different enum types");
- dmrC_info(C, pos, " %s versus", dmrC_show_typename(C, typea));
- dmrC_info(C, pos, " %s", dmrC_show_typename(C, typeb));
- }
-}
-
-/*
- * This gets called for implicit casts in assignments and
- * integer promotion. We often want to try to move the
- * cast down, because the ops involved may have been
- * implicitly cast up, and we can get rid of the casts
- * early.
- */
-static struct expression * cast_to(struct dmr_C *C, struct expression *old, struct symbol *type)
-{
- struct expression *expr;
-
- warn_for_different_enum_types (C, old->pos, old->ctype, type);
-
- if (old->ctype != &C->S->null_ctype && is_same_type(C, old, type))
- return old;
-
- /*
- * See if we can simplify the op. Move the cast down.
- */
- switch (old->type) {
- case EXPR_PREOP:
- if (old->ctype->bit_size < type->bit_size)
- break;
- if (old->op == '~') {
- old->ctype = type;
- old->unop = cast_to(C, old->unop, type);
- return old;
- }
- break;
-
- case EXPR_IMPLIED_CAST:
- warn_for_different_enum_types(C, old->pos, old->ctype, type);
-
- if (old->ctype->bit_size >= type->bit_size) {
- struct expression *orig = old->cast_expression;
- if (same_cast_type(C, orig->ctype, type))
- return orig;
- if (old->ctype->bit_offset == type->bit_offset) {
- old->ctype = type;
- old->cast_type = type;
- return old;
- }
- }
- break;
-
- default:
- /* nothing */;
- }
-
- expr = dmrC_alloc_expression(C, old->pos, EXPR_IMPLIED_CAST);
- expr->flags = old->flags;
- expr->ctype = type;
- expr->cast_type = type;
- expr->cast_expression = old;
-
- if (dmrC_is_bool_type(C->S, type))
- cast_to_bool(C, expr);
-
- return expr;
-}
-
-enum {
- TYPE_NUM = 1,
- TYPE_BITFIELD = 2,
- TYPE_RESTRICT = 4,
- TYPE_FLOAT = 8,
- TYPE_PTR = 16,
- TYPE_COMPOUND = 32,
- TYPE_FOULED = 64,
- TYPE_FN = 128,
-};
-
-static inline int classify_type(struct dmr_C *C, struct symbol *type, struct symbol **base)
-{
- static int type_class[SYM_BAD + 1] = {
- [SYM_PTR] = TYPE_PTR,
- [SYM_FN] = TYPE_PTR | TYPE_FN,
- [SYM_ARRAY] = TYPE_PTR | TYPE_COMPOUND,
- [SYM_STRUCT] = TYPE_COMPOUND,
- [SYM_UNION] = TYPE_COMPOUND,
- [SYM_BITFIELD] = TYPE_NUM | TYPE_BITFIELD,
- [SYM_RESTRICT] = TYPE_NUM | TYPE_RESTRICT,
- [SYM_FOULED] = TYPE_NUM | TYPE_RESTRICT | TYPE_FOULED,
- };
- if (type->type == SYM_NODE)
- type = type->ctype.base_type;
- if (type->type == SYM_TYPEOF) {
- type = dmrC_evaluate_expression(C, type->initializer);
- if (!type)
- type = &C->S->bad_ctype;
- else if (type->type == SYM_NODE)
- type = type->ctype.base_type;
- }
- if (type->type == SYM_ENUM)
- type = type->ctype.base_type;
- *base = type;
- if (type->type == SYM_BASETYPE) {
- if (type->ctype.base_type == &C->S->int_type)
- return TYPE_NUM;
- if (type->ctype.base_type == &C->S->fp_type)
- return TYPE_NUM | TYPE_FLOAT;
- }
- return type_class[type->type];
-}
-
-#define is_int(klass) ((klass & (TYPE_NUM | TYPE_FLOAT)) == TYPE_NUM)
-
-static inline int is_string_type(struct dmr_C *C, struct symbol *type)
-{
- if (type->type == SYM_NODE)
- type = type->ctype.base_type;
- return type->type == SYM_ARRAY && dmrC_is_byte_type(C->target, type->ctype.base_type);
-}
-
-static struct symbol *bad_expr_type(struct dmr_C *C, struct expression *expr)
-{
- dmrC_sparse_error(C, expr->pos, "incompatible types for operation (%s)", dmrC_show_special(C, expr->op));
- switch (expr->type) {
- case EXPR_BINOP:
- case EXPR_COMPARE:
- dmrC_info(C, expr->pos, " left side has type %s", dmrC_show_typename(C, expr->left->ctype));
- dmrC_info(C, expr->pos, " right side has type %s", dmrC_show_typename(C, expr->right->ctype));
- break;
- case EXPR_PREOP:
- case EXPR_POSTOP:
- dmrC_info(C, expr->pos, " argument has type %s", dmrC_show_typename(C, expr->unop->ctype));
- break;
- default:
- break;
- }
-
- expr->flags = 0;
- return expr->ctype = &C->S->bad_ctype;
-}
-
-static int restricted_value(struct expression *v, struct symbol *type)
-{
- (void)type;
- if (v->type != EXPR_VALUE)
- return 1;
- if (v->value != 0)
- return 1;
- return 0;
-}
-
-static int restricted_binop(int op)
-{
- switch (op) {
- case '&':
- case '=':
- case SPECIAL_AND_ASSIGN:
- case SPECIAL_OR_ASSIGN:
- case SPECIAL_XOR_ASSIGN:
- return 1; /* unfoul */
- case '|':
- case '^':
- case '?':
- return 2; /* keep fouled */
- case SPECIAL_EQUAL:
- case SPECIAL_NOTEQUAL:
- return 3; /* warn if fouled */
- default:
- return 0; /* warn */
- }
-}
-
-static int restricted_unop(struct dmr_C *C, int op, struct symbol **type)
-{
- if (op == '~') {
- if ((*type)->bit_size < C->target->bits_in_int)
- *type = dmrC_befoul(C->S, *type);
- return 0;
- } if (op == '+')
- return 0;
- return 1;
-}
-
-/* type should be SYM_FOULED */
-static inline struct symbol *unfoul(struct symbol *type)
-{
- return type->ctype.base_type;
-}
-
-static struct symbol *restricted_binop_type(struct dmr_C *C, int op,
- struct expression *left,
- struct expression *right,
- int lclass, int rclass,
- struct symbol *ltype,
- struct symbol *rtype)
-{
- (void) C;
- struct symbol *ctype = NULL;
- if (lclass & TYPE_RESTRICT) {
- if (rclass & TYPE_RESTRICT) {
- if (ltype == rtype) {
- ctype = ltype;
- } else if (lclass & TYPE_FOULED) {
- if (unfoul(ltype) == rtype)
- ctype = ltype;
- } else if (rclass & TYPE_FOULED) {
- if (unfoul(rtype) == ltype)
- ctype = rtype;
- }
- } else {
- if (!restricted_value(right, ltype))
- ctype = ltype;
- }
- } else if (!restricted_value(left, rtype))
- ctype = rtype;
-
- if (ctype) {
- switch (restricted_binop(op)) {
- case 1:
- if ((lclass ^ rclass) & TYPE_FOULED)
- ctype = unfoul(ctype);
- break;
- case 3:
- if (!(lclass & rclass & TYPE_FOULED))
- break;
- case 0:
- ctype = NULL;
- default:
- break;
- }
- }
-
- return ctype;
-}
-
-static inline void unrestrict(struct dmr_C *C, struct expression *expr,
- int klass, struct symbol **ctype)
-{
- if (klass & TYPE_RESTRICT) {
- if (klass & TYPE_FOULED)
- *ctype = unfoul(*ctype);
- dmrC_warning(C, expr->pos, "%s degrades to integer",
- dmrC_show_typename(C, *ctype));
- *ctype = (*ctype)->ctype.base_type; /* get to arithmetic type */
- }
-}
-
-static struct symbol *usual_conversions(struct dmr_C *C, int op,
- struct expression *left,
- struct expression *right,
- int lclass, int rclass,
- struct symbol *ltype,
- struct symbol *rtype)
-{
- struct symbol *ctype;
-
- warn_for_different_enum_types(C, right->pos, left->ctype, right->ctype);
-
- if ((lclass | rclass) & TYPE_RESTRICT)
- goto Restr;
-
-Normal:
- if (!(lclass & TYPE_FLOAT)) {
- if (!(rclass & TYPE_FLOAT))
- return bigger_int_type(C, ltype, rtype);
- else
- return rtype;
- } else if (rclass & TYPE_FLOAT) {
- unsigned long lmod = ltype->ctype.modifiers;
- unsigned long rmod = rtype->ctype.modifiers;
- if (rmod & ~lmod & (MOD_LONG_ALL))
- return rtype;
- else
- return ltype;
- } else
- return ltype;
-
-Restr:
- ctype = restricted_binop_type(C, op, left, right,
- lclass, rclass, ltype, rtype);
- if (ctype)
- return ctype;
-
- unrestrict(C, left, lclass, <ype);
- unrestrict(C, right, rclass, &rtype);
-
- goto Normal;
-}
-
-static inline int lvalue_expression(struct dmr_C *C, struct expression *expr)
-{
- (void) C;
- return expr->type == EXPR_PREOP && expr->op == '*';
-}
-
-static struct symbol *evaluate_ptr_add(struct dmr_C *C, struct expression *expr, struct symbol *itype)
-{
- struct expression *index = expr->right;
- struct symbol *ctype, *base;
- int multiply;
-
- classify_type(C, degenerate(C, expr->left), &ctype);
- base = dmrC_examine_pointer_target(C->S, ctype);
-
- if (!base) {
- dmrC_expression_error(C, expr, "missing type information");
- return NULL;
- }
- if (dmrC_is_function(base)) {
- dmrC_expression_error(C, expr, "arithmetics on pointers to functions");
- return NULL;
- }
-
- /* Get the size of whatever the pointer points to */
- multiply = dmrC_is_void_type(C->S, base) ? 1 : dmrC_bits_to_bytes(C->target, base->bit_size);
-
- if (ctype == &C->S->null_ctype)
- ctype = &C->S->ptr_ctype;
- expr->ctype = ctype;
-
- if (multiply == 1 && itype->bit_size >= C->target->bits_in_pointer)
- return ctype;
-
- if (index->type == EXPR_VALUE) {
- struct expression *val = dmrC_alloc_expression(C, expr->pos, EXPR_VALUE);
- unsigned long long v = index->value, mask;
- mask = 1ULL << (itype->bit_size - 1);
- if (v & mask)
- v |= -mask;
- else
- v &= mask - 1;
- v *= multiply;
- mask = 1ULL << (C->target->bits_in_pointer - 1);
- v &= mask | (mask - 1);
- val->value = v;
- val->ctype = C->target->ssize_t_ctype;
- expr->right = val;
- return ctype;
- }
-
- if (itype->bit_size < C->target->bits_in_pointer)
- index = cast_to(C, index, C->target->ssize_t_ctype);
-
- if (multiply > 1) {
- struct expression *val = dmrC_alloc_expression(C, expr->pos, EXPR_VALUE);
- struct expression *mul = dmrC_alloc_expression(C, expr->pos, EXPR_BINOP);
-
- val->ctype = C->target->ssize_t_ctype;
- val->value = multiply;
-
- mul->op = '*';
- mul->ctype = C->target->ssize_t_ctype;
- mul->left = index;
- mul->right = val;
- index = mul;
- }
-
- expr->right = index;
- return ctype;
-}
-
-
-#define MOD_IGN (MOD_VOLATILE | MOD_CONST | MOD_PURE)
-
-const char *dmrC_type_difference(struct dmr_C *C, struct ctype *c1, struct ctype *c2,
- unsigned long mod1, unsigned long mod2)
-{
- unsigned long as1 = c1->as, as2 = c2->as;
- struct symbol *t1 = c1->base_type;
- struct symbol *t2 = c2->base_type;
- int move1 = 1, move2 = 1;
- mod1 |= c1->modifiers;
- mod2 |= c2->modifiers;
- for (;;) {
- unsigned long diff;
- int type;
- struct symbol *base1 = t1->ctype.base_type;
- struct symbol *base2 = t2->ctype.base_type;
-
- /*
- * FIXME! Collect alignment and context too here!
- */
- if (move1) {
- if (t1 && t1->type != SYM_PTR) {
- mod1 |= t1->ctype.modifiers;
- as1 |= t1->ctype.as;
- }
- move1 = 0;
- }
-
- if (move2) {
- if (t2 && t2->type != SYM_PTR) {
- mod2 |= t2->ctype.modifiers;
- as2 |= t2->ctype.as;
- }
- move2 = 0;
- }
-
- if (t1 == t2)
- break;
- if (!t1 || !t2)
- return "different types";
-
- if (t1->type == SYM_NODE || t1->type == SYM_ENUM) {
- t1 = base1;
- move1 = 1;
- if (!t1)
- return "bad types";
- continue;
- }
-
- if (t2->type == SYM_NODE || t2->type == SYM_ENUM) {
- t2 = base2;
- move2 = 1;
- if (!t2)
- return "bad types";
- continue;
- }
-
- move1 = move2 = 1;
- type = t1->type;
- if (type != t2->type)
- return "different base types";
-
- switch (type) {
- default:
- dmrC_sparse_error(C, t1->pos,
- "internal error: bad type in derived(%d)",
- type);
- return "bad types";
- case SYM_RESTRICT:
- return "different base types";
- case SYM_UNION:
- case SYM_STRUCT:
- /* allow definition of incomplete structs and unions */
- if (t1->ident == t2->ident)
- return NULL;
- return "different base types";
- case SYM_ARRAY:
- /* XXX: we ought to compare sizes */
- break;
- case SYM_PTR:
- if (as1 != as2)
- return "different address spaces";
- /* MOD_SPECIFIER is due to idiocy in parse.c */
- if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SPECIFIER)
- return "different modifiers";
- /* we could be lazier here */
- base1 = dmrC_examine_pointer_target(C->S, t1);
- base2 = dmrC_examine_pointer_target(C->S, t2);
- mod1 = t1->ctype.modifiers;
- as1 = t1->ctype.as;
- mod2 = t2->ctype.modifiers;
- as2 = t2->ctype.as;
- break;
- case SYM_FN: {
- struct symbol *arg1, *arg2;
- int i;
-
- if (as1 != as2)
- return "different address spaces";
- if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SIGNEDNESS)
- return "different modifiers";
- mod1 = t1->ctype.modifiers;
- as1 = t1->ctype.as;
- mod2 = t2->ctype.modifiers;
- as2 = t2->ctype.as;
-
- if (t1->variadic != t2->variadic)
- return "incompatible variadic arguments";
- examine_fn_arguments(C, t1);
- examine_fn_arguments(C, t2);
- PREPARE_PTR_LIST(t1->arguments, arg1);
- PREPARE_PTR_LIST(t2->arguments, arg2);
- i = 1;
- for (;;) {
- const char *diffstr;
- if (!arg1 && !arg2)
- break;
- if (!arg1 || !arg2)
- return "different argument counts";
- diffstr = dmrC_type_difference(C, &arg1->ctype,
- &arg2->ctype,
- MOD_IGN, MOD_IGN);
- if (diffstr) {
- ////// FIXME
- static char argdiff[80];
- sprintf(argdiff, "incompatible argument %d (%s)", i, diffstr);
- return argdiff;
- }
- NEXT_PTR_LIST(arg1);
- NEXT_PTR_LIST(arg2);
- i++;
- }
- FINISH_PTR_LIST(arg2);
- FINISH_PTR_LIST(arg1);
- break;
- }
- case SYM_BASETYPE:
- if (as1 != as2)
- return "different address spaces";
- if (base1 != base2)
- return "different base types";
- diff = (mod1 ^ mod2) & ~MOD_IGNORE;
- if (!diff)
- return NULL;
- if (diff & MOD_SIZE)
- return "different type sizes";
- else if (diff & ~MOD_SIGNEDNESS)
- return "different modifiers";
- else
- return "different signedness";
- }
- t1 = base1;
- t2 = base2;
- }
- if (as1 != as2)
- return "different address spaces";
- if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SIGNEDNESS)
- return "different modifiers";
- return NULL;
-}
-
-static void bad_null(struct dmr_C *C, struct expression *expr)
-{
- if (C->Wnon_pointer_null)
- dmrC_warning(C, expr->pos, "Using plain integer as NULL pointer");
-}
-
-static unsigned long target_qualifiers(struct dmr_C *C, struct symbol *type)
-{
- (void) C;
- unsigned long mod = type->ctype.modifiers & MOD_IGN;
- if (type->ctype.base_type && type->ctype.base_type->type == SYM_ARRAY)
- mod = 0;
- return mod;
-}
-
-static struct symbol *evaluate_ptr_sub(struct dmr_C *C, struct expression *expr)
-{
- const char *typediff;
- struct symbol *ltype, *rtype;
- struct expression *l = expr->left;
- struct expression *r = expr->right;
- struct symbol *lbase;
-
- classify_type(C, degenerate(C, l), <ype);
- classify_type(C, degenerate(C, r), &rtype);
-
- lbase = dmrC_examine_pointer_target(C->S, ltype);
- dmrC_examine_pointer_target(C->S, rtype);
- typediff = dmrC_type_difference(C, <ype->ctype, &rtype->ctype,
- target_qualifiers(C, rtype),
- target_qualifiers(C, ltype));
- if (typediff)
- dmrC_expression_error(C, expr, "subtraction of different types can't work (%s)", typediff);
-
- if (dmrC_is_function(lbase)) {
- dmrC_expression_error(C, expr, "subtraction of functions? Share your drugs");
- return NULL;
- }
-
- expr->ctype = C->target->ssize_t_ctype;
- if (lbase->bit_size > C->target->bits_in_char) {
- struct expression *sub = dmrC_alloc_expression(C, expr->pos, EXPR_BINOP);
- struct expression *div = expr;
- struct expression *val = dmrC_alloc_expression(C, expr->pos, EXPR_VALUE);
- unsigned long value = dmrC_bits_to_bytes(C->target, lbase->bit_size);
-
- val->ctype = C->target->size_t_ctype;
- val->value = value;
-
- if (value & (value-1)) {
- if (C->Wptr_subtraction_blows)
- dmrC_warning(C, expr->pos, "potentially expensive pointer subtraction");
- }
-
- sub->op = '-';
- sub->ctype = C->target->ssize_t_ctype;
- sub->left = l;
- sub->right = r;
-
- div->op = '/';
- div->left = sub;
- div->right = val;
- }
-
- return C->target->ssize_t_ctype;
-}
-
-#define is_safe_type(type) ((type)->ctype.modifiers & MOD_SAFE)
-
-static struct symbol *evaluate_conditional(struct dmr_C *C, struct expression *expr, int iterator)
-{
- struct symbol *ctype;
-
- if (!expr)
- return NULL;
-
- if (!iterator && expr->type == EXPR_ASSIGNMENT && expr->op == '=')
- dmrC_warning(C, expr->pos, "assignment expression in conditional");
-
- ctype = dmrC_evaluate_expression(C, expr);
- if (ctype) {
- if (is_safe_type(ctype))
- dmrC_warning(C, expr->pos, "testing a 'safe expression'");
- if (dmrC_is_func_type(ctype)) {
- if (C->Waddress)
- dmrC_warning(C, expr->pos, "the address of %s will always evaluate as true", "a function");
- }
- else if (dmrC_is_array_type(ctype)) {
- if (C->Waddress)
- dmrC_warning(C, expr->pos, "the address of %s will always evaluate as true", "an array");
- }
- else if (!dmrC_is_scalar_type(C->S, ctype)) {
- dmrC_sparse_error(C, expr->pos, "incorrect type in conditional");
- dmrC_info(C, expr->pos, " got %s", dmrC_show_typename(C, ctype));
- ctype = NULL;
- }
- }
- ctype = degenerate(C, expr);
-
- return ctype;
-}
-
-static struct symbol *evaluate_logical(struct dmr_C *C, struct expression *expr)
-{
- if (!evaluate_conditional(C, expr->left, 0))
- return NULL;
- if (!evaluate_conditional(C, expr->right, 0))
- return NULL;
-
- /* the result is int [6.5.13(3), 6.5.14(3)] */
- expr->ctype = &C->S->int_ctype;
- if (expr->flags) {
- if (!(expr->left->flags & expr->right->flags & Int_const_expr))
- expr->flags = 0;
- }
- return &C->S->int_ctype;
-}
-
-static struct symbol *evaluate_binop(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *ltype, *rtype, *ctype;
- int lclass = classify_type(C, expr->left->ctype, <ype);
- int rclass = classify_type(C, expr->right->ctype, &rtype);
- int op = expr->op;
-
- if (expr->flags) {
- if (!(expr->left->flags & expr->right->flags & Int_const_expr))
- expr->flags = 0;
- }
-
- /* number op number */
- if (lclass & rclass & TYPE_NUM) {
- if ((lclass | rclass) & TYPE_FLOAT) {
- switch (op) {
- case '+': case '-': case '*': case '/':
- break;
- default:
- return bad_expr_type(C, expr);
- }
- }
-
- if (op == SPECIAL_LEFTSHIFT || op == SPECIAL_RIGHTSHIFT) {
- // shifts do integer promotions, but that's it.
- unrestrict(C, expr->left, lclass, <ype);
- unrestrict(C, expr->right, rclass, &rtype);
- ctype = ltype = integer_promotion(C, ltype);
- rtype = integer_promotion(C, rtype);
- } else {
- // The rest do usual conversions
- const unsigned left_not = expr->left->type == EXPR_PREOP
- && expr->left->op == '!';
- const unsigned right_not = expr->right->type == EXPR_PREOP
- && expr->right->op == '!';
- if ((op == '&' || op == '|') && (left_not || right_not))
- dmrC_warning(C, expr->pos, "dubious: %sx %c %sy",
- left_not ? "!" : "",
- op,
- right_not ? "!" : "");
-
- ltype = usual_conversions(C, op, expr->left, expr->right,
- lclass, rclass, ltype, rtype);
- ctype = rtype = ltype;
- }
-
- expr->left = cast_to(C, expr->left, ltype);
- expr->right = cast_to(C, expr->right, rtype);
- expr->ctype = ctype;
- return ctype;
- }
-
- /* pointer (+|-) integer */
- if (lclass & TYPE_PTR && is_int(rclass) && (op == '+' || op == '-')) {
- unrestrict(C, expr->right, rclass, &rtype);
- return evaluate_ptr_add(C, expr, rtype);
- }
-
- /* integer + pointer */
- if (rclass & TYPE_PTR && is_int(lclass) && op == '+') {
- struct expression *index = expr->left;
- unrestrict(C, index, lclass, <ype);
- expr->left = expr->right;
- expr->right = index;
- return evaluate_ptr_add(C, expr, ltype);
- }
-
- /* pointer - pointer */
- if (lclass & rclass & TYPE_PTR && expr->op == '-')
- return evaluate_ptr_sub(C, expr);
-
- return bad_expr_type(C, expr);
-}
-
-static struct symbol *evaluate_comma(struct dmr_C *C, struct expression *expr)
-{
- expr->ctype = degenerate(C, expr->right);
- if (expr->ctype == &C->S->null_ctype)
- expr->ctype = &C->S->ptr_ctype;
- expr->flags &= expr->left->flags & expr->right->flags;
- return expr->ctype;
-}
-
-static int modify_for_unsigned(struct dmr_C *C, int op)
-{
- (void) C;
- if (op == '<')
- op = SPECIAL_UNSIGNED_LT;
- else if (op == '>')
- op = SPECIAL_UNSIGNED_GT;
- else if (op == SPECIAL_LTE)
- op = SPECIAL_UNSIGNED_LTE;
- else if (op == SPECIAL_GTE)
- op = SPECIAL_UNSIGNED_GTE;
- return op;
-}
-
-static inline int is_null_pointer_constant(struct dmr_C *C, struct expression *e)
-{
- if (e->ctype == &C->S->null_ctype)
- return 1;
- if (!(e->flags & Int_const_expr))
- return 0;
- return dmrC_is_zero_constant(C, e) ? 2 : 0;
-}
-
-static struct symbol *evaluate_compare(struct dmr_C *C, struct expression *expr)
-{
- struct expression *left = expr->left, *right = expr->right;
- struct symbol *ltype, *rtype, *lbase, *rbase;
- int lclass = classify_type(C, degenerate(C, left), <ype);
- int rclass = classify_type(C, degenerate(C, right), &rtype);
- struct symbol *ctype;
- const char *typediff;
-
- if (expr->flags) {
- if (!(expr->left->flags & expr->right->flags & Int_const_expr))
- expr->flags = 0;
- }
-
- /* Type types? */
- if (dmrC_is_type_type(ltype) && dmrC_is_type_type(rtype))
- goto OK;
-
- if (is_safe_type(left->ctype) || is_safe_type(right->ctype))
- dmrC_warning(C, expr->pos, "testing a 'safe expression'");
-
- /* number on number */
- if (lclass & rclass & TYPE_NUM) {
- ctype = usual_conversions(C, expr->op, expr->left, expr->right,
- lclass, rclass, ltype, rtype);
- expr->left = cast_to(C, expr->left, ctype);
- expr->right = cast_to(C, expr->right, ctype);
- if (ctype->ctype.modifiers & MOD_UNSIGNED)
- expr->op = modify_for_unsigned(C, expr->op);
- goto OK;
- }
-
- /* at least one must be a pointer */
- if (!((lclass | rclass) & TYPE_PTR))
- return bad_expr_type(C, expr);
-
- /* equality comparisons can be with null pointer constants */
- if (expr->op == SPECIAL_EQUAL || expr->op == SPECIAL_NOTEQUAL) {
- int is_null1 = is_null_pointer_constant(C, left);
- int is_null2 = is_null_pointer_constant(C, right);
- if (is_null1 == 2)
- bad_null(C, left);
- if (is_null2 == 2)
- bad_null(C, right);
- if (is_null1 && is_null2) {
- int positive = expr->op == SPECIAL_EQUAL;
- expr->type = EXPR_VALUE;
- expr->value = positive;
- goto OK;
- }
- if (is_null1 && (rclass & TYPE_PTR)) {
- left = cast_to(C, left, rtype);
- goto OK;
- }
- if (is_null2 && (lclass & TYPE_PTR)) {
- right = cast_to(C, right, ltype);
- goto OK;
- }
- }
- /* both should be pointers */
- if (!(lclass & rclass & TYPE_PTR))
- return bad_expr_type(C, expr);
- expr->op = modify_for_unsigned(C, expr->op);
-
- lbase = dmrC_examine_pointer_target(C->S, ltype);
- rbase = dmrC_examine_pointer_target(C->S, rtype);
-
- /* they also have special treatment for pointers to void */
- if (expr->op == SPECIAL_EQUAL || expr->op == SPECIAL_NOTEQUAL) {
- if (ltype->ctype.as == rtype->ctype.as) {
- if (lbase == &C->S->void_ctype) {
- right = cast_to(C, right, ltype);
- goto OK;
- }
- if (rbase == &C->S->void_ctype) {
- left = cast_to(C, left, rtype);
- goto OK;
- }
- }
- }
-
- typediff = dmrC_type_difference(C, <ype->ctype, &rtype->ctype,
- target_qualifiers(C, rtype),
- target_qualifiers(C, ltype));
- if (!typediff)
- goto OK;
-
- dmrC_expression_error(C, expr, "incompatible types in comparison expression (%s)", typediff);
- return NULL;
-
-OK:
- /* the result is int [6.5.8(6), 6.5.9(3)]*/
- expr->ctype = &C->S->int_ctype;
- return &C->S->int_ctype;
-}
-
-/*
- * NOTE! The degenerate case of "x ? : y", where we don't
- * have a true case, this will possibly promote "x" to the
- * same type as "y", and thus _change_ the conditional
- * test in the expression. But since promotion is "safe"
- * for testing, that's OK.
- */
-static struct symbol *evaluate_conditional_expression(struct dmr_C *C, struct expression *expr)
-{
- struct expression **truee;
- struct symbol *ctype, *ltype, *rtype, *lbase, *rbase;
- int lclass, rclass;
- const char * typediff;
- int qual;
-
- if (!evaluate_conditional(C, expr->conditional, 0))
- return NULL;
- if (!dmrC_evaluate_expression(C, expr->cond_false))
- return NULL;
-
- ctype = degenerate(C, expr->conditional);
- rtype = degenerate(C, expr->cond_false);
-
- truee = &expr->conditional;
- ltype = ctype;
- if (expr->cond_true) {
- if (!dmrC_evaluate_expression(C, expr->cond_true))
- return NULL;
- ltype = degenerate(C, expr->cond_true);
- truee = &expr->cond_true;
- }
-
- if (expr->flags) {
- int flags = expr->conditional->flags & Int_const_expr;
- flags &= (*truee)->flags & expr->cond_false->flags;
- if (!flags)
- expr->flags = 0;
- }
-
- lclass = classify_type(C, ltype, <ype);
- rclass = classify_type(C, rtype, &rtype);
- if (lclass & rclass & TYPE_NUM) {
- ctype = usual_conversions(C, '?', *truee, expr->cond_false,
- lclass, rclass, ltype, rtype);
- *truee = cast_to(C, *truee, ctype);
- expr->cond_false = cast_to(C, expr->cond_false, ctype);
- goto out;
- }
-
- if ((lclass | rclass) & TYPE_PTR) {
- int is_null1 = is_null_pointer_constant(C, *truee);
- int is_null2 = is_null_pointer_constant(C, expr->cond_false);
-
- if (is_null1 && is_null2) {
- *truee = cast_to(C, *truee, &C->S->ptr_ctype);
- expr->cond_false = cast_to(C, expr->cond_false, &C->S->ptr_ctype);
- ctype = &C->S->ptr_ctype;
- goto out;
- }
- if (is_null1 && (rclass & TYPE_PTR)) {
- if (is_null1 == 2)
- bad_null(C, *truee);
- *truee = cast_to(C, *truee, rtype);
- ctype = rtype;
- goto out;
- }
- if (is_null2 && (lclass & TYPE_PTR)) {
- if (is_null2 == 2)
- bad_null(C, expr->cond_false);
- expr->cond_false = cast_to(C, expr->cond_false, ltype);
- ctype = ltype;
- goto out;
- }
- if (!(lclass & rclass & TYPE_PTR)) {
- typediff = "different types";
- goto Err;
- }
- /* OK, it's pointer on pointer */
- if (ltype->ctype.as != rtype->ctype.as) {
- typediff = "different address spaces";
- goto Err;
- }
-
- /* need to be lazier here */
- lbase = dmrC_examine_pointer_target(C->S, ltype);
- rbase = dmrC_examine_pointer_target(C->S, rtype);
- qual = target_qualifiers(C, ltype) | target_qualifiers(C, rtype);
-
- if (lbase == &C->S->void_ctype) {
- /* XXX: pointers to function should warn here */
- ctype = ltype;
- goto Qual;
-
- }
- if (rbase == &C->S->void_ctype) {
- /* XXX: pointers to function should warn here */
- ctype = rtype;
- goto Qual;
- }
- /* XXX: that should be pointer to composite */
- ctype = ltype;
- typediff = dmrC_type_difference(C, <ype->ctype, &rtype->ctype,
- qual, qual);
- if (!typediff)
- goto Qual;
- goto Err;
- }
-
- /* void on void, struct on same struct, union on same union */
- if (ltype == rtype) {
- ctype = ltype;
- goto out;
- }
- typediff = "different base types";
-
-Err:
- dmrC_expression_error(C, expr, "incompatible types in conditional expression (%s)", typediff);
- /*
- * if the condition is constant, the type is in fact known
- * so use it, as gcc & clang do.
- */
- switch (dmrC_expr_truth_value(C, expr->conditional)) {
- case 1: expr->ctype = ltype;
- break;
- case 0: expr->ctype = rtype;
- break;
- default:
- break;
- }
- return NULL;
-
-out:
- expr->ctype = ctype;
- return ctype;
-
-Qual:
- if (qual & ~ctype->ctype.modifiers) {
- struct symbol *sym = dmrC_alloc_symbol(C->S, ctype->pos, SYM_PTR);
- *sym = *ctype;
- sym->ctype.modifiers |= qual;
- ctype = sym;
- }
- *truee = cast_to(C, *truee, ctype);
- expr->cond_false = cast_to(C, expr->cond_false, ctype);
- goto out;
-}
-
-/* FP assignments can not do modulo or bit operations */
-static int compatible_float_op(int op)
-{
- return op == SPECIAL_ADD_ASSIGN ||
- op == SPECIAL_SUB_ASSIGN ||
- op == SPECIAL_MUL_ASSIGN ||
- op == SPECIAL_DIV_ASSIGN;
-}
-
-static int evaluate_assign_op(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *target = expr->left->ctype;
- struct symbol *source = expr->right->ctype;
- struct symbol *t, *s;
- int tclass = classify_type(C, target, &t);
- int sclass = classify_type(C, source, &s);
- int op = expr->op;
-
- if (tclass & sclass & TYPE_NUM) {
- if (tclass & TYPE_FLOAT && !compatible_float_op(op)) {
- dmrC_expression_error(C, expr, "invalid assignment");
- return 0;
- }
- if (tclass & TYPE_RESTRICT) {
- if (!restricted_binop(op)) {
- dmrC_warning(C, expr->pos, "bad assignment (%s) to %s",
- dmrC_show_special(C, op), dmrC_show_typename(C, t));
- expr->right = cast_to(C, expr->right, target);
- return 0;
- }
- /* allowed assignments unfoul */
- if (sclass & TYPE_FOULED && unfoul(s) == t)
- goto Cast;
- if (!restricted_value(expr->right, t))
- return 1;
- } else if (!(sclass & TYPE_RESTRICT))
- goto usual;
- /* source and target would better be identical restricted */
- if (t == s)
- return 1;
- dmrC_warning(C, expr->pos, "invalid assignment: %s", dmrC_show_special(C, op));
- dmrC_info(C, expr->pos, " left side has type %s", dmrC_show_typename(C, t));
- dmrC_info(C, expr->pos, " right side has type %s", dmrC_show_typename(C, s));
- expr->right = cast_to(C, expr->right, target);
- return 0;
- }
- if (tclass == TYPE_PTR && is_int(sclass)) {
- if (op == SPECIAL_ADD_ASSIGN || op == SPECIAL_SUB_ASSIGN) {
- unrestrict(C, expr->right, sclass, &s);
- evaluate_ptr_add(C, expr, s);
- return 1;
- }
- dmrC_expression_error(C, expr, "invalid pointer assignment");
- return 0;
- }
-
- dmrC_expression_error(C, expr, "invalid assignment");
- return 0;
-
-usual:
- target = usual_conversions(C, op, expr->left, expr->right,
- tclass, sclass, target, source);
-Cast:
- expr->right = cast_to(C, expr->right, target);
- return 1;
-}
-
-static int whitelist_pointers(struct dmr_C *C, struct symbol *t1, struct symbol *t2)
-{
- if (t1 == t2)
- return 0; /* yes, 0 - we don't want a cast_to here */
- if (t1 == &C->S->void_ctype)
- return 1;
- if (t2 == &C->S->void_ctype)
- return 1;
- if (classify_type(C, t1, &t1) != TYPE_NUM)
- return 0;
- if (classify_type(C, t2, &t2) != TYPE_NUM)
- return 0;
- if (t1 == t2)
- return 1;
- if (t1->ctype.modifiers & t2->ctype.modifiers & MOD_CHAR)
- return 1;
- if ((t1->ctype.modifiers ^ t2->ctype.modifiers) & MOD_SIZE)
- return 0;
- return !C->Wtypesign;
-}
-
-static int check_assignment_types(struct dmr_C *C, struct symbol *target, struct expression **rp,
- const char **typediff)
-{
- struct symbol *source = degenerate(C, *rp);
- struct symbol *t, *s;
- int tclass = classify_type(C, target, &t);
- int sclass = classify_type(C, source, &s);
-
- if (tclass & sclass & TYPE_NUM) {
- if (tclass & TYPE_RESTRICT) {
- /* allowed assignments unfoul */
- if (sclass & TYPE_FOULED && unfoul(s) == t)
- goto Cast;
- if (!restricted_value(*rp, target))
- return 1;
- if (s == t)
- return 1;
- } else if (!(sclass & TYPE_RESTRICT))
- goto Cast;
- if (t == &C->S->bool_ctype) {
- if (dmrC_is_fouled_type(s))
- dmrC_warning(C, (*rp)->pos, "%s degrades to integer",
- dmrC_show_typename(C, s->ctype.base_type));
- goto Cast;
- }
- *typediff = "different base types";
- return 0;
- }
-
- if (tclass == TYPE_PTR) {
- unsigned long mod1, mod2;
- struct symbol *b1, *b2;
- // NULL pointer is always OK
- int is_null = is_null_pointer_constant(C, *rp);
- if (is_null) {
- if (is_null == 2)
- bad_null(C, *rp);
- goto Cast;
- }
- if (!(sclass & TYPE_PTR)) {
- *typediff = "different base types";
- return 0;
- }
- b1 = dmrC_examine_pointer_target(C->S, t);
- b2 = dmrC_examine_pointer_target(C->S, s);
- mod1 = target_qualifiers(C, t);
- mod2 = target_qualifiers(C, s);
- if (whitelist_pointers(C, b1, b2)) {
- /*
- * assignments to/from void * are OK, provided that
- * we do not remove qualifiers from pointed to [C]
- * or mix address spaces [sparse].
- */
- if (t->ctype.as != s->ctype.as) {
- *typediff = "different address spaces";
- return 0;
- }
- /*
- * If this is a function pointer assignment, it is
- * actually fine to assign a pointer to const data to
- * it, as a function pointer points to const data
- * implicitly, i.e., dereferencing it does not produce
- * an lvalue.
- */
- if (b1->type == SYM_FN)
- mod1 |= MOD_CONST;
- if (mod2 & ~mod1) {
- *typediff = "different modifiers";
- return 0;
- }
- goto Cast;
- }
- /* It's OK if the target is more volatile or const than the source */
- *typediff = dmrC_type_difference(C, &t->ctype, &s->ctype, 0, mod1);
- if (*typediff)
- return 0;
- return 1;
- }
-
- if ((tclass & TYPE_COMPOUND) && s == t)
- return 1;
-
- if (tclass & TYPE_NUM) {
- /* XXX: need to turn into comparison with NULL */
- if (t == &C->S->bool_ctype && (sclass & TYPE_PTR))
- goto Cast;
- *typediff = "different base types";
- return 0;
- }
- *typediff = "invalid types";
- return 0;
-Cast:
- *rp = cast_to(C, *rp, target);
- return 1;
-}
-
-static int compatible_assignment_types(struct dmr_C *C, struct expression *expr, struct symbol *target,
- struct expression **rp, const char *where)
-{
- const char *typediff;
- struct symbol *source = degenerate(C, *rp);
-
- if (!check_assignment_types(C, target, rp, &typediff)) {
- dmrC_warning(C, expr->pos, "incorrect type in %s (%s)", where, typediff);
- dmrC_info(C, expr->pos, " expected %s", dmrC_show_typename(C, target));
- dmrC_info(C, expr->pos, " got %s", dmrC_show_typename(C, source));
- *rp = cast_to(C, *rp, target);
- return 0;
- }
-
- return 1;
-}
-
-static int compatible_transparent_union(struct dmr_C *C, struct symbol *target,
- struct expression **rp)
-{
- struct symbol *t, *member;
- classify_type(C, target, &t);
- if (t->type != SYM_UNION || !t->transparent_union)
- return 0;
-
- FOR_EACH_PTR(t->symbol_list, member) {
- const char *typediff;
- if (check_assignment_types(C, member, rp, &typediff))
- return 1;
- } END_FOR_EACH_PTR(member);
-
- return 0;
-}
-
-static int compatible_argument_type(struct dmr_C *C, struct expression *expr, struct symbol *target,
- struct expression **rp, const char *where)
-{
- if (compatible_transparent_union(C, target, rp))
- return 1;
-
- return compatible_assignment_types(C, expr, target, rp, where);
-}
-static void mark_assigned(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *sym;
-
- if (!expr)
- return;
- switch (expr->type) {
- case EXPR_SYMBOL:
- sym = expr->symbol;
- if (!sym)
- return;
- if (sym->type != SYM_NODE)
- return;
- sym->ctype.modifiers |= MOD_ASSIGNED;
- return;
-
- case EXPR_BINOP:
- mark_assigned(C, expr->left);
- mark_assigned(C, expr->right);
- return;
- case EXPR_CAST:
- case EXPR_FORCE_CAST:
- mark_assigned(C, expr->cast_expression);
- return;
- case EXPR_SLICE:
- mark_assigned(C, expr->base);
- return;
- default:
- /* Hmm? */
- return;
- }
-}
-
-static void evaluate_assign_to(struct dmr_C *C, struct expression *left, struct symbol *type)
-{
- if (type->ctype.modifiers & MOD_CONST)
- dmrC_expression_error(C, left, "assignment to const expression");
-
- /* We know left is an lvalue, so it's a "preop-*" */
- mark_assigned(C, left->unop);
-}
-
-static struct symbol *evaluate_assignment(struct dmr_C *C, struct expression *expr)
-{
- struct expression *left = expr->left;
- struct expression *where = expr;
- struct symbol *ltype;
-
- if (!lvalue_expression(C, left)) {
- dmrC_expression_error(C, expr, "not an lvalue");
- return NULL;
- }
-
- ltype = left->ctype;
-
- if (expr->op != '=') {
- if (!evaluate_assign_op(C, expr))
- return NULL;
- } else {
- if (!compatible_assignment_types(C, where, ltype, &expr->right, "assignment"))
- return NULL;
- }
-
- evaluate_assign_to(C, left, ltype);
-
- expr->ctype = ltype;
- return ltype;
-}
-
-static void examine_fn_arguments(struct dmr_C *C, struct symbol *fn)
-{
- struct symbol *s;
-
- FOR_EACH_PTR(fn->arguments, s) {
- struct symbol *arg = evaluate_symbol(C, s);
- /* Array/function arguments silently degenerate into pointers */
- if (arg) {
- struct symbol *ptr;
- switch(arg->type) {
- case SYM_ARRAY:
- case SYM_FN:
- ptr = dmrC_alloc_symbol(C->S, s->pos, SYM_PTR);
- if (arg->type == SYM_ARRAY)
- ptr->ctype = arg->ctype;
- else
- ptr->ctype.base_type = arg;
- ptr->ctype.as |= s->ctype.as;
- ptr->ctype.modifiers |= s->ctype.modifiers & MOD_PTRINHERIT;
-
- s->ctype.base_type = ptr;
- s->ctype.as = 0;
- s->ctype.modifiers &= ~MOD_PTRINHERIT;
- s->bit_size = 0;
- s->examined = 0;
- dmrC_examine_symbol_type(C->S, s);
- break;
- default:
- /* nothing */
- break;
- }
- }
- } END_FOR_EACH_PTR(s);
-}
-
-static struct symbol *convert_to_as_mod(struct dmr_C *C, struct symbol *sym, int as, int mod)
-{
- /* Take the modifiers of the pointer, and apply them to the member */
- mod |= sym->ctype.modifiers;
- if ((int)(sym->ctype.as) != as || (int)(sym->ctype.modifiers) != mod) {
- struct symbol *newsym = dmrC_alloc_symbol(C->S, sym->pos, SYM_NODE);
- *newsym = *sym;
- newsym->ctype.as = as;
- newsym->ctype.modifiers = mod;
- sym = newsym;
- }
- return sym;
-}
-
-static struct symbol *create_pointer(struct dmr_C *C, struct expression *expr, struct symbol *sym, int degenerate)
-{
- struct symbol *node = dmrC_alloc_symbol(C->S, expr->pos, SYM_NODE);
- struct symbol *ptr = dmrC_alloc_symbol(C->S, expr->pos, SYM_PTR);
-
- node->ctype.base_type = ptr;
- ptr->bit_size = C->target->bits_in_pointer;
- ptr->ctype.alignment = C->target->pointer_alignment;
-
- node->bit_size = C->target->bits_in_pointer;
- node->ctype.alignment = C->target->pointer_alignment;
-
- dmrC_access_symbol(C->S, sym);
- if (sym->ctype.modifiers & MOD_REGISTER) {
- dmrC_warning(C, expr->pos, "taking address of 'register' variable '%s'", dmrC_show_ident(C, sym->ident));
- sym->ctype.modifiers &= ~MOD_REGISTER;
- }
- if (sym->type == SYM_NODE) {
- ptr->ctype.as |= sym->ctype.as;
- ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT;
- sym = sym->ctype.base_type;
- }
- if (degenerate && sym->type == SYM_ARRAY) {
- ptr->ctype.as |= sym->ctype.as;
- ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT;
- sym = sym->ctype.base_type;
- }
- ptr->ctype.base_type = sym;
-
- return node;
-}
-
-/* Arrays degenerate into pointers on pointer arithmetic */
-static struct symbol *degenerate(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *ctype, *base;
-
- if (!expr)
- return NULL;
- ctype = expr->ctype;
- if (!ctype)
- return NULL;
- base = dmrC_examine_symbol_type(C->S, ctype);
- if (ctype->type == SYM_NODE)
- base = ctype->ctype.base_type;
- /*
- * Arrays degenerate into pointers to the entries, while
- * functions degenerate into pointers to themselves.
- * If array was part of non-lvalue compound, we create a copy
- * of that compound first and then act as if we were dealing with
- * the corresponding field in there.
- */
- switch (base->type) {
- case SYM_ARRAY:
- if (expr->type == EXPR_SLICE) {
- struct symbol *a = dmrC_alloc_symbol(C->S, expr->pos, SYM_NODE);
- struct expression *e0, *e1, *e2, *e3, *e4;
-
- a->ctype.base_type = expr->base->ctype;
- a->bit_size = expr->base->ctype->bit_size;
- a->array_size = expr->base->ctype->array_size;
-
- e0 = dmrC_alloc_expression(C, expr->pos, EXPR_SYMBOL);
- e0->symbol = a;
- e0->ctype = &C->S->lazy_ptr_ctype;
-
- e1 = dmrC_alloc_expression(C, expr->pos, EXPR_PREOP);
- e1->unop = e0;
- e1->op = '*';
- e1->ctype = expr->base->ctype; /* XXX */
-
- e2 = dmrC_alloc_expression(C, expr->pos, EXPR_ASSIGNMENT);
- e2->left = e1;
- e2->right = expr->base;
- e2->op = '=';
- e2->ctype = expr->base->ctype;
-
- if (expr->r_bitpos) {
- e3 = dmrC_alloc_expression(C, expr->pos, EXPR_BINOP);
- e3->op = '+';
- e3->left = e0;
- e3->right = dmrC_alloc_const_expression(C, expr->pos,
- dmrC_bits_to_bytes(C->target, expr->r_bitpos));
- e3->ctype = &C->S->lazy_ptr_ctype;
- } else {
- e3 = e0;
- }
-
- e4 = dmrC_alloc_expression(C, expr->pos, EXPR_COMMA);
- e4->left = e2;
- e4->right = e3;
- e4->ctype = &C->S->lazy_ptr_ctype;
-
- expr->unop = e4;
- expr->type = EXPR_PREOP;
- expr->op = '*';
- }
- case SYM_FN:
- if (expr->op != '*' || expr->type != EXPR_PREOP) {
- dmrC_expression_error(C, expr, "strange non-value function or array");
- return &C->S->bad_ctype;
- }
- *expr = *expr->unop;
- ctype = create_pointer(C, expr, ctype, 1);
- expr->ctype = ctype;
- default:
- /* nothing */;
- }
- return ctype;
-}
-
-static struct symbol *evaluate_addressof(struct dmr_C *C, struct expression *expr)
-{
- struct expression *op = expr->unop;
- struct symbol *ctype;
-
- if (op->op != '*' || op->type != EXPR_PREOP) {
- dmrC_expression_error(C, expr, "not addressable");
- return NULL;
- }
- ctype = op->ctype;
- *expr = *op->unop;
- expr->flags = 0;
-
- if (expr->type == EXPR_SYMBOL) {
- struct symbol *sym = expr->symbol;
- sym->ctype.modifiers |= MOD_ADDRESSABLE;
- }
-
- /*
- * symbol expression evaluation is lazy about the type
- * of the sub-expression, so we may have to generate
- * the type here if so..
- */
- if (expr->ctype == &C->S->lazy_ptr_ctype) {
- ctype = create_pointer(C, expr, ctype, 0);
- expr->ctype = ctype;
- }
- return expr->ctype;
-}
-
-
-static struct symbol *evaluate_dereference(struct dmr_C *C, struct expression *expr)
-{
- struct expression *op = expr->unop;
- struct symbol *ctype = op->ctype, *node, *target;
-
- /* Simplify: *&(expr) => (expr) */
- if (op->type == EXPR_PREOP && op->op == '&') {
- *expr = *op->unop;
- expr->flags = 0;
- return expr->ctype;
- }
-
- dmrC_examine_symbol_type(C->S, ctype);
-
- /* Dereferencing a node drops all the node information. */
- if (ctype->type == SYM_NODE)
- ctype = ctype->ctype.base_type;
-
- node = dmrC_alloc_symbol(C->S, expr->pos, SYM_NODE);
- target = ctype->ctype.base_type;
-
- switch (ctype->type) {
- default:
- dmrC_expression_error(C, expr, "cannot dereference this type");
- return NULL;
- case SYM_PTR:
- node->ctype.modifiers = target->ctype.modifiers & MOD_SPECIFIER;
- dmrC_merge_type(node, ctype);
- break;
-
- case SYM_ARRAY:
- if (!lvalue_expression(C, op)) {
- dmrC_expression_error(C, op, "non-lvalue array??");
- return NULL;
- }
-
- /* Do the implied "addressof" on the array */
- *op = *op->unop;
-
- /*
- * When an array is dereferenced, we need to pick
- * up the attributes of the original node too..
- */
- dmrC_merge_type(node, op->ctype);
- dmrC_merge_type(node, ctype);
- break;
- }
-
- node->bit_size = target->bit_size;
- node->array_size = target->array_size;
-
- expr->ctype = node;
- return node;
-}
-
-/*
- * Unary post-ops: x++ and x--
- */
-static struct symbol *evaluate_postop(struct dmr_C *C, struct expression *expr)
-{
- struct expression *op = expr->unop;
- struct symbol *ctype = op->ctype;
- int klass = classify_type(C, ctype, &ctype);
- int multiply = 0;
-
- if (!klass || klass & TYPE_COMPOUND) {
- dmrC_expression_error(C, expr, "need scalar for ++/--");
- return NULL;
- }
- if (!lvalue_expression(C, expr->unop)) {
- dmrC_expression_error(C, expr, "need lvalue expression for ++/--");
- return NULL;
- }
-
- if ((klass & TYPE_RESTRICT) && restricted_unop(C, expr->op, &ctype))
- unrestrict(C, expr, klass, &ctype);
-
- if (klass & TYPE_NUM) {
- multiply = 1;
- } else if (klass == TYPE_PTR) {
- struct symbol *target = dmrC_examine_pointer_target(C->S, ctype);
- if (!dmrC_is_function(target))
- multiply = dmrC_bits_to_bytes(C->target, target->bit_size);
- }
-
- if (multiply) {
- evaluate_assign_to(C, op, op->ctype);
- expr->op_value = multiply;
- expr->ctype = ctype;
- return ctype;
- }
-
- dmrC_expression_error(C, expr, "bad argument type for ++/--");
- return NULL;
-}
-
-static struct symbol *evaluate_sign(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *ctype = expr->unop->ctype;
- int klass = classify_type(C, ctype, &ctype);
- if (expr->flags && !(expr->unop->flags & Int_const_expr))
- expr->flags = 0;
- /* should be an arithmetic type */
- if (!(klass & TYPE_NUM))
- return bad_expr_type(C, expr);
- if (klass & TYPE_RESTRICT)
- goto Restr;
-Normal:
- if (!(klass & TYPE_FLOAT)) {
- ctype = integer_promotion(C, ctype);
- expr->unop = cast_to(C, expr->unop, ctype);
- } else if (expr->op != '~') {
- /* no conversions needed */
- } else {
- return bad_expr_type(C, expr);
- }
- if (expr->op == '+')
- *expr = *expr->unop;
- expr->ctype = ctype;
- return ctype;
-Restr:
- if (restricted_unop(C, expr->op, &ctype))
- unrestrict(C, expr, klass, &ctype);
- goto Normal;
-}
-
-static struct symbol *evaluate_preop(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *ctype = expr->unop->ctype;
-
- switch (expr->op) {
- case '(':
- *expr = *expr->unop;
- return ctype;
-
- case '+':
- case '-':
- case '~':
- return evaluate_sign(C, expr);
-
- case '*':
- return evaluate_dereference(C, expr);
-
- case '&':
- return evaluate_addressof(C, expr);
-
- case SPECIAL_INCREMENT:
- case SPECIAL_DECREMENT:
- /*
- * From a type evaluation standpoint the preops are
- * the same as the postops
- */
- return evaluate_postop(C, expr);
-
- case '!':
- if (expr->flags && !(expr->unop->flags & Int_const_expr))
- expr->flags = 0;
- if (is_safe_type(ctype))
- dmrC_warning(C, expr->pos, "testing a 'safe expression'");
- if (dmrC_is_float_type(C->S, ctype)) {
- struct expression *arg = expr->unop;
- expr->type = EXPR_COMPARE;
- expr->op = SPECIAL_EQUAL;
- expr->left = arg;
- expr->right = dmrC_alloc_expression(C, expr->pos, EXPR_FVALUE);
- expr->right->ctype = ctype;
- expr->right->fvalue = 0;
- } else if (dmrC_is_fouled_type(ctype)) {
- dmrC_warning(C, expr->pos, "%s degrades to integer",
- dmrC_show_typename(C, ctype->ctype.base_type));
- }
- /* the result is int [6.5.3.3(5)]*/
- ctype = &C->S->int_ctype;
- break;
-
- default:
- break;
- }
- expr->ctype = ctype;
- return ctype;
-}
-
-static struct symbol *find_identifier(struct dmr_C *C, struct ident *ident, struct symbol_list *_list, int *offset)
-{
- struct ptr_list *head = (struct ptr_list *)_list;
- struct ptr_list *list = head;
-
- if (!head)
- return NULL;
- do {
- int i;
- for (i = 0; i < list->nr_; i++) {
- struct symbol *sym = (struct symbol *) list->list_[i];
- if (sym->ident) {
- if (sym->ident != ident)
- continue;
- *offset = sym->offset;
- return sym;
- } else {
- struct symbol *ctype = sym->ctype.base_type;
- struct symbol *sub;
- if (!ctype)
- continue;
- if (ctype->type != SYM_UNION && ctype->type != SYM_STRUCT)
- continue;
- sub = find_identifier(C, ident, ctype->symbol_list, offset);
- if (!sub)
- continue;
- *offset += sym->offset;
- return sub;
- }
- }
- } while ((list = list->next_) != head);
- return NULL;
-}
-
-static struct expression *evaluate_offset(struct dmr_C *C, struct expression *expr, unsigned long offset)
-{
- struct expression *add;
-
- /*
- * Create a new add-expression
- *
- * NOTE! Even if we just add zero, we need a new node
- * for the member pointer, since it has a different
- * type than the original pointer. We could make that
- * be just a cast, but the fact is, a node is a node,
- * so we might as well just do the "add zero" here.
- */
- add = dmrC_alloc_expression(C, expr->pos, EXPR_BINOP);
- add->op = '+';
- add->left = expr;
- add->right = dmrC_alloc_expression(C, expr->pos, EXPR_VALUE);
- add->right->ctype = &C->S->int_ctype;
- add->right->value = offset;
-
- /*
- * The ctype of the pointer will be lazily evaluated if
- * we ever take the address of this member dereference..
- */
- add->ctype = &C->S->lazy_ptr_ctype;
- return add;
-}
-
-/* structure/union dereference */
-static struct symbol *evaluate_member_dereference(struct dmr_C *C, struct expression *expr)
-{
- int offset;
- struct symbol *ctype, *member;
- struct expression *deref = expr->deref, *add;
- struct ident *ident = expr->member;
- unsigned int mod;
- int address_space;
-
- if (!dmrC_evaluate_expression(C, deref))
- return NULL;
- if (!ident) {
- dmrC_expression_error(C, expr, "bad member name");
- return NULL;
- }
-
- ctype = deref->ctype;
- dmrC_examine_symbol_type(C->S, ctype);
- address_space = ctype->ctype.as;
- mod = ctype->ctype.modifiers;
- if (ctype->type == SYM_NODE) {
- ctype = ctype->ctype.base_type;
- address_space |= ctype->ctype.as;
- mod |= ctype->ctype.modifiers;
- }
- if (!ctype || (ctype->type != SYM_STRUCT && ctype->type != SYM_UNION)) {
- dmrC_expression_error(C, expr, "expected structure or union");
- return NULL;
- }
- offset = 0;
- member = find_identifier(C, ident, ctype->symbol_list, &offset);
- if (!member) {
- const char *type = ctype->type == SYM_STRUCT ? "struct" : "union";
- const char *name = "";
- int namelen = 9;
- if (ctype->ident) {
- name = ctype->ident->name;
- namelen = ctype->ident->len;
- }
- if (ctype->symbol_list)
- dmrC_expression_error(C, expr, "no member '%s' in %s %.*s",
- dmrC_show_ident(C, ident), type, namelen, name);
- else
- dmrC_expression_error(C, expr, "using member '%s' in "
- "incomplete %s %.*s", dmrC_show_ident(C, ident),
- type, namelen, name);
- return NULL;
- }
-
- /*
- * The member needs to take on the address space and modifiers of
- * the "parent" type.
- */
- member = convert_to_as_mod(C, member, address_space, mod);
- ctype = dmrC_get_base_type(C->S, member);
-
- if (!lvalue_expression(C, deref)) {
- if (deref->type != EXPR_SLICE) {
- expr->base = deref;
- expr->r_bitpos = 0;
- } else {
- expr->base = deref->base;
- expr->r_bitpos = deref->r_bitpos;
- }
- expr->r_bitpos += dmrC_bytes_to_bits(C->target, offset);
- expr->type = EXPR_SLICE;
- expr->r_nrbits = member->bit_size;
- expr->r_bitpos += member->bit_offset;
- expr->ctype = member;
- return member;
- }
-
- deref = deref->unop;
- expr->deref = deref;
-
- add = evaluate_offset(C, deref, offset);
- expr->type = EXPR_PREOP;
- expr->op = '*';
- expr->unop = add;
-
- expr->ctype = member;
- return member;
-}
-
-static int is_promoted(struct dmr_C *C, struct expression *expr)
-{
- (void) C;
- while (1) {
- switch (expr->type) {
- case EXPR_BINOP:
- case EXPR_SELECT:
- case EXPR_CONDITIONAL:
- return 1;
- case EXPR_COMMA:
- expr = expr->right;
- continue;
- case EXPR_PREOP:
- switch (expr->op) {
- case '(':
- expr = expr->unop;
- continue;
- case '+':
- case '-':
- case '~':
- return 1;
- default:
- return 0;
- }
- default:
- return 0;
- }
- }
-}
-
-
-static struct symbol *evaluate_cast(struct dmr_C *C, struct expression *);
-
-static struct symbol *evaluate_type_information(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *sym = expr->cast_type;
- if (!sym) {
- sym = dmrC_evaluate_expression(C, expr->cast_expression);
- if (!sym)
- return NULL;
- /*
- * Expressions of restricted types will possibly get
- * promoted - check that here
- */
- if (dmrC_is_restricted_type(sym)) {
- if (sym->bit_size < C->target->bits_in_int && is_promoted(C, expr))
- sym = &C->S->int_ctype;
- } else if (dmrC_is_fouled_type(sym)) {
- sym = &C->S->int_ctype;
- }
- }
- dmrC_examine_symbol_type(C->S, sym);
- if (dmrC_is_bitfield_type(sym)) {
- dmrC_expression_error(C, expr, "trying to examine bitfield type");
- return NULL;
- }
- return sym;
-}
-
-static struct symbol *evaluate_sizeof(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *type;
- int size;
-
- type = evaluate_type_information(C, expr);
- if (!type)
- return NULL;
-
- size = type->bit_size;
-
- if (size < 0 && dmrC_is_void_type(C->S, type)) {
- dmrC_warning(C, expr->pos, "expression using sizeof(void)");
- size = C->target->bits_in_char;
- }
-
- if (size == 1 && dmrC_is_bool_type(C->S, type)) {
- if (C->Wsizeof_bool)
- dmrC_warning(C, expr->pos, "expression using sizeof bool");
- size = C->target->bits_in_char;
- }
-
- if (dmrC_is_function(type->ctype.base_type)) {
- dmrC_warning(C, expr->pos, "expression using sizeof on a function");
- size = C->target->bits_in_char;
- }
-
- if ((size < 0) || (size & (C->target->bits_in_char - 1)))
- dmrC_expression_error(C, expr, "cannot size expression");
-
- expr->type = EXPR_VALUE;
- expr->value = dmrC_bits_to_bytes(C->target, size);
- expr->taint = 0;
- expr->ctype = C->target->size_t_ctype;
- return C->target->size_t_ctype;
-}
-
-static struct symbol *evaluate_ptrsizeof(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *type;
- int size;
-
- type = evaluate_type_information(C, expr);
- if (!type)
- return NULL;
-
- if (type->type == SYM_NODE)
- type = type->ctype.base_type;
- if (!type)
- return NULL;
- switch (type->type) {
- case SYM_ARRAY:
- break;
- case SYM_PTR:
- type = dmrC_get_base_type(C->S, type);
- if (type)
- break;
- default:
- dmrC_expression_error(C, expr, "expected pointer expression");
- return NULL;
- }
- size = type->bit_size;
- if (size & (C->target->bits_in_char-1))
- size = 0;
- expr->type = EXPR_VALUE;
- expr->value = dmrC_bits_to_bytes(C->target, size);
- expr->taint = 0;
- expr->ctype = C->target->size_t_ctype;
- return C->target->size_t_ctype;
-}
-
-static struct symbol *evaluate_alignof(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *type;
-
- type = evaluate_type_information(C, expr);
- if (!type)
- return NULL;
-
- expr->type = EXPR_VALUE;
- expr->value = type->ctype.alignment;
- expr->taint = 0;
- expr->ctype = C->target->size_t_ctype;
- return C->target->size_t_ctype;
-}
-
-static int evaluate_arguments(struct dmr_C *C, struct symbol *fn, struct expression_list *head)
-{
- struct expression *expr;
- struct symbol_list *argument_types = fn->arguments;
- struct symbol *argtype;
- int i = 1;
-
- PREPARE_PTR_LIST(argument_types, argtype);
- FOR_EACH_PTR (head, expr) {
- struct expression **p = THIS_ADDRESS(struct expression*, expr);
- struct symbol *ctype, *target;
- ctype = dmrC_evaluate_expression(C, expr);
-
- if (!ctype)
- return 0;
-
- target = argtype;
- if (!target) {
- struct symbol *type;
- int klass = classify_type(C, ctype, &type);
- if (is_int(klass)) {
- *p = cast_to(C, expr, integer_promotion(C, type));
- } else if (klass & TYPE_FLOAT) {
- unsigned long mod = type->ctype.modifiers;
- if (!(mod & (MOD_LONG_ALL)))
- *p = cast_to(C, expr, &C->S->double_ctype);
- } else if (klass & TYPE_PTR) {
- if (expr->ctype == &C->S->null_ctype)
- *p = cast_to(C, expr, &C->S->ptr_ctype);
- else
- degenerate(C, expr);
- }
- } else if (!target->forced_arg){
- /// FIXME
- static char where[30];
- dmrC_examine_symbol_type(C->S, target);
- sprintf(where, "argument %d", i);
- compatible_argument_type(C, expr, target, p, where);
- }
-
- i++;
- NEXT_PTR_LIST(argtype);
- } END_FOR_EACH_PTR(expr);
- FINISH_PTR_LIST(argtype);
- return 1;
-}
-
-static void convert_index(struct dmr_C *C, struct expression *e)
-{
- struct expression *child = e->idx_expression;
- unsigned from = e->idx_from;
- unsigned to = e->idx_to + 1;
- e->type = EXPR_POS;
- e->init_offset = from * dmrC_bits_to_bytes(C->target, e->ctype->bit_size);
- e->init_nr = to - from;
- e->init_expr = child;
-}
-
-static void convert_ident(struct dmr_C *C, struct expression *e)
-{
- (void) C;
- struct expression *child = e->ident_expression;
- int offset = e->offset;
-
- e->type = EXPR_POS;
- e->init_offset = offset;
- e->init_nr = 1;
- e->init_expr = child;
-}
-
-static void convert_designators(struct dmr_C *C, struct expression *e)
-{
- while (e) {
- if (e->type == EXPR_INDEX)
- convert_index(C, e);
- else if (e->type == EXPR_IDENTIFIER)
- convert_ident(C, e);
- else
- break;
- e = e->init_expr;
- }
-}
-
-static void excess(struct dmr_C *C, struct expression *e, const char *s)
-{
- dmrC_warning(C, e->pos, "excessive elements in %s initializer", s);
-}
-
-/*
- * implicit designator for the first element
- */
-static struct expression *first_subobject(struct dmr_C *C, struct symbol *ctype, int klass,
- struct expression **v)
-{
- struct expression *e = *v, *newe;
-
- if (ctype->type == SYM_NODE)
- ctype = ctype->ctype.base_type;
-
- if (klass & TYPE_PTR) { /* array */
- if (!ctype->bit_size)
- return NULL;
- newe = dmrC_alloc_expression(C, e->pos, EXPR_INDEX);
- newe->idx_expression = e;
- newe->ctype = ctype->ctype.base_type;
- } else {
- struct symbol *field, *p;
- PREPARE_PTR_LIST(ctype->symbol_list, p);
- while (p && !p->ident && dmrC_is_bitfield_type(p))
- NEXT_PTR_LIST(p);
- field = p;
- FINISH_PTR_LIST(p);
- if (!field)
- return NULL;
- newe = dmrC_alloc_expression(C, e->pos, EXPR_IDENTIFIER);
- newe->ident_expression = e;
- newe->field = newe->ctype = field;
- newe->offset = field->offset;
- }
- *v = newe;
- return newe;
-}
-
-/*
- * sanity-check explicit designators; return the innermost one or NULL
- * in case of error. Assign types.
- */
-static struct expression *check_designators(struct dmr_C *C, struct expression *e,
- struct symbol *ctype)
-{
- struct expression *last = NULL;
- const char *err;
- while (1) {
- if (ctype->type == SYM_NODE)
- ctype = ctype->ctype.base_type;
- if (e->type == EXPR_INDEX) {
- struct symbol *type;
- if (ctype->type != SYM_ARRAY) {
- err = "array index in non-array";
- break;
- }
- type = ctype->ctype.base_type;
- if (ctype->bit_size >= 0 && type->bit_size >= 0) {
- unsigned offset = (unsigned) dmrC_array_element_offset(C->target, type->bit_size, e->idx_to);
- if (offset >= (unsigned) (ctype->bit_size)) {
- err = "index out of bounds in";
- break;
- }
- }
- e->ctype = ctype = type;
- ctype = type;
- last = e;
- if (!e->idx_expression) {
- err = "invalid";
- break;
- }
- e = e->idx_expression;
- } else if (e->type == EXPR_IDENTIFIER) {
- int offset = 0;
- if (ctype->type != SYM_STRUCT && ctype->type != SYM_UNION) {
- err = "field name not in struct or union";
- break;
- }
- ctype = find_identifier(C, e->expr_ident, ctype->symbol_list, &offset);
- if (!ctype) {
- err = "unknown field name in";
- break;
- }
- e->offset = offset;
- e->field = e->ctype = ctype;
- last = e;
- if (!e->ident_expression) {
- err = "invalid";
- break;
- }
- e = e->ident_expression;
- } else if (e->type == EXPR_POS) {
- err = "internal front-end error: EXPR_POS in";
- break;
- } else
- return last;
- }
- dmrC_expression_error(C, e, "%s initializer", err);
- return NULL;
-}
-
-/*
- * choose the next subobject to initialize.
- *
- * Get designators for next element, switch old ones to EXPR_POS.
- * Return the resulting expression or NULL if we'd run out of subobjects.
- * The innermost designator is returned in *v. Designators in old
- * are assumed to be already sanity-checked.
- */
-static struct expression *next_designators(struct dmr_C *C, struct expression *old,
- struct symbol *ctype,
- struct expression *e, struct expression **v)
-{
- struct expression *newe = NULL;
-
- if (!old)
- return NULL;
- if (old->type == EXPR_INDEX) {
- struct expression *copy;
- unsigned n;
-
- copy = next_designators(C, old->idx_expression,
- old->ctype, e, v);
- if (!copy) {
- n = old->idx_to + 1;
- if ((int)dmrC_array_element_offset(C->target, old->ctype->bit_size, n) == ctype->bit_size) {
- convert_index(C, old);
- return NULL;
- }
- copy = e;
- *v = newe = dmrC_alloc_expression(C, e->pos, EXPR_INDEX);
- } else {
- n = old->idx_to;
- newe = dmrC_alloc_expression(C, e->pos, EXPR_INDEX);
- }
-
- newe->idx_from = newe->idx_to = n;
- newe->idx_expression = copy;
- newe->ctype = old->ctype;
- convert_index(C, old);
- } else if (old->type == EXPR_IDENTIFIER) {
- struct expression *copy;
- struct symbol *field;
- int offset = 0;
-
- copy = next_designators(C, old->ident_expression,
- old->ctype, e, v);
- if (!copy) {
- field = old->field->next_subobject;
- if (!field) {
- convert_ident(C, old);
- return NULL;
- }
- copy = e;
- *v = newe = dmrC_alloc_expression(C, e->pos, EXPR_IDENTIFIER);
- /*
- * We can't necessarily trust "field->offset",
- * because the field might be in an anonymous
- * union, and the field offset is then the offset
- * within that union.
- *
- * The "old->offset - old->field->offset"
- * would be the offset of such an anonymous
- * union.
- */
- offset = old->offset - old->field->offset;
- } else {
- field = old->field;
- newe = dmrC_alloc_expression(C, e->pos, EXPR_IDENTIFIER);
- }
-
- newe->field = field;
- newe->expr_ident = field->ident;
- newe->ident_expression = copy;
- newe->ctype = field;
- newe->offset = field->offset + offset;
- convert_ident(C, old);
- }
- return newe;
-}
-
-static int handle_simple_initializer(struct dmr_C *C, struct expression **ep, int nested,
- int klass, struct symbol *ctype);
-
-/*
- * deal with traversing subobjects [6.7.8(17,18,20)]
- */
-static void handle_list_initializer(struct dmr_C *C, struct expression *expr,
- int klass, struct symbol *ctype)
-{
- struct expression *e, *last = NULL, *top = NULL, *next;
- int jumped = 0;
-
- FOR_EACH_PTR(expr->expr_list, e) {
- struct expression **v;
- struct symbol *type;
- int lclass;
-
- if (e->type != EXPR_INDEX && e->type != EXPR_IDENTIFIER) {
- struct symbol *struct_sym;
- if (!top) {
- top = e;
- last = first_subobject(C, ctype, klass, &top);
- } else {
- last = next_designators(C, last, ctype, e, &top);
- }
- if (!last) {
- excess(C, e, klass & TYPE_PTR ? "array" :
- "struct or union");
- DELETE_CURRENT_PTR(e);
- continue;
- }
- struct_sym = ctype->type == SYM_NODE ? ctype->ctype.base_type : ctype;
- if (C->Wdesignated_init && struct_sym->designated_init)
- dmrC_warning(C, e->pos, "%s%.*s%spositional init of field in %s %s, declared with attribute designated_init",
- ctype->ident ? "in initializer for " : "",
- ctype->ident ? ctype->ident->len : 0,
- ctype->ident ? ctype->ident->name : "",
- ctype->ident ? ": " : "",
- dmrC_get_type_name(struct_sym->type),
- dmrC_show_ident(C, struct_sym->ident));
- if (jumped) {
- dmrC_warning(C, e->pos, "advancing past deep designator");
- jumped = 0;
- }
- REPLACE_CURRENT_PTR(struct expression *, e, last);
- } else {
- next = check_designators(C, e, ctype);
- if (!next) {
- DELETE_CURRENT_PTR(e);
- continue;
- }
- top = next;
- /* deeper than one designator? */
- jumped = top != e;
- convert_designators(C, last);
- last = e;
- }
-
-found:
- lclass = classify_type(C, top->ctype, &type);
- if (top->type == EXPR_INDEX)
- v = &top->idx_expression;
- else
- v = &top->ident_expression;
-
- if (handle_simple_initializer(C, v, 1, lclass, top->ctype))
- continue;
-
- if (!(lclass & TYPE_COMPOUND)) {
- dmrC_warning(C, e->pos, "bogus scalar initializer");
- DELETE_CURRENT_PTR(e);
- continue;
- }
-
- next = first_subobject(C, type, lclass, v);
- if (next) {
- dmrC_warning(C, e->pos, "missing braces around initializer");
- top = next;
- goto found;
- }
-
- DELETE_CURRENT_PTR(e);
- excess(C, e, lclass & TYPE_PTR ? "array" : "struct or union");
-
- } END_FOR_EACH_PTR(e);
-
- convert_designators(C, last);
- expr->ctype = ctype;
-}
-
-static int is_string_literal(struct dmr_C *C, struct expression **v)
-{
- struct expression *e = *v;
- while (e && e->type == EXPR_PREOP && e->op == '(')
- e = e->unop;
- if (!e || e->type != EXPR_STRING)
- return 0;
- if (e != *v && C->Wparen_string)
- dmrC_warning(C, e->pos,
- "array initialized from parenthesized string constant");
- *v = e;
- return 1;
-}
-
-/*
- * We want a normal expression, possibly in one layer of braces. Warn
- * if the latter happens inside a list (it's legal, but likely to be
- * an effect of screwup). In case of anything not legal, we are definitely
- * having an effect of screwup, so just fail and let the caller warn.
- */
-static struct expression *handle_scalar(struct dmr_C *C, struct expression *e, int nested)
-{
- struct expression *v = NULL, *p;
- int count = 0;
-
- /* normal case */
- if (e->type != EXPR_INITIALIZER)
- return e;
-
- FOR_EACH_PTR(e->expr_list, p) {
- if (!v)
- v = p;
- count++;
- } END_FOR_EACH_PTR(p);
- if (count != 1)
- return NULL;
- switch(v->type) {
- case EXPR_INITIALIZER:
- case EXPR_INDEX:
- case EXPR_IDENTIFIER:
- return NULL;
- default:
- break;
- }
- if (nested)
- dmrC_warning(C, e->pos, "braces around scalar initializer");
- return v;
-}
-
-/*
- * deal with the cases that don't care about subobjects:
- * scalar <- assignment expression, possibly in braces [6.7.8(11)]
- * character array <- string literal, possibly in braces [6.7.8(14)]
- * struct or union <- assignment expression of compatible type [6.7.8(13)]
- * compound type <- initializer list in braces [6.7.8(16)]
- * The last one punts to handle_list_initializer() which, in turn will call
- * us for individual elements of the list.
- *
- * We do not handle 6.7.8(15) (wide char array <- wide string literal) for
- * the lack of support of wide char stuff in general.
- *
- * One note: we need to take care not to evaluate a string literal until
- * we know that we *will* handle it right here. Otherwise we would screw
- * the cases like struct { struct {char s[10]; ...} ...} initialized with
- * { "string", ...} - we need to preserve that string literal recognizable
- * until we dig into the inner struct.
- */
-static int handle_simple_initializer(struct dmr_C *C, struct expression **ep, int nested,
- int klass, struct symbol *ctype)
-{
- int is_string = is_string_type(C, ctype);
- struct expression *e = *ep, *p;
- struct symbol *type;
-
- if (!e)
- return 0;
-
- /* scalar */
- if (!(klass & TYPE_COMPOUND)) {
- e = handle_scalar(C, e, nested);
- if (!e)
- return 0;
- *ep = e;
- if (!dmrC_evaluate_expression(C, e))
- return 1;
- compatible_assignment_types(C, e, ctype, ep, "initializer");
- return 1;
- }
-
- /*
- * sublist; either a string, or we dig in; the latter will deal with
- * pathologies, so we don't need anything fancy here.
- */
- if (e->type == EXPR_INITIALIZER) {
- if (is_string) {
- struct expression *v = NULL;
- int count = 0;
-
- FOR_EACH_PTR(e->expr_list, p) {
- if (!v)
- v = p;
- count++;
- } END_FOR_EACH_PTR(p);
- if (count == 1 && is_string_literal(C, &v)) {
- *ep = e = v;
- goto String;
- }
- }
- handle_list_initializer(C, e, klass, ctype);
- return 1;
- }
-
- /* string */
- if (is_string_literal(C, &e)) {
- /* either we are doing array of char, or we'll have to dig in */
- if (is_string) {
- *ep = e;
- goto String;
- }
- return 0;
- }
- /* struct or union can be initialized by compatible */
- if (klass != TYPE_COMPOUND)
- return 0;
- type = dmrC_evaluate_expression(C, e);
- if (!type)
- return 0;
- if (ctype->type == SYM_NODE)
- ctype = ctype->ctype.base_type;
- if (type->type == SYM_NODE)
- type = type->ctype.base_type;
- if (ctype == type)
- return 1;
- return 0;
-
-String:
- p = dmrC_alloc_expression(C, e->pos, EXPR_STRING);
- *p = *e;
- type = dmrC_evaluate_expression(C, p);
- if (ctype->bit_size != -1) {
- if (ctype->bit_size + C->target->bits_in_char < type->bit_size)
- dmrC_warning(C, e->pos,
- "too long initializer-string for array of char");
- else if (C->Winit_cstring && ctype->bit_size + C->target->bits_in_char == type->bit_size) {
- dmrC_warning(C, e->pos,
- "too long initializer-string for array of char(no space for nul char)");
- }
- }
- *ep = p;
- return 1;
-}
-
-static void evaluate_initializer(struct dmr_C *C, struct symbol *ctype, struct expression **ep)
-{
- struct symbol *type;
- int klass = classify_type(C, ctype, &type);
- if (!handle_simple_initializer(C, ep, 0, klass, ctype))
- dmrC_expression_error(C, *ep, "invalid initializer");
-}
-
-static struct symbol *cast_to_bool(struct dmr_C *C, struct expression *expr)
-{
- struct expression *old = expr->cast_expression;
- struct expression *zero;
- struct symbol *otype;
- int oclass = classify_type(C, degenerate(C, old), &otype);
- struct symbol *ctype;
-
- if (oclass & TYPE_COMPOUND)
- return NULL;
-
- zero = dmrC_alloc_const_expression(C, expr->pos, 0);
- expr->op = SPECIAL_NOTEQUAL;
- ctype = usual_conversions(C, expr->op, old, zero,
- oclass, TYPE_NUM, otype, zero->ctype);
- expr->type = EXPR_COMPARE;
- expr->left = cast_to(C, old, ctype);
- expr->right = cast_to(C, zero, ctype);
-
- return expr->ctype;
-}
-static struct symbol *evaluate_cast(struct dmr_C *C, struct expression *expr)
-{
- struct expression *target = expr->cast_expression;
- struct symbol *ctype;
- struct symbol *t1, *t2;
- int class1, class2;
- int as1 = 0, as2 = 0;
-
- if (!target)
- return NULL;
-
- /*
- * Special case: a cast can be followed by an
- * initializer, in which case we need to pass
- * the type value down to that initializer rather
- * than trying to evaluate it as an expression
- *
- * A more complex case is when the initializer is
- * dereferenced as part of a post-fix expression.
- * We need to produce an expression that can be dereferenced.
- */
- if (target->type == EXPR_INITIALIZER) {
- struct symbol *sym = expr->cast_type;
- struct expression *addr = dmrC_alloc_expression(C, expr->pos, EXPR_SYMBOL);
-
- sym->initializer = target;
- evaluate_symbol(C, sym);
-
- addr->ctype = &C->S->lazy_ptr_ctype; /* Lazy eval */
- addr->symbol = sym;
-
- expr->type = EXPR_PREOP;
- expr->op = '*';
- expr->unop = addr;
- expr->ctype = sym;
-
- return sym;
- }
-
- ctype = dmrC_examine_symbol_type(C->S, expr->cast_type);
- expr->ctype = ctype;
- expr->cast_type = ctype;
-
- dmrC_evaluate_expression(C, target);
- degenerate(C, target);
-
- class1 = classify_type(C, ctype, &t1);
-
- /* cast to non-integer type -> not an integer constant expression */
- if (!is_int(class1))
- expr->flags = 0;
- /* if argument turns out to be not an integer constant expression *and*
- it was not a floating literal to start with -> too bad */
- else if (expr->flags == Int_const_expr &&
- !(target->flags & Int_const_expr))
- expr->flags = 0;
- /*
- * You can always throw a value away by casting to
- * "void" - that's an implicit "force". Note that
- * the same is _not_ true of "void *".
- */
- if (t1 == &C->S->void_ctype)
- goto out;
-
- if (class1 & (TYPE_COMPOUND | TYPE_FN))
- dmrC_warning(C, expr->pos, "cast to non-scalar");
-
- t2 = target->ctype;
- if (!t2) {
- dmrC_expression_error(C, expr, "cast from unknown type");
- goto out;
- }
- class2 = classify_type(C, t2, &t2);
-
- if (class2 & TYPE_COMPOUND)
- dmrC_warning(C, expr->pos, "cast from non-scalar");
-
- if (expr->type == EXPR_FORCE_CAST)
- goto out;
-
- /* allowed cast unfouls */
- if (class2 & TYPE_FOULED)
- t2 = unfoul(t2);
-
- if (t1 != t2) {
- if ((class1 & TYPE_RESTRICT) && restricted_value(target, t1))
- dmrC_warning(C, expr->pos, "cast to %s",
- dmrC_show_typename(C, t1));
- if (class2 & TYPE_RESTRICT) {
- if (t1 == &C->S->bool_ctype) {
- if (class2 & TYPE_FOULED)
- dmrC_warning(C, expr->pos, "%s degrades to integer",
- dmrC_show_typename(C, t2));
- }
- else {
- dmrC_warning(C, expr->pos, "cast from %s",
- dmrC_show_typename(C, t2));
- }
- }
- }
-
- if (t1 == &C->S->ulong_ctype)
- as1 = -1;
- else if (class1 == TYPE_PTR) {
- dmrC_examine_pointer_target(C->S, t1);
- as1 = t1->ctype.as;
- }
-
- if (t2 == &C->S->ulong_ctype)
- as2 = -1;
- else if (class2 == TYPE_PTR) {
- dmrC_examine_pointer_target(C->S, t2);
- as2 = t2->ctype.as;
- }
-
- if (!as1 && as2 > 0)
- dmrC_warning(C, expr->pos, "cast removes address space of expression");
- if (as1 > 0 && as2 > 0 && as1 != as2)
- dmrC_warning(C, expr->pos, "cast between address spaces (->)", as2, as1);
- if (as1 > 0 && !as2 &&
- !is_null_pointer_constant(C, target) && C->Wcast_to_as)
- dmrC_warning(C, expr->pos,
- "cast adds address space to expression ()", as1);
-
- if (!(t1->ctype.modifiers & MOD_PTRINHERIT) && class1 == TYPE_PTR &&
- !as1 && (target->flags & Int_const_expr)) {
- if (t1->ctype.base_type == &C->S->void_ctype) {
- if (dmrC_is_zero_constant(C, target)) {
- /* NULL */
- expr->type = EXPR_VALUE;
- expr->ctype = &C->S->null_ctype;
- expr->value = 0;
- return expr->ctype;
- }
- }
- }
-
- if (t1 == &C->S->bool_ctype)
- cast_to_bool(C, expr);
-
-out:
- return ctype;
-}
-
-/*
- * Evaluate a call expression with a symbol. This
- * should expand inline functions, and evaluate
- * builtins.
- */
-static int evaluate_symbol_call(struct dmr_C *C, struct expression *expr)
-{
- struct expression *fn = expr->fn;
- struct symbol *ctype = fn->ctype;
-
- if (fn->type != EXPR_PREOP)
- return 0;
-
- if (ctype->op && ctype->op->evaluate)
- return ctype->op->evaluate(C, expr);
-
- if (ctype->ctype.modifiers & MOD_INLINE) {
- int ret;
- struct symbol *curr = C->current_fn;
-
- if (ctype->definition)
- ctype = ctype->definition;
-
- C->current_fn = ctype->ctype.base_type;
-
- ret = dmrC_inline_function(C, expr, ctype);
-
- /* restore the old function */
- C->current_fn = curr;
- return ret;
- }
-
- return 0;
-}
-
-static struct symbol *evaluate_call(struct dmr_C *C, struct expression *expr)
-{
- int args, fnargs;
- struct symbol *ctype, *sym;
- struct expression *fn = expr->fn;
- struct expression_list *arglist = expr->args;
-
- if (!dmrC_evaluate_expression(C, fn))
- return NULL;
- sym = ctype = fn->ctype;
- if (ctype->type == SYM_NODE)
- ctype = ctype->ctype.base_type;
- if (ctype->type == SYM_PTR)
- ctype = dmrC_get_base_type(C->S, ctype);
-
- if (ctype->type != SYM_FN) {
- struct expression *arg;
- dmrC_expression_error(C, expr, "not a function %s",
- dmrC_show_ident(C, sym->ident));
- /* do typechecking in arguments */
- FOR_EACH_PTR (arglist, arg) {
- dmrC_evaluate_expression(C, arg);
- } END_FOR_EACH_PTR(arg);
- return NULL;
- }
-
- examine_fn_arguments(C, ctype);
- if (sym->type == SYM_NODE && fn->type == EXPR_PREOP &&
- sym->op && sym->op->args) {
- if (!sym->op->args(C, expr))
- return NULL;
- } else {
- if (!evaluate_arguments(C, ctype, arglist))
- return NULL;
- args = dmrC_expression_list_size(expr->args);
- fnargs = dmrC_symbol_list_size(ctype->arguments);
- if (args < fnargs)
- dmrC_expression_error(C, expr,
- "not enough arguments for function %s",
- dmrC_show_ident(C, sym->ident));
- if (args > fnargs && !ctype->variadic)
- dmrC_expression_error(C, expr,
- "too many arguments for function %s",
- dmrC_show_ident(C, sym->ident));
- }
- if (sym->type == SYM_NODE) {
- if (evaluate_symbol_call(C, expr))
- return expr->ctype;
- }
- expr->ctype = ctype->ctype.base_type;
- return expr->ctype;
-}
-
-static struct symbol *evaluate_offsetof(struct dmr_C *C, struct expression *expr)
-{
- struct expression *e = expr->down;
- struct symbol *ctype = expr->in;
- int klass;
-
- if (expr->op == '.') {
- struct symbol *field;
- int offset = 0;
- if (!ctype) {
- dmrC_expression_error(C, expr, "expected structure or union");
- return NULL;
- }
- dmrC_examine_symbol_type(C->S, ctype);
- klass = classify_type(C, ctype, &ctype);
- if (klass != TYPE_COMPOUND) {
- dmrC_expression_error(C, expr, "expected structure or union");
- return NULL;
- }
-
- field = find_identifier(C, expr->ident, ctype->symbol_list, &offset);
- if (!field) {
- dmrC_expression_error(C, expr, "unknown member");
- return NULL;
- }
- ctype = field;
- expr->type = EXPR_VALUE;
- expr->flags = Int_const_expr;
- expr->value = offset;
- expr->taint = 0;
- expr->ctype = C->target->size_t_ctype;
- } else {
- if (!ctype) {
- dmrC_expression_error(C, expr, "expected structure or union");
- return NULL;
- }
- dmrC_examine_symbol_type(C->S, ctype);
- klass = classify_type(C, ctype, &ctype);
- if (klass != (TYPE_COMPOUND | TYPE_PTR)) {
- dmrC_expression_error(C, expr, "expected array");
- return NULL;
- }
- ctype = ctype->ctype.base_type;
- if (!expr->index) {
- expr->type = EXPR_VALUE;
- expr->flags = Int_const_expr;
- expr->value = 0;
- expr->taint = 0;
- expr->ctype = C->target->size_t_ctype;
- } else {
- struct expression *idx = expr->index, *m;
- struct symbol *i_type = dmrC_evaluate_expression(C, idx);
- int i_class = classify_type(C, i_type, &i_type);
- if (!is_int(i_class)) {
- dmrC_expression_error(C, expr, "non-integer index");
- return NULL;
- }
- unrestrict(C, idx, i_class, &i_type);
- idx = cast_to(C, idx, C->target->size_t_ctype);
- m = dmrC_alloc_const_expression(C, expr->pos,
- dmrC_bits_to_bytes(C->target, ctype->bit_size));
- m->ctype = C->target->size_t_ctype;
- m->flags = Int_const_expr;
- expr->type = EXPR_BINOP;
- expr->left = idx;
- expr->right = m;
- expr->op = '*';
- expr->ctype = C->target->size_t_ctype;
- expr->flags = m->flags & idx->flags & Int_const_expr;
- }
- }
- if (e) {
- struct expression *copy = (struct expression *)dmrC_allocator_allocate(&C->expression_allocator, 0);
- *copy = *expr;
- if (e->type == EXPR_OFFSETOF)
- e->in = ctype;
- if (!dmrC_evaluate_expression(C, e))
- return NULL;
- expr->type = EXPR_BINOP;
- expr->flags = e->flags & copy->flags & Int_const_expr;
- expr->op = '+';
- expr->ctype = C->target->size_t_ctype;
- expr->left = copy;
- expr->right = e;
- }
- return C->target->size_t_ctype;
-}
-
-struct symbol *dmrC_evaluate_expression(struct dmr_C *C, struct expression *expr)
-{
- if (!expr)
- return NULL;
- if (expr->ctype)
- return expr->ctype;
-
- switch (expr->type) {
- case EXPR_VALUE:
- case EXPR_FVALUE:
- dmrC_expression_error(C, expr, "value expression without a type");
- return NULL;
- case EXPR_STRING:
- return evaluate_string(C, expr);
- case EXPR_SYMBOL:
- return evaluate_symbol_expression(C, expr);
- case EXPR_BINOP:
- if (!dmrC_evaluate_expression(C, expr->left))
- return NULL;
- if (!dmrC_evaluate_expression(C, expr->right))
- return NULL;
- return evaluate_binop(C, expr);
- case EXPR_LOGICAL:
- return evaluate_logical(C, expr);
- case EXPR_COMMA:
- dmrC_evaluate_expression(C, expr->left);
- if (!dmrC_evaluate_expression(C, expr->right))
- return NULL;
- return evaluate_comma(C, expr);
- case EXPR_COMPARE:
- if (!dmrC_evaluate_expression(C, expr->left))
- return NULL;
- if (!dmrC_evaluate_expression(C, expr->right))
- return NULL;
- return evaluate_compare(C, expr);
- case EXPR_ASSIGNMENT:
- if (!dmrC_evaluate_expression(C, expr->left))
- return NULL;
- if (!dmrC_evaluate_expression(C, expr->right))
- return NULL;
- return evaluate_assignment(C, expr);
- case EXPR_PREOP:
- if (!dmrC_evaluate_expression(C, expr->unop))
- return NULL;
- return evaluate_preop(C, expr);
- case EXPR_POSTOP:
- if (!dmrC_evaluate_expression(C, expr->unop))
- return NULL;
- return evaluate_postop(C, expr);
- case EXPR_CAST:
- case EXPR_FORCE_CAST:
- case EXPR_IMPLIED_CAST:
- return evaluate_cast(C, expr);
- case EXPR_SIZEOF:
- return evaluate_sizeof(C, expr);
- case EXPR_PTRSIZEOF:
- return evaluate_ptrsizeof(C, expr);
- case EXPR_ALIGNOF:
- return evaluate_alignof(C, expr);
- case EXPR_DEREF:
- return evaluate_member_dereference(C, expr);
- case EXPR_CALL:
- return evaluate_call(C, expr);
- case EXPR_SELECT:
- case EXPR_CONDITIONAL:
- return evaluate_conditional_expression(C, expr);
- case EXPR_STATEMENT:
- expr->ctype = dmrC_evaluate_statement(C, expr->statement);
- return expr->ctype;
-
- case EXPR_LABEL:
- expr->ctype = &C->S->ptr_ctype;
- return &C->S->ptr_ctype;
-
- case EXPR_TYPE:
- /* Evaluate the type of the symbol .. */
- evaluate_symbol(C, expr->symbol);
- /* .. but the type of the _expression_ is a "type" */
- expr->ctype = &C->S->type_ctype;
- return &C->S->type_ctype;
-
- case EXPR_OFFSETOF:
- return evaluate_offsetof(C, expr);
-
- /* These can not exist as stand-alone expressions */
- case EXPR_INITIALIZER:
- case EXPR_IDENTIFIER:
- case EXPR_INDEX:
- case EXPR_POS:
- dmrC_expression_error(C, expr, "internal front-end error: initializer in expression");
- return NULL;
- case EXPR_SLICE:
- dmrC_expression_error(C, expr, "internal front-end error: SLICE re-evaluated");
- return NULL;
- }
- return NULL;
-}
-
-static void check_duplicates(struct dmr_C *C, struct symbol *sym)
-{
- int declared = 0;
- struct symbol *next = sym;
- int initialized = sym->initializer != NULL;
-
- while ((next = next->same_symbol) != NULL) {
- const char *typediff;
- evaluate_symbol(C, next);
- if (initialized && next->initializer) {
- dmrC_sparse_error(C, sym->pos, "symbol '%s' has multiple initializers (originally initialized at %s:%d)",
- dmrC_show_ident(C, sym->ident),
- dmrC_stream_name(C, next->pos.stream), next->pos.line);
- /* Only warn once */
- initialized = 0;
- }
- declared++;
- typediff = dmrC_type_difference(C, &sym->ctype, &next->ctype, 0, 0);
- if (typediff) {
- dmrC_sparse_error(C, sym->pos, "symbol '%s' redeclared with different type (originally declared at %s:%d) - %s",
- dmrC_show_ident(C, sym->ident),
- dmrC_stream_name(C, next->pos.stream), next->pos.line, typediff);
- return;
- }
- }
- if (!declared) {
- unsigned long mod = sym->ctype.modifiers;
- if (mod & (MOD_STATIC | MOD_REGISTER))
- return;
- if (!(mod & MOD_TOPLEVEL))
- return;
- if (!C->Wdecl)
- return;
- if (sym->ident == C->S->main_ident)
- return;
- dmrC_warning(C, sym->pos, "symbol '%s' was not declared. Should it be static?", dmrC_show_ident(C, sym->ident));
- }
-}
-
-static struct symbol *evaluate_symbol(struct dmr_C *C, struct symbol *sym)
-{
- struct symbol *base_type;
-
- if (!sym)
- return sym;
- if (sym->evaluated)
- return sym;
- sym->evaluated = 1;
-
- sym = dmrC_examine_symbol_type(C->S, sym);
- base_type = dmrC_get_base_type(C->S, sym);
- if (!base_type)
- return NULL;
-
- /* Evaluate the initializers */
- if (sym->initializer)
- evaluate_initializer(C, sym, &sym->initializer);
-
- /* And finally, evaluate the body of the symbol too */
- if (base_type->type == SYM_FN) {
- struct symbol *curr = C->current_fn;
-
- if (sym->definition && sym->definition != sym)
- return evaluate_symbol(C, sym->definition);
-
- C->current_fn = base_type;
-
- examine_fn_arguments(C, base_type);
- if (!base_type->stmt && base_type->inline_stmt)
- dmrC_uninline(C, sym);
- if (base_type->stmt)
- dmrC_evaluate_statement(C, base_type->stmt);
-
- C->current_fn = curr;
- }
-
- return base_type;
-}
-
-void dmrC_evaluate_symbol_list(struct dmr_C *C, struct symbol_list *list)
-{
- struct symbol *sym;
-
- FOR_EACH_PTR(list, sym) {
- C->has_error &= ~ERROR_CURR_PHASE;
- evaluate_symbol(C, sym);
- check_duplicates(C, sym);
- } END_FOR_EACH_PTR(sym);
-}
-
-static struct symbol *evaluate_return_expression(struct dmr_C *C, struct statement *stmt)
-{
- struct expression *expr = stmt->expression;
- struct symbol *fntype;
-
- dmrC_evaluate_expression(C, expr);
- fntype = C->current_fn->ctype.base_type;
- if (!fntype || fntype == &C->S->void_ctype) {
- if (expr && expr->ctype != &C->S->void_ctype)
- dmrC_expression_error(C, expr, "return expression in %s function", fntype?"void":"typeless");
- if (expr && C->Wreturn_void)
- dmrC_warning(C, stmt->pos, "returning void-valued expression");
- return NULL;
- }
-
- if (!expr) {
- dmrC_sparse_error(C, stmt->pos, "return with no return value");
- return NULL;
- }
- if (!expr->ctype)
- return NULL;
- compatible_assignment_types(C, expr, fntype, &stmt->expression, "return expression");
- return NULL;
-}
-
-static void evaluate_if_statement(struct dmr_C *C, struct statement *stmt)
-{
- if (!stmt->if_conditional)
- return;
-
- evaluate_conditional(C, stmt->if_conditional, 0);
- dmrC_evaluate_statement(C, stmt->if_true);
- dmrC_evaluate_statement(C, stmt->if_false);
-}
-
-static void evaluate_iterator(struct dmr_C *C, struct statement *stmt)
-{
- dmrC_evaluate_symbol_list(C, stmt->iterator_syms);
- evaluate_conditional(C, stmt->iterator_pre_condition, 1);
- evaluate_conditional(C, stmt->iterator_post_condition,1);
- dmrC_evaluate_statement(C, stmt->iterator_pre_statement);
- dmrC_evaluate_statement(C, stmt->iterator_statement);
- dmrC_evaluate_statement(C, stmt->iterator_post_statement);
-}
-
-static void verify_output_constraint(struct dmr_C *C, struct expression *expr, const char *constraint)
-{
- switch (*constraint) {
- case '=': /* Assignment */
- case '+': /* Update */
- break;
- default:
- dmrC_expression_error(C, expr, "output constraint is not an assignment constraint (\"%s\")", constraint);
- }
-}
-
-static void verify_input_constraint(struct dmr_C *C, struct expression *expr, const char *constraint)
-{
- switch (*constraint) {
- case '=': /* Assignment */
- case '+': /* Update */
- dmrC_expression_error(C, expr, "input constraint with assignment (\"%s\")", constraint);
- }
-}
-
-static void evaluate_asm_statement(struct dmr_C *C, struct statement *stmt)
-{
- struct expression *expr;
- struct symbol *sym;
- int state;
-
- expr = stmt->asm_string;
- if (!expr || expr->type != EXPR_STRING) {
- dmrC_sparse_error(C, stmt->pos, "need constant string for inline asm");
- return;
- }
-
- state = 0;
- FOR_EACH_PTR(stmt->asm_outputs, expr) {
- switch (state) {
- case 0: /* Identifier */
- state = 1;
- continue;
-
- case 1: /* Constraint */
- state = 2;
- if (!expr || expr->type != EXPR_STRING) {
- dmrC_sparse_error(C, expr ? expr->pos : stmt->pos, "asm output constraint is not a string");
- *THIS_ADDRESS(struct expression *, expr) = NULL;
- continue;
- }
- verify_output_constraint(C, expr, expr->string->data);
- continue;
-
- case 2: /* Expression */
- state = 0;
- if (!dmrC_evaluate_expression(C, expr))
- return;
- if (!lvalue_expression(C, expr))
- dmrC_warning(C, expr->pos, "asm output is not an lvalue");
- evaluate_assign_to(C, expr, expr->ctype);
- continue;
- }
- } END_FOR_EACH_PTR(expr);
-
- state = 0;
- FOR_EACH_PTR(stmt->asm_inputs, expr) {
- switch (state) {
- case 0: /* Identifier */
- state = 1;
- continue;
-
- case 1: /* Constraint */
- state = 2;
- if (!expr || expr->type != EXPR_STRING) {
- dmrC_sparse_error(C, expr ? expr->pos : stmt->pos, "asm input constraint is not a string");
- *THIS_ADDRESS(struct expression *, expr) = NULL;
- continue;
- }
- verify_input_constraint(C, expr, expr->string->data);
- continue;
-
- case 2: /* Expression */
- state = 0;
- if (!dmrC_evaluate_expression(C, expr))
- return;
- continue;
- }
- } END_FOR_EACH_PTR(expr);
-
- FOR_EACH_PTR(stmt->asm_clobbers, expr) {
- if (!expr) {
- dmrC_sparse_error(C, stmt->pos, "bad asm clobbers");
- return;
- }
- if (expr->type == EXPR_STRING)
- continue;
- dmrC_expression_error(C, expr, "asm clobber is not a string");
- } END_FOR_EACH_PTR(expr);
-
-
- FOR_EACH_PTR(stmt->asm_labels, sym) {
- if (!sym || sym->type != SYM_LABEL) {
- dmrC_sparse_error(C, stmt->pos, "bad asm label");
- return;
- }
- } END_FOR_EACH_PTR(sym);
-}
-
-static void evaluate_case_statement(struct dmr_C *C, struct statement *stmt)
-{
- dmrC_evaluate_expression(C, stmt->case_expression);
- dmrC_evaluate_expression(C, stmt->case_to);
- dmrC_evaluate_statement(C, stmt->case_statement);
-}
-
-static void check_case_type(struct dmr_C *C, struct expression *switch_expr,
- struct expression *case_expr,
- struct expression **enumcase)
-{
- struct symbol *switch_type, *case_type;
- int sclass, cclass;
-
- if (!case_expr)
- return;
-
- switch_type = switch_expr->ctype;
- case_type = dmrC_evaluate_expression(C, case_expr);
-
- if (!switch_type || !case_type)
- goto Bad;
- if (enumcase) {
- if (*enumcase)
- warn_for_different_enum_types(C, case_expr->pos, case_type, (*enumcase)->ctype);
- else if (dmrC_is_enum_type(case_type))
- *enumcase = case_expr;
- }
-
- sclass = classify_type(C, switch_type, &switch_type);
- cclass = classify_type(C, case_type, &case_type);
-
- /* both should be arithmetic */
- if (!(sclass & cclass & TYPE_NUM))
- goto Bad;
-
- /* neither should be floating */
- if ((sclass | cclass) & TYPE_FLOAT)
- goto Bad;
-
- /* if neither is restricted, we are OK */
- if (!((sclass | cclass) & TYPE_RESTRICT))
- return;
-
- if (!restricted_binop_type(C, SPECIAL_EQUAL, case_expr, switch_expr,
- cclass, sclass, case_type, switch_type)) {
- unrestrict(C, case_expr, cclass, &case_type);
- unrestrict(C, switch_expr, sclass, &switch_type);
- }
- return;
-
-Bad:
- dmrC_expression_error(C, case_expr, "incompatible types for 'case' statement");
-}
-
-static void evaluate_switch_statement(struct dmr_C *C, struct statement *stmt)
-{
- struct symbol *sym;
- struct expression *enumcase = NULL;
- struct expression **enumcase_holder = &enumcase;
- struct expression *sel = stmt->switch_expression;
-
- dmrC_evaluate_expression(C, sel);
- dmrC_evaluate_statement(C, stmt->switch_statement);
- if (!sel)
- return;
- if (sel->ctype && dmrC_is_enum_type(sel->ctype))
- enumcase_holder = NULL; /* Only check cases against switch */
-
- FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
- struct statement *case_stmt = sym->stmt;
- check_case_type(C, sel, case_stmt->case_expression, enumcase_holder);
- check_case_type(C, sel, case_stmt->case_to, enumcase_holder);
- } END_FOR_EACH_PTR(sym);
-}
-
-static void evaluate_goto_statement(struct dmr_C *C, struct statement *stmt)
-{
- struct symbol *label = stmt->goto_label;
-
- if (label && !label->stmt && !dmrC_lookup_keyword(label->ident, NS_KEYWORD))
- dmrC_sparse_error(C, stmt->pos, "label '%s' was not declared", dmrC_show_ident(C, label->ident));
-
- dmrC_evaluate_expression(C, stmt->goto_expression);
-}
-
-struct symbol *dmrC_evaluate_statement(struct dmr_C *C, struct statement *stmt)
-{
- if (!stmt)
- return NULL;
-
- switch (stmt->type) {
- case STMT_DECLARATION: {
- struct symbol *s;
- FOR_EACH_PTR(stmt->declaration, s) {
- evaluate_symbol(C, s);
- } END_FOR_EACH_PTR(s);
- return NULL;
- }
-
- case STMT_RETURN:
- return evaluate_return_expression(C, stmt);
-
- case STMT_EXPRESSION:
- if (!dmrC_evaluate_expression(C, stmt->expression))
- return NULL;
- if (stmt->expression->ctype == &C->S->null_ctype)
- stmt->expression = cast_to(C, stmt->expression, &C->S->ptr_ctype);
- return degenerate(C, stmt->expression);
-
- case STMT_COMPOUND: {
- struct statement *s;
- struct symbol *type = NULL;
-
- /* Evaluate the return symbol in the compound statement */
- evaluate_symbol(C, stmt->ret);
-
- /*
- * Then, evaluate each statement, making the type of the
- * compound statement be the type of the last statement
- */
- type = dmrC_evaluate_statement(C, stmt->args);
- FOR_EACH_PTR(stmt->stmts, s) {
- type = dmrC_evaluate_statement(C, s);
- } END_FOR_EACH_PTR(s);
- if (!type)
- type = &C->S->void_ctype;
- return type;
- }
- case STMT_IF:
- evaluate_if_statement(C, stmt);
- return NULL;
- case STMT_ITERATOR:
- evaluate_iterator(C, stmt);
- return NULL;
- case STMT_SWITCH:
- evaluate_switch_statement(C, stmt);
- return NULL;
- case STMT_CASE:
- evaluate_case_statement(C, stmt);
- return NULL;
- case STMT_LABEL:
- return dmrC_evaluate_statement(C, stmt->label_statement);
- case STMT_GOTO:
- evaluate_goto_statement(C, stmt);
- return NULL;
- case STMT_NONE:
- break;
- case STMT_ASM:
- evaluate_asm_statement(C, stmt);
- return NULL;
- case STMT_CONTEXT:
- dmrC_evaluate_expression(C, stmt->expression);
- return NULL;
- case STMT_RANGE:
- dmrC_evaluate_expression(C, stmt->range_expression);
- dmrC_evaluate_expression(C, stmt->range_low);
- dmrC_evaluate_expression(C, stmt->range_high);
- return NULL;
- }
- return NULL;
-}
diff --git a/dmr_c/src/expand.c b/dmr_c/src/expand.c
deleted file mode 100644
index 7f86df4..0000000
--- a/dmr_c/src/expand.c
+++ /dev/null
@@ -1,1347 +0,0 @@
-/*
- * sparse/expand.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.
- *
- * expand constant expressions.
- */
- /*
- * This version is part of the dmr_c project.
- * Copyright (C) 2017 Dibyendu Majumdar
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-static int expand_expression(struct dmr_C *C, struct expression *);
-static int expand_statement(struct dmr_C *C, struct statement *);
-static int conservative;
-
-static int expand_symbol_expression(struct dmr_C *C, struct expression *expr)
-{
- struct symbol *sym = expr->symbol;
-
- if (sym == &C->S->zero_int) {
- if (C->Wundef)
- dmrC_warning(C, expr->pos, "undefined preprocessor identifier '%s'", dmrC_show_ident(C, expr->symbol_name));
- expr->type = EXPR_VALUE;
- expr->value = 0;
- expr->taint = 0;
- return 0;
- }
- /* The cost of a symbol expression is lower for on-stack symbols */
- return (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN)) ? 2 : 1;
-}
-
-static long long get_longlong(struct dmr_C *C, struct expression *expr)
-{
- int no_expand = expr->ctype->ctype.modifiers & MOD_UNSIGNED;
- long long mask = 1ULL << (expr->ctype->bit_size - 1);
- long long value = expr->value;
- long long ormask, andmask;
- (void)C;
-
- if (!(value & mask))
- no_expand = 1;
- andmask = mask | (mask-1);
- ormask = ~andmask;
- if (no_expand)
- ormask = 0;
- return (value & andmask) | ormask;
-}
-
-void dmrC_cast_value(struct dmr_C *C, struct expression *expr, struct symbol *newtype,
- struct expression *old, struct symbol *oldtype)
-{
- int old_size = oldtype->bit_size;
- int new_size = newtype->bit_size;
- long long value, mask, signmask;
- long long oldmask, oldsignmask, dropped;
-
- if (dmrC_is_float_type(C->S, newtype) ||
- dmrC_is_float_type(C->S, oldtype))
- goto Float;
-
- // For pointers and integers, we can just move the value around
- expr->type = EXPR_VALUE;
- expr->taint = old->taint;
- if (old_size == new_size) {
- expr->value = old->value;
- return;
- }
-
- // expand it to the full "long long" value
- value = get_longlong(C, old);
-
-Int:
- // _Bool requires a zero test rather than truncation.
- if (dmrC_is_bool_type(C->S, newtype)) {
- expr->value = !!value;
- if (!conservative && value != 0 && value != 1)
- dmrC_warning(C, old->pos, "odd constant _Bool cast (%llx becomes 1)", value);
- return;
- }
-
- // Truncate it to the new size
- signmask = 1ULL << (new_size-1);
- mask = signmask | (signmask-1);
- expr->value = value & mask;
-
- // Stop here unless checking for truncation
- if (!C->Wcast_truncate || conservative)
- return;
-
- // Check if we dropped any bits..
- oldsignmask = 1ULL << (old_size-1);
- oldmask = oldsignmask | (oldsignmask-1);
- dropped = oldmask & ~mask;
-
- // OK if the bits were (and still are) purely sign bits
- if (value & dropped) {
- if (!(value & oldsignmask) || !(value & signmask) || (value & dropped) != dropped)
- dmrC_warning(C, old->pos, "cast truncates bits from constant value (%llx becomes %llx)",
- value & oldmask,
- value & mask);
- }
- return;
-
-Float:
- if (!dmrC_is_float_type(C->S, newtype)) {
- value = (long long)old->fvalue;
- expr->type = EXPR_VALUE;
- expr->taint = 0;
- goto Int;
- }
-
- if (!dmrC_is_float_type(C->S, oldtype))
- expr->fvalue = (long double)get_longlong(C, old);
- else
- expr->fvalue = old->fvalue;
-
- if (!(newtype->ctype.modifiers & MOD_LONGLONG) && \
- !(newtype->ctype.modifiers & MOD_LONGLONGLONG)) {
- if ((newtype->ctype.modifiers & MOD_LONG))
- expr->fvalue = (double)expr->fvalue;
- else
- expr->fvalue = (float)expr->fvalue;
- }
- expr->type = EXPR_FVALUE;
-}
-
-static int check_shift_count(struct dmr_C *C, struct expression *expr, struct symbol *ctype, unsigned int count)
-{
- dmrC_warning(C, expr->pos, "shift too big (%u) for type %s", count, dmrC_show_typename(C, ctype));
- count &= ctype->bit_size-1;
- return count;
-}
-
-/*
- * CAREFUL! We need to get the size and sign of the
- * result right!
- */
-#define CONVERT(op,s) (((op)<<1)+(s))
-#define SIGNED(op) CONVERT(op, 1)
-#define UNSIGNED(op) CONVERT(op, 0)
-static int simplify_int_binop(struct dmr_C *C, struct expression *expr, struct symbol *ctype)
-{
- struct expression *left = expr->left, *right = expr->right;
- unsigned long long v, l, r, mask;
- signed long long sl, sr;
- int is_signed;
-
- if (right->type != EXPR_VALUE)
- return 0;
- r = right->value;
- if (expr->op == SPECIAL_LEFTSHIFT || expr->op == SPECIAL_RIGHTSHIFT) {
- if ((int)r >= ctype->bit_size) {
- if (conservative)
- return 0;
- r = check_shift_count(C, expr, ctype, (unsigned int)r);
- right->value = r;
- }
- }
- if (left->type != EXPR_VALUE)
- return 0;
- l = left->value; r = right->value;
- is_signed = !(ctype->ctype.modifiers & MOD_UNSIGNED);
- mask = 1ULL << (ctype->bit_size-1);
- sl = l; sr = r;
- if (is_signed && (sl & mask))
- sl |= ~(mask-1);
- if (is_signed && (sr & mask))
- sr |= ~(mask-1);
-
- switch (CONVERT(expr->op,is_signed)) {
- case SIGNED('+'):
- case UNSIGNED('+'):
- v = l + r;
- break;
-
- case SIGNED('-'):
- case UNSIGNED('-'):
- v = l - r;
- break;
-
- case SIGNED('&'):
- case UNSIGNED('&'):
- v = l & r;
- break;
-
- case SIGNED('|'):
- case UNSIGNED('|'):
- v = l | r;
- break;
-
- case SIGNED('^'):
- case UNSIGNED('^'):
- v = l ^ r;
- break;
-
- case SIGNED('*'):
- v = sl * sr;
- break;
-
- case UNSIGNED('*'):
- v = l * r;
- break;
-
- case SIGNED('/'):
- if (!r)
- goto Div;
- if (l == mask && sr == -1)
- goto Overflow;
- v = sl / sr;
- break;
-
- case UNSIGNED('/'):
- if (!r) goto Div;
- v = l / r;
- break;
-
- case SIGNED('%'):
- if (!r)
- goto Div;
- if (l == mask && sr == -1)
- goto Overflow;
- v = sl % sr;
- break;
-
- case UNSIGNED('%'):
- if (!r) goto Div;
- v = l % r;
- break;
-
- case SIGNED(SPECIAL_LEFTSHIFT):
- case UNSIGNED(SPECIAL_LEFTSHIFT):
- v = l << r;
- break;
-
- case SIGNED(SPECIAL_RIGHTSHIFT):
- v = sl >> r;
- break;
-
- case UNSIGNED(SPECIAL_RIGHTSHIFT):
- v = l >> r;
- break;
-
- default:
- return 0;
- }
- mask = mask | (mask-1);
- expr->value = v & mask;
- expr->type = EXPR_VALUE;
- expr->taint = left->taint | right->taint;
- return 1;
-Div:
- if (!conservative)
- dmrC_warning(C, expr->pos, "division by zero");
- return 0;
-Overflow:
- if (!conservative)
- dmrC_warning(C, expr->pos, "constant integer operation overflow");
- return 0;
-}
-
-static int simplify_cmp_binop(struct dmr_C *C, struct expression *expr, struct symbol *ctype)
-{
- struct expression *left = expr->left, *right = expr->right;
- unsigned long long l, r, mask;
- signed long long sl, sr;
-
- (void) C;
- if (left->type != EXPR_VALUE || right->type != EXPR_VALUE)
- return 0;
- l = left->value; r = right->value;
- mask = 1ULL << (ctype->bit_size-1);
- sl = l; sr = r;
- if (sl & mask)
- sl |= ~(mask-1);
- if (sr & mask)
- sr |= ~(mask-1);
- switch (expr->op) {
- case '<': expr->value = sl < sr; break;
- case '>': expr->value = sl > sr; break;
- case SPECIAL_LTE: expr->value = sl <= sr; break;
- case SPECIAL_GTE: expr->value = sl >= sr; break;
- case SPECIAL_EQUAL: expr->value = l == r; break;
- case SPECIAL_NOTEQUAL: expr->value = l != r; break;
- case SPECIAL_UNSIGNED_LT:expr->value = l < r; break;
- case SPECIAL_UNSIGNED_GT:expr->value = l > r; break;
- case SPECIAL_UNSIGNED_LTE:expr->value = l <= r; break;
- case SPECIAL_UNSIGNED_GTE:expr->value = l >= r; break;
- }
- expr->type = EXPR_VALUE;
- expr->taint = left->taint | right->taint;
- return 1;
-}
-
-static int simplify_float_binop(struct dmr_C *C, struct expression *expr)
-{
- struct expression *left = expr->left, *right = expr->right;
- unsigned long mod = expr->ctype->ctype.modifiers;
- long double l, r, res;
-
- if (left->type != EXPR_FVALUE || right->type != EXPR_FVALUE)
- return 0;
-
- l = left->fvalue;
- r = right->fvalue;
-
- if (mod & MOD_LONGLONG) {
- switch (expr->op) {
- case '+': res = l + r; break;
- case '-': res = l - r; break;
- case '*': res = l * r; break;
- case '/': if (!r) goto Div;
- res = l / r; break;
- default: return 0;
- }
- } else if (mod & MOD_LONG) {
- switch (expr->op) {
- case '+': res = (double) l + (double) r; break;
- case '-': res = (double) l - (double) r; break;
- case '*': res = (double) l * (double) r; break;
- case '/': if (!r) goto Div;
- res = (double) l / (double) r; break;
- default: return 0;
- }
- } else {
- switch (expr->op) {
- case '+': res = (float)l + (float)r; break;
- case '-': res = (float)l - (float)r; break;
- case '*': res = (float)l * (float)r; break;
- case '/': if (!r) goto Div;
- res = (float)l / (float)r; break;
- default: return 0;
- }
- }
- expr->type = EXPR_FVALUE;
- expr->fvalue = res;
- return 1;
-Div:
- if (!conservative)
- dmrC_warning(C, expr->pos, "division by zero");
- return 0;
-}
-
-static int simplify_float_cmp(struct dmr_C *C, struct expression *expr, struct symbol *ctype)
-{
- (void) C;
- (void)ctype;
- struct expression *left = expr->left, *right = expr->right;
- long double l, r;
-
- if (left->type != EXPR_FVALUE || right->type != EXPR_FVALUE)
- return 0;
-
- l = left->fvalue;
- r = right->fvalue;
- switch (expr->op) {
- case '<': expr->value = l < r; break;
- case '>': expr->value = l > r; break;
- case SPECIAL_LTE: expr->value = l <= r; break;
- case SPECIAL_GTE: expr->value = l >= r; break;
- case SPECIAL_EQUAL: expr->value = l == r; break;
- case SPECIAL_NOTEQUAL: expr->value = l != r; break;
- }
- expr->type = EXPR_VALUE;
- expr->taint = 0;
- return 1;
-}
-
-static int expand_binop(struct dmr_C *C, struct expression *expr)
-{
- int cost;
-
- cost = expand_expression(C, expr->left);
- cost += expand_expression(C, expr->right);
- if (simplify_int_binop(C, expr, expr->ctype))
- return 0;
- if (simplify_float_binop(C, expr))
- return 0;
- return cost + 1;
-}
-
-static int expand_logical(struct dmr_C *C, struct expression *expr)
-{
- struct expression *left = expr->left;
- struct expression *right;
- int cost, rcost;
-
- /* Do immediate short-circuiting ... */
- cost = expand_expression(C, left);
- if (left->type == EXPR_VALUE) {
- if (expr->op == SPECIAL_LOGICAL_AND) {
- if (!left->value) {
- expr->type = EXPR_VALUE;
- expr->value = 0;
- expr->taint = left->taint;
- return 0;
- }
- } else {
- if (left->value) {
- expr->type = EXPR_VALUE;
- expr->value = 1;
- expr->taint = left->taint;
- return 0;
- }
- }
- }
-
- right = expr->right;
- rcost = expand_expression(C, right);
- if (left->type == EXPR_VALUE && right->type == EXPR_VALUE) {
- /*
- * We know the left value doesn't matter, since
- * otherwise we would have short-circuited it..
- */
- expr->type = EXPR_VALUE;
- expr->value = right->value != 0;
- expr->taint = left->taint | right->taint;
- return 0;
- }
-
- /*
- * If the right side is safe and cheaper than a branch,
- * just avoid the branch and turn it into a regular binop
- * style SAFELOGICAL.
- */
- if (rcost < BRANCH_COST) {
- expr->type = EXPR_BINOP;
- rcost -= BRANCH_COST - 1;
- }
-
- return cost + BRANCH_COST + rcost;
-}
-
-static int expand_comma(struct dmr_C *C, struct expression *expr)
-{
- int cost;
-
- cost = expand_expression(C, expr->left);
- cost += expand_expression(C, expr->right);
- if (expr->left->type == EXPR_VALUE || expr->left->type == EXPR_FVALUE) {
- unsigned flags = expr->flags;
- unsigned taint;
- taint = expr->left->type == EXPR_VALUE ? expr->left->taint : 0;
- *expr = *expr->right;
- expr->flags = flags;
- if (expr->type == EXPR_VALUE)
- expr->taint |= Taint_comma | taint;
- }
- return cost;
-}
-
-#define MOD_IGN (MOD_VOLATILE | MOD_CONST)
-
-static int compare_types(struct dmr_C *C, int op, struct symbol *left, struct symbol *right)
-{
- struct ctype c1 = {.base_type = left};
- struct ctype c2 = {.base_type = right};
- switch (op) {
- case SPECIAL_EQUAL:
- return !dmrC_type_difference(C, &c1, &c2, MOD_IGN, MOD_IGN);
- case SPECIAL_NOTEQUAL:
- return dmrC_type_difference(C, &c1, &c2, MOD_IGN, MOD_IGN) != NULL;
- case '<':
- return left->bit_size < right->bit_size;
- case '>':
- return left->bit_size > right->bit_size;
- case SPECIAL_LTE:
- return left->bit_size <= right->bit_size;
- case SPECIAL_GTE:
- return left->bit_size >= right->bit_size;
- }
- return 0;
-}
-
-static int expand_compare(struct dmr_C *C, struct expression *expr)
-{
- struct expression *left = expr->left, *right = expr->right;
- int cost;
-
- cost = expand_expression(C, left);
- cost += expand_expression(C, right);
-
- if (left && right) {
- /* Type comparison? */
- if (left->type == EXPR_TYPE && right->type == EXPR_TYPE) {
- int op = expr->op;
- expr->type = EXPR_VALUE;
- expr->value = compare_types(C, op, left->symbol, right->symbol);
- expr->taint = 0;
- return 0;
- }
- if (simplify_cmp_binop(C, expr, left->ctype))
- return 0;
- if (simplify_float_cmp(C, expr, left->ctype))
- return 0;
- }
- return cost + 1;
-}
-
-static int expand_conditional(struct dmr_C *C, struct expression *expr)
-{
- struct expression *cond = expr->conditional;
- struct expression *truee = expr->cond_true;
- struct expression *falsee = expr->cond_false;
- int cost, cond_cost;
-
- cond_cost = expand_expression(C, cond);
- if (cond->type == EXPR_VALUE) {
- unsigned flags = expr->flags;
- if (!cond->value)
- truee = falsee;
- if (!truee)
- truee = cond;
- cost = expand_expression(C, truee);
- *expr = *truee;
- expr->flags = flags;
- if (expr->type == EXPR_VALUE)
- expr->taint |= cond->taint;
- return cost;
- }
-
- cost = expand_expression(C, truee);
- cost += expand_expression(C, falsee);
-
- if (cost < SELECT_COST) {
- expr->type = EXPR_SELECT;
- cost -= BRANCH_COST - 1;
- }
-
- return cost + cond_cost + BRANCH_COST;
-}
-
-static int expand_assignment(struct dmr_C *C, struct expression *expr)
-{
- expand_expression(C, expr->left);
- expand_expression(C, expr->right);
- return SIDE_EFFECTS;
-}
-
-static int expand_addressof(struct dmr_C *C, struct expression *expr)
-{
- return expand_expression(C, expr->unop);
-}
-
-/*
- * Look up a trustable initializer value at the requested offset.
- *
- * Return NULL if no such value can be found or statically trusted.
- *
- * FIXME!! We should check that the size is right!
- */
-static struct expression *constant_symbol_value(struct dmr_C *C, struct symbol *sym, int offset)
-{
- struct expression *value;
- (void)C;
-
- if (sym->ctype.modifiers & (MOD_ASSIGNED | MOD_ADDRESSABLE))
- return NULL;
- value = sym->initializer;
- if (!value)
- return NULL;
- if (value->type == EXPR_INITIALIZER) {
- struct expression *entry;
- FOR_EACH_PTR(value->expr_list, entry) {
- if (entry->type != EXPR_POS) {
- if (offset)
- continue;
- return entry;
- }
- if ((int) entry->init_offset < offset)
- continue;
- if ((int) entry->init_offset > offset)
- return NULL;
- return entry->init_expr;
- } END_FOR_EACH_PTR(entry);
- return NULL;
- }
- return value;
-}
-
-static int expand_dereference(struct dmr_C *C, struct expression *expr)
-{
- struct expression *unop = expr->unop;
- unsigned int offset;
-
- expand_expression(C, unop);
-
- /*
- * NOTE! We get a bogus warning right now for some special
- * cases: apparently I've screwed up the optimization of
- * a zero-offset dereference, and the ctype is wrong.
- *
- * Leave the warning in anyway, since this is also a good
- * test for me to get the type evaluation right..
- */
- if (expr->ctype->ctype.modifiers & MOD_NODEREF)
- dmrC_warning(C, unop->pos, "dereference of noderef expression");
-
- /*
- * Is it "symbol" or "symbol + offset"?
- */
- offset = 0;
- if (unop->type == EXPR_BINOP && unop->op == '+') {
- struct expression *right = unop->right;
- if (right->type == EXPR_VALUE) {
- offset = (unsigned int) right->value;
- unop = unop->left;
- }
- }
-
- if (unop->type == EXPR_SYMBOL) {
- struct symbol *sym = unop->symbol;
- struct expression *value = constant_symbol_value(C, sym, offset);
-
- /* Const symbol with a constant initializer? */
- if (value) {
- /* FIXME! We should check that the size is right! */
- if (value->type == EXPR_VALUE) {
- /*
- During the expansion of a dereference, it's if the initializer
- which corrrespond to the offset we're interested is a constant.
- In which case this dereference can be avoided and the value
- given in the initializer can be used instead.
-
- However, it's not enough to check for the offset since for bitfields
- several are placed at the same offset.
- Hence refuse such expansion if the constant value correspond
- to a bitfield.
- */
- if (dmrC_is_bitfield_type(value->ctype))
- return UNSAFE;
- expr->type = EXPR_VALUE;
- expr->value = value->value;
- expr->taint = 0;
- return 0;
- } else if (value->type == EXPR_FVALUE) {
- expr->type = EXPR_FVALUE;
- expr->fvalue = value->fvalue;
- return 0;
- }
- }
-
- /* Direct symbol dereference? Cheap and safe */
- return (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN)) ? 2 : 1;
- }
-
- return UNSAFE;
-}
-
-static int simplify_preop(struct dmr_C *C, struct expression *expr)
-{
- struct expression *op = expr->unop;
- unsigned long long v, mask;
-
- if (op->type != EXPR_VALUE)
- return 0;
-
- mask = 1ULL << (expr->ctype->bit_size-1);
- v = op->value;
- switch (expr->op) {
- case '+': break;
- case '-':
- if (v == mask && !(expr->ctype->ctype.modifiers & MOD_UNSIGNED))
- goto Overflow;
- v = -v;
- break;
- case '!': v = !v; break;
- case '~': v = ~v; break;
- default: return 0;
- }
- mask = mask | (mask-1);
- expr->value = v & mask;
- expr->type = EXPR_VALUE;
- expr->taint = op->taint;
- return 1;
-
-Overflow:
- if (!conservative)
- dmrC_warning(C, expr->pos, "constant integer operation overflow");
- return 0;
-}
-
-static int simplify_float_preop(struct dmr_C *C, struct expression *expr)
-{
- (void) C;
- struct expression *op = expr->unop;
- long double v;
-
- if (op->type != EXPR_FVALUE)
- return 0;
- v = op->fvalue;
- switch (expr->op) {
- case '+': break;
- case '-': v = -v; break;
- default: return 0;
- }
- expr->fvalue = v;
- expr->type = EXPR_FVALUE;
- return 1;
-}
-
-/*
- * Unary post-ops: x++ and x--
- */
-static int expand_postop(struct dmr_C *C, struct expression *expr)
-{
- expand_expression(C, expr->unop);
- return SIDE_EFFECTS;
-}
-
-static int expand_preop(struct dmr_C *C, struct expression *expr)
-{
- int cost;
-
- switch (expr->op) {
- case '*':
- return expand_dereference(C, expr);
-
- case '&':
- return expand_addressof(C, expr);
-
- case SPECIAL_INCREMENT:
- case SPECIAL_DECREMENT:
- /*
- * From a type evaluation standpoint the preops are
- * the same as the postops
- */
- return expand_postop(C, expr);
-
- default:
- break;
- }
- cost = expand_expression(C, expr->unop);
-
- if (simplify_preop(C, expr))
- return 0;
- if (simplify_float_preop(C, expr))
- return 0;
- return cost + 1;
-}
-
-static int expand_arguments(struct dmr_C *C, struct expression_list *head)
-{
- int cost = 0;
- struct expression *expr;
-
- FOR_EACH_PTR (head, expr) {
- cost += expand_expression(C, expr);
- } END_FOR_EACH_PTR(expr);
- return cost;
-}
-
-static int expand_cast(struct dmr_C *C, struct expression *expr)
-{
- int cost;
- struct expression *target = expr->cast_expression;
-
- cost = expand_expression(C, target);
-
- /* Simplify normal integer casts.. */
- if (target->type == EXPR_VALUE || target->type == EXPR_FVALUE) {
- dmrC_cast_value(C, expr, expr->ctype, target, target->ctype);
- return 0;
- }
- return cost + 1;
-}
-
-/*
- * expand a call expression with a symbol. This
- * should expand builtins.
- */
-static int expand_symbol_call(struct dmr_C *C, struct expression *expr, int cost)
-{
- struct expression *fn = expr->fn;
- struct symbol *ctype = fn->ctype;
-
- if (fn->type != EXPR_PREOP)
- return SIDE_EFFECTS;
-
- if (ctype->op && ctype->op->expand)
- return ctype->op->expand(C, expr, cost);
-
- if (ctype->ctype.modifiers & MOD_PURE)
- return cost + 1;
-
- return SIDE_EFFECTS;
-}
-
-static int expand_call(struct dmr_C *C, struct expression *expr)
-{
- int cost;
- struct symbol *sym;
- struct expression *fn = expr->fn;
-
- cost = expand_arguments(C, expr->args);
- sym = fn->ctype;
- if (!sym) {
- dmrC_expression_error(C, expr, "function has no type");
- return SIDE_EFFECTS;
- }
- if (sym->type == SYM_NODE)
- return expand_symbol_call(C, expr, cost);
-
- return SIDE_EFFECTS;
-}
-
-static int expand_expression_list(struct dmr_C *C, struct expression_list *list)
-{
- int cost = 0;
- struct expression *expr;
-
- FOR_EACH_PTR(list, expr) {
- cost += expand_expression(C, expr);
- } END_FOR_EACH_PTR(expr);
- return cost;
-}
-
-/*
- * We can simplify nested position expressions if
- * this is a simple (single) positional expression.
- */
-static int expand_pos_expression(struct dmr_C *C, struct expression *expr)
-{
- struct expression *nested = expr->init_expr;
- unsigned long offset = expr->init_offset;
- int nr = expr->init_nr;
-
- if (nr == 1) {
- switch (nested->type) {
- case EXPR_POS:
- offset += nested->init_offset;
- *expr = *nested;
- expr->init_offset = offset;
- nested = expr;
- break;
-
- case EXPR_INITIALIZER: {
- struct expression *reuse = nested, *entry;
- *expr = *nested;
- FOR_EACH_PTR(expr->expr_list, entry) {
- if (entry->type == EXPR_POS) {
- entry->init_offset += offset;
- } else {
- if (!reuse) {
- /*
- * This happens rarely, but it can happen
- * with bitfields that are all at offset
- * zero..
- */
- reuse = dmrC_alloc_expression(C, entry->pos, EXPR_POS);
- }
- reuse->type = EXPR_POS;
- reuse->ctype = entry->ctype;
- reuse->init_offset = offset;
- reuse->init_nr = 1;
- reuse->init_expr = entry;
- REPLACE_CURRENT_PTR(struct expression *, entry, reuse);
- reuse = NULL;
- }
- } END_FOR_EACH_PTR(entry);
- nested = expr;
- break;
- }
-
- default:
- break;
- }
- }
- return expand_expression(C, nested);
-}
-
-static unsigned long bit_offset(struct dmr_C *C, const struct expression *expr)
-{
- unsigned long offset = 0;
- while (expr->type == EXPR_POS) {
- offset += dmrC_bytes_to_bits(C->target, expr->init_offset);
- expr = expr->init_expr;
- }
- if (expr && expr->ctype)
- offset += expr->ctype->bit_offset;
- return offset;
-}
-
-static unsigned long bit_range(const struct expression *expr)
-{
- unsigned long range = 0;
- unsigned long size = 0;
- while (expr->type == EXPR_POS) {
- unsigned long nr = expr->init_nr;
- size = expr->ctype->bit_size;
- range += (nr - 1) * size;
- expr = expr->init_expr;
- }
- range += size;
- return range;
-}
-
-static int compare_expressions(void *userdata, const void *_a, const void *_b)
-{
- struct dmr_C *C = (struct dmr_C *) userdata;
- const struct expression *a = (const struct expression *)_a;
- const struct expression *b = (const struct expression *)_b;
- unsigned long a_pos = bit_offset(C, a);
- unsigned long b_pos = bit_offset(C, b);
-
- return (a_pos < b_pos) ? -1 : (a_pos == b_pos) ? 0 : 1;
-}
-
-static void sort_expression_list(struct dmr_C *C, struct expression_list **list)
-{
- ptrlist_sort((struct ptr_list **)list, C, compare_expressions);
-}
-
-static void verify_nonoverlapping(struct dmr_C *C, struct expression_list **list, struct expression *expr)
-{
- struct expression *a = NULL;
- unsigned long max = 0;
- unsigned long whole = expr->ctype->bit_size;
- struct expression *b;
-
- if (!C->Woverride_init)
- return;
-
- FOR_EACH_PTR(*list, b) {
- unsigned long off, end;
- if (!b->ctype || !b->ctype->bit_size)
- continue;
- off = bit_offset(C, b);
- if (a && off < max) {
- dmrC_warning(C, a->pos, "Initializer entry defined twice");
- dmrC_info(C, b->pos, " also defined here");
- if (!C->Woverride_init_all)
- return;
- }
- end = off + bit_range(b);
- if (!a && !C->Woverride_init_whole_range) {
- // If first entry is the whole range, do not let
- // any warning about it (this allow to initialize
- // an array with some default value and then override
- // some specific entries).
- if (off == 0 && end == whole)
- continue;
- }
- if (end > max) {
- max = end;
- a = b;
- }
- } END_FOR_EACH_PTR(b);
-}
-
-static int expand_expression(struct dmr_C *C, struct expression *expr)
-{
- if (!expr)
- return 0;
- if (!expr->ctype || expr->ctype == &C->S->bad_ctype)
- return UNSAFE;
-
- switch (expr->type) {
- case EXPR_VALUE:
- case EXPR_FVALUE:
- case EXPR_STRING:
- return 0;
- case EXPR_TYPE:
- case EXPR_SYMBOL:
- return expand_symbol_expression(C, expr);
- case EXPR_BINOP:
- return expand_binop(C, expr);
-
- case EXPR_LOGICAL:
- return expand_logical(C, expr);
-
- case EXPR_COMMA:
- return expand_comma(C, expr);
-
- case EXPR_COMPARE:
- return expand_compare(C, expr);
-
- case EXPR_ASSIGNMENT:
- return expand_assignment(C, expr);
-
- case EXPR_PREOP:
- return expand_preop(C, expr);
-
- case EXPR_POSTOP:
- return expand_postop(C, expr);
-
- case EXPR_CAST:
- case EXPR_FORCE_CAST:
- case EXPR_IMPLIED_CAST:
- return expand_cast(C, expr);
-
- case EXPR_CALL:
- return expand_call(C, expr);
-
- case EXPR_DEREF:
- dmrC_warning(C, expr->pos, "we should not have an EXPR_DEREF left at expansion time");
- return UNSAFE;
-
- case EXPR_SELECT:
- case EXPR_CONDITIONAL:
- return expand_conditional(C, expr);
-
- case EXPR_STATEMENT: {
- struct statement *stmt = expr->statement;
- int cost = expand_statement(C, stmt);
-
- if (stmt->type == STMT_EXPRESSION && stmt->expression)
- *expr = *stmt->expression;
- return cost;
- }
-
- case EXPR_LABEL:
- return 0;
-
- case EXPR_INITIALIZER:
- sort_expression_list(C, &expr->expr_list);
- verify_nonoverlapping(C, &expr->expr_list, expr);
- return expand_expression_list(C, expr->expr_list);
-
- case EXPR_IDENTIFIER:
- return UNSAFE;
-
- case EXPR_INDEX:
- return UNSAFE;
-
- case EXPR_SLICE:
- return expand_expression(C, expr->base) + 1;
-
- case EXPR_POS:
- return expand_pos_expression(C, expr);
-
- case EXPR_SIZEOF:
- case EXPR_PTRSIZEOF:
- case EXPR_ALIGNOF:
- case EXPR_OFFSETOF:
- dmrC_expression_error(C, expr, "internal front-end error: sizeof in expansion?");
- return UNSAFE;
- }
- return SIDE_EFFECTS;
-}
-
-static void expand_const_expression(struct dmr_C *C, struct expression *expr, const char *where)
-{
- if (expr) {
- expand_expression(C, expr);
- if (expr->type != EXPR_VALUE)
- dmrC_expression_error(C, expr, "Expected constant expression in %s", where);
- }
-}
-
-int dmrC_expand_symbol(struct dmr_C *C, struct symbol *sym)
-{
- int retval;
- struct symbol *base_type;
-
- if (!sym)
- return 0;
- base_type = sym->ctype.base_type;
- if (!base_type)
- return 0;
-
- retval = expand_expression(C, sym->initializer);
- /* expand the body of the symbol */
- if (base_type->type == SYM_FN) {
- if (base_type->stmt)
- expand_statement(C, base_type->stmt);
- }
- return retval;
-}
-
-static void expand_return_expression(struct dmr_C *C, struct statement *stmt)
-{
- expand_expression(C, stmt->expression);
-}
-
-static int expand_if_statement(struct dmr_C *C, struct statement *stmt)
-{
- struct expression *expr = stmt->if_conditional;
-
- if (!expr || !expr->ctype || expr->ctype == &C->S->bad_ctype)
- return UNSAFE;
-
- expand_expression(C, expr);
-
-/* This is only valid if nobody jumps into the "dead" side */
-#if 0
- /* Simplify constant conditionals without even evaluating the false side */
- if (expr->type == EXPR_VALUE) {
- struct statement *simple;
- simple = expr->value ? stmt->if_true : stmt->if_false;
-
- /* Nothing? */
- if (!simple) {
- stmt->type = STMT_NONE;
- return 0;
- }
- expand_statement(simple);
- *stmt = *simple;
- return SIDE_EFFECTS;
- }
-#endif
- expand_statement(C, stmt->if_true);
- expand_statement(C, stmt->if_false);
- return SIDE_EFFECTS;
-}
-
-/*
- * Expanding a compound statement is really just
- * about adding up the costs of each individual
- * statement.
- *
- * We also collapse a simple compound statement:
- * this would trigger for simple inline functions,
- * except we would have to check the "return"
- * symbol usage. Next time.
- */
-static int expand_compound(struct dmr_C *C, struct statement *stmt)
-{
- struct statement *s, *last;
- int cost, statements;
-
- if (stmt->ret)
- dmrC_expand_symbol(C, stmt->ret);
-
- last = stmt->args;
- cost = expand_statement(C, last);
- statements = last != NULL;
- FOR_EACH_PTR(stmt->stmts, s) {
- statements++;
- last = s;
- cost += expand_statement(C, s);
- } END_FOR_EACH_PTR(s);
-
- if (statements == 1 && !stmt->ret)
- *stmt = *last;
-
- return cost;
-}
-
-static int expand_statement(struct dmr_C *C, struct statement *stmt)
-{
- if (!stmt)
- return 0;
-
- switch (stmt->type) {
- case STMT_DECLARATION: {
- struct symbol *sym;
- FOR_EACH_PTR(stmt->declaration, sym) {
- dmrC_expand_symbol(C, sym);
- } END_FOR_EACH_PTR(sym);
- return SIDE_EFFECTS;
- }
-
- case STMT_RETURN:
- expand_return_expression(C, stmt);
- return SIDE_EFFECTS;
-
- case STMT_EXPRESSION:
- return expand_expression(C, stmt->expression);
-
- case STMT_COMPOUND:
- return expand_compound(C, stmt);
-
- case STMT_IF:
- return expand_if_statement(C, stmt);
-
- case STMT_ITERATOR:
- expand_expression(C, stmt->iterator_pre_condition);
- expand_expression(C, stmt->iterator_post_condition);
- expand_statement(C, stmt->iterator_pre_statement);
- expand_statement(C, stmt->iterator_statement);
- expand_statement(C, stmt->iterator_post_statement);
- return SIDE_EFFECTS;
-
- case STMT_SWITCH:
- expand_expression(C, stmt->switch_expression);
- expand_statement(C, stmt->switch_statement);
- return SIDE_EFFECTS;
-
- case STMT_CASE:
- expand_const_expression(C, stmt->case_expression, "case statement");
- expand_const_expression(C, stmt->case_to, "case statement");
- expand_statement(C, stmt->case_statement);
- return SIDE_EFFECTS;
-
- case STMT_LABEL:
- expand_statement(C, stmt->label_statement);
- return SIDE_EFFECTS;
-
- case STMT_GOTO:
- expand_expression(C, stmt->goto_expression);
- return SIDE_EFFECTS;
-
- case STMT_NONE:
- break;
- case STMT_ASM:
- /* FIXME! Do the asm parameter evaluation! */
- break;
- case STMT_CONTEXT:
- expand_expression(C, stmt->expression);
- break;
- case STMT_RANGE:
- expand_expression(C, stmt->range_expression);
- expand_expression(C, stmt->range_low);
- expand_expression(C, stmt->range_high);
- break;
- }
- return SIDE_EFFECTS;
-}
-
-static inline int bad_integer_constant_expression(struct dmr_C *C, struct expression *expr)
-{
- (void) C;
- if (!(expr->flags & Int_const_expr))
- return 1;
- if (expr->taint & Taint_comma)
- return 1;
- return 0;
-}
-
-static long long __get_expression_value(struct dmr_C *C, struct expression *expr, int strict)
-{
- long long value, mask;
- struct symbol *ctype;
-
- if (!expr)
- return 0;
- ctype = dmrC_evaluate_expression(C, expr);
- if (!ctype) {
- dmrC_expression_error(C, expr, "bad constant expression type");
- return 0;
- }
- expand_expression(C, expr);
- if (expr->type != EXPR_VALUE) {
- if (strict != 2)
- dmrC_expression_error(C, expr, "bad constant expression");
- return 0;
- }
- if ((strict == 1) && bad_integer_constant_expression(C, expr)) {
- dmrC_expression_error(C, expr, "bad integer constant expression");
- return 0;
- }
-
- value = expr->value;
- mask = 1ULL << (ctype->bit_size-1);
-
- if (value & mask) {
- while (ctype->type != SYM_BASETYPE)
- ctype = ctype->ctype.base_type;
- if (!(ctype->ctype.modifiers & MOD_UNSIGNED))
- value = value | mask | ~(mask-1);
- }
- return value;
-}
-
-long long dmrC_get_expression_value(struct dmr_C *C, struct expression *expr)
-{
- return __get_expression_value(C, expr, 0);
-}
-
-long long dmrC_const_expression_value(struct dmr_C *C, struct expression *expr)
-{
- return __get_expression_value(C, expr, 1);
-}
-
-long long dmrC_get_expression_value_silent(struct dmr_C *C, struct expression *expr)
-{
-
- return __get_expression_value(C, expr, 2);
-}
-
-int dmrC_expr_truth_value(struct dmr_C *C, struct expression *expr)
-{
- const int saved = conservative;
- struct symbol *ctype;
-
- if (!expr)
- return 0;
-
- ctype = dmrC_evaluate_expression(C, expr);
- if (!ctype)
- return -1;
-
- conservative = 1;
- expand_expression(C, expr);
- conservative = saved;
-
-redo:
- switch (expr->type) {
- case EXPR_COMMA:
- expr = expr->right;
- goto redo;
- case EXPR_VALUE:
- return expr->value != 0;
- case EXPR_FVALUE:
- return expr->fvalue != 0;
- default:
- return -1;
- }
-}
-
-int dmrC_is_zero_constant(struct dmr_C *C, struct expression *expr)
-{
- const int saved = conservative;
- conservative = 1;
- expand_expression(C, expr);
- conservative = saved;
- return expr->type == EXPR_VALUE && !expr->value;
-}
diff --git a/dmr_c/src/expand.h b/dmr_c/src/expand.h
deleted file mode 100644
index 27e10c0..0000000
--- a/dmr_c/src/expand.h
+++ /dev/null
@@ -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
diff --git a/dmr_c/src/expression.c b/dmr_c/src/expression.c
deleted file mode 100644
index 08636f2..0000000
--- a/dmr_c/src/expression.c
+++ /dev/null
@@ -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
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-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);
-}
-
-
diff --git a/dmr_c/src/expression.h b/dmr_c/src/expression.h
deleted file mode 100644
index e59c658..0000000
--- a/dmr_c/src/expression.h
+++ /dev/null
@@ -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
-#include
-#include
-
-#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
diff --git a/dmr_c/src/flow.c b/dmr_c/src/flow.c
deleted file mode 100644
index 3419112..0000000
--- a/dmr_c/src/flow.c
+++ /dev/null
@@ -1,1008 +0,0 @@
-/*
- * Flow - walk the linearized flowgraph, simplifying it as we
- * go along.
- *
- * Copyright (C) 2004 Linus Torvalds
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-/*
- * Dammit, if we have a phi-node followed by a conditional
- * branch on that phi-node, we should damn well be able to
- * do something about the source. Maybe.
- */
-static int rewrite_branch(struct dmr_C *C, struct basic_block *bb,
- struct basic_block **ptr,
- struct basic_block *old,
- struct basic_block *new)
-{
- if (*ptr != old || new == old || !bb->ep)
- return 0;
-
- /* We might find new if-conversions or non-dominating CSEs */
- /* we may also create new dead cycles */
- C->L->repeat_phase |= REPEAT_CSE | REPEAT_CFG_CLEANUP;
- *ptr = new;
- dmrC_replace_bb_in_list(&bb->children, old, new, 1);
- dmrC_remove_bb_from_list(&old->parents, bb, 1);
- dmrC_add_bb(C, &new->parents, bb);
- return 1;
-}
-
-/*
- * Return the known truth value of a pseudo, or -1 if
- * it's not known.
- */
-static int pseudo_truth_value(pseudo_t pseudo)
-{
- switch (pseudo->type) {
- case PSEUDO_VAL:
- return !!pseudo->value;
-
- case PSEUDO_REG: {
- struct instruction *insn = pseudo->def;
-
- /* A symbol address is always considered true.. */
- if (insn->opcode == OP_SYMADDR && insn->target == pseudo)
- return 1;
- }
- /* Fall through */
- default:
- return -1;
- }
-}
-
-/*
- * Does a basic block depend on the pseudos that "src" defines?
- */
-static int bb_depends_on(struct basic_block *target, struct basic_block *src)
-{
- pseudo_t pseudo;
-
- FOR_EACH_PTR(src->defines, pseudo) {
- if (dmrC_pseudo_in_list(target->needs, pseudo))
- return 1;
- } END_FOR_EACH_PTR(pseudo);
- return 0;
-}
-
-/*
- * This really should be handled by bb_depends_on()
- * which efficiently check the dependence using the
- * defines - needs liveness info. Problem is that
- * there is no liveness done on OP_PHI & OP_PHISRC.
- *
- * This function add the missing dependency checks.
- */
-static int bb_depends_on_phi(struct basic_block *target, struct basic_block *src)
-{
- struct instruction *insn;
- FOR_EACH_PTR(src->insns, insn) {
- if (!insn->bb)
- continue;
- if (insn->opcode != OP_PHI)
- continue;
- if (dmrC_pseudo_in_list(target->needs, insn->target))
- return 1;
- } END_FOR_EACH_PTR(insn);
- return 0;
-}
-/*
- * When we reach here, we have:
- * - a basic block that ends in a conditional branch and
- * that has no side effects apart from the pseudos it
- * may change.
- * - the phi-node that the conditional branch depends on
- * - full pseudo liveness information
- *
- * We need to check if any of the _sources_ of the phi-node
- * may be constant, and not actually need this block at all.
- */
-static int try_to_simplify_bb(struct dmr_C *C, struct basic_block *bb, struct instruction *first, struct instruction *second)
-{
- int changed = 0;
- pseudo_t phi;
- int bogus;
-
- /*
- * This a due to improper dominance tracking during
- * simplify_symbol_usage()/conversion to SSA form.
- * No sane simplification can be done when we have this.
- */
- bogus = dmrC_bb_list_size(bb->parents) != dmrC_pseudo_list_size(first->phi_list);
-
- FOR_EACH_PTR(first->phi_list, phi) {
- struct instruction *def = phi->def;
- struct basic_block *source, *target;
- pseudo_t pseudo;
- struct instruction *br;
- int true;
-
- if (!def)
- continue;
- source = def->bb;
- pseudo = def->src1;
- if (!pseudo || !source)
- continue;
- br = dmrC_last_instruction(source->insns);
- if (!br)
- continue;
- if (br->opcode != OP_CBR && br->opcode != OP_BR)
- continue;
- true = pseudo_truth_value(pseudo);
- if (true < 0)
- continue;
- target = true ? second->bb_true : second->bb_false;
- if (bb_depends_on(target, bb))
- continue;
- if (bb_depends_on_phi(target, bb))
- continue;
- changed |= rewrite_branch(C, source, &br->bb_true, bb, target);
- changed |= rewrite_branch(C, source, &br->bb_false, bb, target);
- if (changed && !bogus)
- dmrC_kill_use(C, THIS_ADDRESS(pseudo_t, phi));
- } END_FOR_EACH_PTR(phi);
- return changed;
-}
-
-static int bb_has_side_effects(struct basic_block *bb)
-{
- struct instruction *insn;
- FOR_EACH_PTR(bb->insns, insn) {
- switch (insn->opcode) {
- case OP_CALL:
- /* FIXME! This should take "const" etc into account */
- return 1;
-
- case OP_STORE:
- case OP_CONTEXT:
- return 1;
-
- case OP_ASM:
- /* FIXME! This should take "volatile" etc into account */
- return 1;
-
- default:
- continue;
- }
- } END_FOR_EACH_PTR(insn);
- return 0;
-}
-
-static int simplify_phi_branch(struct dmr_C *C, struct basic_block *bb, struct instruction *br)
-{
- pseudo_t cond = br->cond;
- struct instruction *def;
-
- if (cond->type != PSEUDO_REG)
- return 0;
- def = cond->def;
- if (def->bb != bb || def->opcode != OP_PHI)
- return 0;
- if (bb_has_side_effects(bb))
- return 0;
- return try_to_simplify_bb(C, bb, def, br);
-}
-
-static int simplify_branch_branch(struct dmr_C *C, struct basic_block *bb, struct instruction *br,
- struct basic_block **target_p, int true)
-{
- struct basic_block *target = *target_p, *final;
- struct instruction *insn;
- int retval;
-
- if (target == bb)
- return 0;
- insn = dmrC_last_instruction(target->insns);
- if (!insn || insn->opcode != OP_CBR || insn->cond != br->cond)
- return 0;
- /*
- * Ahhah! We've found a branch to a branch on the same conditional!
- * Now we just need to see if we can rewrite the branch..
- */
- retval = 0;
- final = true ? insn->bb_true : insn->bb_false;
- if (bb_has_side_effects(target))
- goto try_to_rewrite_target;
- if (bb_depends_on(final, target))
- goto try_to_rewrite_target;
- if (bb_depends_on_phi(final, target))
- return 0;
- return rewrite_branch(C, bb, target_p, target, final);
-
-try_to_rewrite_target:
- /*
- * If we're the only parent, at least we can rewrite the
- * now-known second branch.
- */
- if (dmrC_bb_list_size(target->parents) != 1)
- return retval;
- dmrC_insert_branch(C, target, insn, final);
- return 1;
-}
-
-static int simplify_one_branch(struct dmr_C *C, struct basic_block *bb, struct instruction *br)
-{
- if (simplify_phi_branch(C, bb, br))
- return 1;
- return simplify_branch_branch(C, bb, br, &br->bb_true, 1) |
- simplify_branch_branch(C, bb, br, &br->bb_false, 0);
-}
-
-static int simplify_branch_nodes(struct dmr_C *C, struct entrypoint *ep)
-{
- int changed = 0;
- struct basic_block *bb;
-
- FOR_EACH_PTR(ep->bbs, bb) {
- struct instruction *br = dmrC_last_instruction(bb->insns);
-
- if (!br || br->opcode != OP_CBR)
- continue;
- changed |= simplify_one_branch(C, bb, br);
- } END_FOR_EACH_PTR(bb);
- return changed;
-}
-
-/*
- * This is called late - when we have intra-bb liveness information..
- */
-int dmrC_simplify_flow(struct dmr_C *C, struct entrypoint *ep)
-{
- return simplify_branch_nodes(C, ep);
-}
-
-
-void dmrC_convert_load_instruction(struct dmr_C *C, struct instruction *insn, pseudo_t src)
-{
- dmrC_convert_instruction_target(C, insn, src);
- /* Turn the load into a no-op */
- insn->opcode = OP_LNOP;
- insn->bb = NULL;
-}
-
-static int overlapping_memop(struct dmr_C *C, struct instruction *a, struct instruction *b)
-{
- unsigned int a_start = dmrC_bytes_to_bits(C->target, a->offset);
- unsigned int b_start = dmrC_bytes_to_bits(C->target, b->offset);
- unsigned int a_size = a->size;
- unsigned int b_size = b->size;
-
- if (a_size + a_start <= b_start)
- return 0;
- if (b_size + b_start <= a_start)
- return 0;
- return 1;
-}
-
-static inline int same_memop(struct instruction *a, struct instruction *b)
-{
- return a->offset == b->offset && a->size == b->size;
-}
-
-static inline int distinct_symbols(pseudo_t a, pseudo_t b)
-{
- if (a->type != PSEUDO_SYM)
- return 0;
- if (b->type != PSEUDO_SYM)
- return 0;
- return a->sym != b->sym;
-}
-/*
- * Return 1 if "dom" dominates the access to "pseudo"
- * in "insn".
- *
- * Return 0 if it doesn't, and -1 if you don't know.
- */
-int dmrC_dominates(struct dmr_C *C, pseudo_t pseudo, struct instruction *insn, struct instruction *dom, int local)
-{
- int opcode = dom->opcode;
-
- if (opcode == OP_CALL || opcode == OP_ENTRY)
- return local ? 0 : -1;
- if (opcode != OP_LOAD && opcode != OP_STORE)
- return 0;
- if (dom->src != pseudo) {
- if (local)
- return 0;
- /* We don't think two explicitly different symbols ever alias */
- if (distinct_symbols(insn->src, dom->src))
- return 0;
- /* We could try to do some alias analysis here */
- return -1;
- }
- if (!same_memop(insn, dom)) {
- // TODO I think I changed this to fix some simplification issue
- // http://marc.info/?l=linux-sparse&m=148966371314267&w=2
- if (dom->opcode == OP_LOAD)
- return -1;
- if (!overlapping_memop(C, insn, dom))
- return 0;
- return -1;
- }
- return 1;
-}
-
-static int phisrc_in_bb(struct pseudo_list *list, struct basic_block *bb)
-{
- pseudo_t p;
- FOR_EACH_PTR(list, p) {
- if (p->def->bb == bb)
- return 1;
- } END_FOR_EACH_PTR(p);
-
- return 0;
-}
-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;
-
- if (!bb->parents)
- return !!local;
-
- 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 == 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:
- if (dominators && phisrc_in_bb(*dominators, parent))
- continue;
- br = dmrC_delete_last_instruction(&parent->insns);
- phi = dmrC_alloc_phi(C, parent, one->target, one->type);
- phi->ident = phi->ident ? phi->ident : pseudo->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;
-}
-
-/*
- * We should probably sort the phi list just to make it easier to compare
- * later for equality.
- */
-void dmrC_rewrite_load_instruction(struct dmr_C *C, struct instruction *insn, struct pseudo_list *dominators)
-{
- pseudo_t new, phi;
-
- /*
- * Check for somewhat common case of duplicate
- * phi nodes.
- */
- new = dmrC_first_pseudo(dominators)->def->src1;
- FOR_EACH_PTR(dominators, phi) {
- if (new != phi->def->src1)
- goto complex_phi;
- new->ident = new->ident ? new->ident : phi->ident;
- } END_FOR_EACH_PTR(phi);
-
- /*
- * All the same pseudo - mark the phi-nodes unused
- * and convert the load into a LNOP and replace the
- * pseudo.
- */
- FOR_EACH_PTR(dominators, phi) {
- dmrC_kill_instruction(C, phi->def);
- } END_FOR_EACH_PTR(phi);
- dmrC_convert_load_instruction(C, insn, new);
- return;
-
-complex_phi:
- /* We leave symbol pseudos with a bogus usage list here */
- if (insn->src->type != PSEUDO_SYM)
- dmrC_kill_use(C, &insn->src);
- insn->opcode = OP_PHI;
- insn->phi_list = dominators;
-}
-
-static int find_dominating_stores(struct dmr_C *C, pseudo_t pseudo, struct instruction *insn,
- unsigned long generation, int local)
-{
- struct basic_block *bb = insn->bb;
- struct instruction *one, *dom = NULL;
- struct pseudo_list *dominators;
- int partial;
-
- /* Unreachable load? Undo it */
- if (!bb) {
- insn->opcode = OP_LNOP;
- return 1;
- }
-
- partial = 0;
- FOR_EACH_PTR(bb->insns, one) {
- int dominance;
- if (one == insn)
- goto found;
- dominance = dmrC_dominates(C, pseudo, insn, one, local);
- if (dominance < 0) {
- /* Ignore partial load dominators */
- if (one->opcode == OP_LOAD)
- continue;
- dom = NULL;
- partial = 1;
- continue;
- }
- if (!dominance)
- continue;
- dom = one;
- partial = 0;
- } END_FOR_EACH_PTR(one);
- /* Whaa? */
- dmrC_warning(C, pseudo->sym->pos, "unable to find symbol read");
- return 0;
-found:
- if (partial)
- return 0;
-
- if (dom) {
- dmrC_convert_load_instruction(C, insn, dom->target);
- return 1;
- }
-
- /* OK, go find the parents */
- bb->generation = generation;
-
- dominators = NULL;
- if (!find_dominating_parents(C, pseudo, insn, bb, generation, &dominators, local))
- return 0;
-
- /* This happens with initial assignments to structures etc.. */
- if (!dominators) {
- if (!local)
- return 0;
- dmrC_check_access(C, insn);
- dmrC_convert_load_instruction(C, insn, dmrC_value_pseudo(C, insn->type, 0));
- return 1;
- }
-
- /*
- * If we find just one dominating instruction, we
- * can turn it into a direct thing. Otherwise we'll
- * have to turn the load into a phi-node of the
- * dominators.
- */
- dmrC_rewrite_load_instruction(C, insn, dominators);
- return 1;
-}
-
-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);
- }
-}
-
-/* Kill a pseudo that is dead on exit from the bb */
-static void kill_dead_stores(struct dmr_C *C, pseudo_t pseudo, unsigned long generation, struct basic_block *bb, int local)
-{
- struct instruction *insn;
- struct basic_block *parent;
-
- if (bb->generation == generation)
- return;
- bb->generation = generation;
- FOR_EACH_PTR_REVERSE(bb->insns, insn) {
- int opcode = insn->opcode;
-
- if (opcode != OP_LOAD && opcode != OP_STORE) {
- if (local)
- continue;
- if (opcode == OP_CALL)
- return;
- continue;
- }
- if (insn->src == pseudo) {
- if (opcode == OP_LOAD)
- return;
- kill_store(C, insn);
- continue;
- }
- if (local)
- continue;
- if (insn->src->type != PSEUDO_SYM)
- return;
- } END_FOR_EACH_PTR_REVERSE(insn);
-
- FOR_EACH_PTR(bb->parents, parent) {
- struct basic_block *child;
- FOR_EACH_PTR(parent->children, child) {
- if (child && child != bb)
- return;
- } END_FOR_EACH_PTR(child);
- kill_dead_stores(C, pseudo, generation, parent, local);
- } END_FOR_EACH_PTR(parent);
-}
-
-/*
- * This should see if the "insn" trivially dominates some previous store, and kill the
- * store if unnecessary.
- */
-static void kill_dominated_stores(struct dmr_C *C, pseudo_t pseudo, struct instruction *insn,
- unsigned long generation, struct basic_block *bb, int local, int found)
-{
- struct instruction *one;
- struct basic_block *parent;
-
- /* Unreachable store? Undo it */
- if (!bb) {
- kill_store(C, insn);
- return;
- }
- if (bb->generation == generation)
- return;
- bb->generation = generation;
- FOR_EACH_PTR_REVERSE(bb->insns, one) {
- int dominance;
- if (!found) {
- if (one != insn)
- continue;
- found = 1;
- continue;
- }
- dominance = dmrC_dominates(C, pseudo, insn, one, local);
- if (!dominance)
- continue;
- if (dominance < 0)
- return;
- if (one->opcode == OP_LOAD)
- return;
- kill_store(C, one);
- } END_FOR_EACH_PTR_REVERSE(one);
-
- if (!found) {
- dmrC_warning(C, bb->pos, "Unable to find instruction");
- return;
- }
-
- FOR_EACH_PTR(bb->parents, parent) {
- struct basic_block *child;
- FOR_EACH_PTR(parent->children, child) {
- if (child && child != bb)
- return;
- } END_FOR_EACH_PTR(child);
- kill_dominated_stores(C, pseudo, insn, generation, parent, local, found);
- } END_FOR_EACH_PTR(parent);
-}
-
-void dmrC_check_access(struct dmr_C *C, struct instruction *insn)
-{
- pseudo_t pseudo = insn->src;
-
- if (insn->bb && pseudo->type == PSEUDO_SYM) {
- int offset = insn->offset, bit = dmrC_bytes_to_bits(C->target, offset) + insn->size;
- struct symbol *sym = pseudo->sym;
-
- if (sym->bit_size > 0 && (offset < 0 || bit > sym->bit_size))
- dmrC_warning(C, insn->pos, "invalid access %s '%s' (%d %d)",
- offset < 0 ? "below" : "past the end of",
- dmrC_show_ident(C, sym->ident), offset,
- dmrC_bits_to_bytes(C->target, sym->bit_size));
- }
-}
-
-static void simplify_one_symbol(struct dmr_C *C, struct entrypoint *ep, struct symbol *sym)
-{
-#if SINGLE_STORE_SHORTCUT
- pseudo_t pseudo, src;
- struct instruction *def;
-#else
- pseudo_t pseudo;
-#endif
- struct pseudo_user *pu;
- unsigned long mod;
-#if SINGLE_STORE_SHORTCUT
- int all, stores, complex;
-#else
- int all;
-#endif
-
- /* Never used as a symbol? */
- pseudo = sym->pseudo;
- if (!pseudo)
- return;
-
- /* We don't do coverage analysis of volatiles.. */
- if (sym->ctype.modifiers & MOD_VOLATILE)
- return;
-
- /* ..and symbols with external visibility need more care */
- mod = sym->ctype.modifiers & (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE);
- if (mod)
- goto external_visibility;
-
-#if SINGLE_STORE_SHORTCUT
- def = NULL;
- stores = 0;
- complex = 0;
-#endif
- FOR_EACH_PTR(pseudo->users, pu) {
- /* We know that the symbol-pseudo use is the "src" in the instruction */
- struct instruction *insn = pu->insn;
-
- switch (insn->opcode) {
- case OP_STORE:
-#if SINGLE_STORE_SHORTCUT
- stores++;
- def = insn;
-#endif
- break;
- case OP_LOAD:
- break;
- case OP_SYMADDR:
- if (!insn->bb)
- continue;
- mod |= MOD_ADDRESSABLE;
- goto external_visibility;
- case OP_NOP:
- case OP_SNOP:
- case OP_LNOP:
- case OP_PHI:
- continue;
- default:
- dmrC_warning(C, sym->pos, "symbol '%s' pseudo used in unexpected way", dmrC_show_ident(C, sym->ident));
- }
-#if SINGLE_STORE_SHORTCUT
- complex |= insn->offset;
-#endif
- } END_FOR_EACH_PTR(pu);
-
-#if SINGLE_STORE_SHORTCUT
- if (complex)
- goto complex_def;
- if (stores > 1)
- goto multi_def;
-
- /*
- * Goodie, we have a single store (if even that) in the whole
- * thing. Replace all loads with moves from the pseudo,
- * replace the store with a def.
- */
- src = VOID_PSEUDO(C);
- if (def)
- src = def->target;
-
- //printf("simply one symbol pre convert load\n");
- //dmrC_show_entry(C, ep);
-
- FOR_EACH_PTR(pseudo->users, pu) {
- struct instruction *insn = pu->insn;
- if (insn->opcode == OP_LOAD) {
- dmrC_check_access(C, insn);
- dmrC_convert_load_instruction(C, insn, src);
- }
- } END_FOR_EACH_PTR(pu);
-
- /* Turn the store into a no-op */
- kill_store(C, def);
-
- //printf("simply one symbol post kill store\n");
- //dmrC_show_entry(C, ep);
-
- return;
-
-multi_def:
-complex_def:
-#endif
-
-external_visibility:
- all = 1;
- FOR_EACH_PTR_REVERSE(pseudo->users, pu) {
- struct instruction *insn = pu->insn;
- if (insn->opcode == OP_LOAD)
- all &= find_dominating_stores(C, pseudo, insn, ++C->L->bb_generation, !mod);
- } END_FOR_EACH_PTR_REVERSE(pu);
-
- //printf("simply one symbol post find dominating stores\n");
- //dmrC_show_entry(C, ep);
-
- /* If we converted all the loads, remove the stores. They are dead */
- if (all && !mod) {
- FOR_EACH_PTR(pseudo->users, pu) {
- struct instruction *insn = pu->insn;
- if (insn->opcode == OP_STORE)
- kill_store(C, insn);
- } END_FOR_EACH_PTR(pu);
- } else {
- /*
- * If we couldn't take the shortcut, see if we can at least kill some
- * of them..
- */
-
- FOR_EACH_PTR(pseudo->users, pu) {
- struct instruction *insn = pu->insn;
-
- //printf("simply one symbol pre kill dominated stores ins %s\n", dmrC_show_instruction(C, insn));
- //dmrC_show_entry(C, ep);
-
- if (insn->opcode == OP_STORE)
- kill_dominated_stores(C, pseudo, insn, ++C->L->bb_generation, insn->bb, !mod, 0);
- } END_FOR_EACH_PTR(pu);
-
- //printf("simply one symbol pre kill dead stores\n");
- //dmrC_show_entry(C, ep);
-
- if (!(mod & (MOD_NONLOCAL | MOD_STATIC))) {
- struct basic_block *bb;
- FOR_EACH_PTR(ep->bbs, bb) {
- if (!bb->children)
- kill_dead_stores(C, pseudo, ++C->L->bb_generation, bb, !mod);
- } END_FOR_EACH_PTR(bb);
- }
- }
-
- return;
-}
-
-void dmrC_simplify_symbol_usage(struct dmr_C *C, struct entrypoint *ep)
-{
- pseudo_t pseudo;
-
- FOR_EACH_PTR(ep->accesses, pseudo) {
- simplify_one_symbol(C, ep, pseudo->sym);
- } END_FOR_EACH_PTR(pseudo);
-}
-
-
-static int rewrite_parent_branch(struct dmr_C *C, struct basic_block *bb, struct basic_block *old, struct basic_block *new)
-{
- int changed = 0;
- struct instruction *insn = dmrC_last_instruction(bb->insns);
-
- if (!insn)
- return 0;
-
- /* Infinite loops: let's not "optimize" them.. */
- if (old == new)
- return 0;
-
- switch (insn->opcode) {
- case OP_CBR:
- changed |= rewrite_branch(C, bb, &insn->bb_false, old, new);
- /* fall through */
- case OP_BR:
- changed |= rewrite_branch(C, bb, &insn->bb_true, old, new);
- assert(changed);
- return changed;
- case OP_SWITCH: {
- struct multijmp *jmp;
- FOR_EACH_PTR(insn->multijmp_list, jmp) {
- changed |= rewrite_branch(C, bb, &jmp->target, old, new);
- } END_FOR_EACH_PTR(jmp);
- assert(changed);
- return changed;
- }
- default:
- return 0;
- }
-}
-
-static struct basic_block * rewrite_branch_bb(struct dmr_C *C, struct basic_block *bb, struct instruction *br)
-{
- struct basic_block *parent;
- struct basic_block *target = br->bb_true;
- struct basic_block *false = br->bb_false;
-
- if (br->opcode == OP_CBR) {
- pseudo_t cond = br->cond;
- if (cond->type != PSEUDO_VAL)
- return NULL;
- target = cond->value ? target : false;
- }
-
- /*
- * We can't do FOR_EACH_PTR() here, because the parent list
- * may change when we rewrite the parent.
- */
- while ((parent = dmrC_first_basic_block(bb->parents)) != NULL) {
- if (!rewrite_parent_branch(C, parent, bb, target))
- return NULL;
- }
- return target;
-}
-
-static void vrfy_bb_in_list(struct basic_block *bb, struct basic_block_list *list)
-{
- if (bb) {
- struct basic_block *tmp;
- int no_bb_in_list = 0;
-
- FOR_EACH_PTR(list, tmp) {
- if (bb == tmp)
- return;
- } END_FOR_EACH_PTR(tmp);
- assert(no_bb_in_list);
- }
-}
-
-static void vrfy_parents(struct basic_block *bb)
-{
- struct basic_block *tmp;
- FOR_EACH_PTR(bb->parents, tmp) {
- vrfy_bb_in_list(bb, tmp->children);
- } END_FOR_EACH_PTR(tmp);
-}
-
-static void vrfy_children(struct basic_block *bb)
-{
- struct basic_block *tmp;
- struct instruction *br = dmrC_last_instruction(bb->insns);
-
- if (!br) {
- assert(!bb->children);
- return;
- }
- switch (br->opcode) {
- struct multijmp *jmp;
- case OP_CBR:
- vrfy_bb_in_list(br->bb_false, bb->children);
- /* fall through */
- case OP_BR:
- vrfy_bb_in_list(br->bb_true, bb->children);
- break;
- case OP_SWITCH:
- case OP_COMPUTEDGOTO:
- FOR_EACH_PTR(br->multijmp_list, jmp) {
- vrfy_bb_in_list(jmp->target, bb->children);
- } END_FOR_EACH_PTR(jmp);
- break;
- default:
- break;
- }
-
- FOR_EACH_PTR(bb->children, tmp) {
- vrfy_bb_in_list(bb, tmp->parents);
- } END_FOR_EACH_PTR(tmp);
-}
-
-static void vrfy_bb_flow(struct basic_block *bb)
-{
- vrfy_children(bb);
- vrfy_parents(bb);
-}
-
-void dmrC_vrfy_flow(struct entrypoint *ep)
-{
- struct basic_block *bb;
- struct basic_block *entry = ep->entry->bb;
-
- FOR_EACH_PTR(ep->bbs, bb) {
- if (bb == entry)
- entry = NULL;
- vrfy_bb_flow(bb);
- } END_FOR_EACH_PTR(bb);
- assert(!entry);
-}
-
-void dmrC_pack_basic_blocks(struct dmr_C *C, struct entrypoint *ep)
-{
- struct basic_block *bb;
-
- /* See if we can merge a bb into another one.. */
- FOR_EACH_PTR(ep->bbs, bb) {
- struct instruction *first, *insn;
- struct basic_block *parent, *child, *last;
-
- if (!dmrC_bb_reachable(bb))
- continue;
-
- /*
- * Just a branch?
- */
- FOR_EACH_PTR(bb->insns, first) {
- if (!first->bb)
- continue;
- switch (first->opcode) {
- case OP_NOP: case OP_LNOP: case OP_SNOP:
- case OP_INLINED_CALL:
- continue;
- case OP_CBR:
- case OP_BR: {
- struct basic_block *replace;
- replace = rewrite_branch_bb(C, bb, first);
- if (replace) {
- dmrC_kill_bb(C, bb);
- goto no_merge;
- }
- }
- /* fallthrough */
- default:
- goto out;
- }
- } END_FOR_EACH_PTR(first);
-
-out:
- /*
- * See if we only have one parent..
- */
- last = NULL;
- FOR_EACH_PTR(bb->parents, parent) {
- if (last) {
- if (last != parent)
- goto no_merge;
- continue;
- }
- last = parent;
- } END_FOR_EACH_PTR(parent);
-
- parent = last;
- if (!parent || parent == bb)
- continue;
-
- /*
- * Goodie. See if the parent can merge..
- */
- FOR_EACH_PTR(parent->children, child) {
- if (child != bb)
- goto no_merge;
- } END_FOR_EACH_PTR(child);
-
- /*
- * Merge the two.
- */
- C->L->repeat_phase |= REPEAT_CSE;
-
- parent->children = bb->children;
- bb->children = NULL;
- bb->parents = NULL;
-
- FOR_EACH_PTR(parent->children, child) {
- dmrC_replace_bb_in_list(&child->parents, bb, parent, 0);
- } END_FOR_EACH_PTR(child);
-
- dmrC_kill_instruction(C, dmrC_delete_last_instruction(&parent->insns));
- FOR_EACH_PTR(bb->insns, insn) {
- if (insn->bb) {
- assert(insn->bb == bb);
- insn->bb = parent;
- }
- dmrC_add_instruction(C, &parent->insns, insn);
- } END_FOR_EACH_PTR(insn);
- bb->insns = NULL;
-
- no_merge:
- /* nothing to do */;
- } END_FOR_EACH_PTR(bb);
-}
-
-
diff --git a/dmr_c/src/flow.h b/dmr_c/src/flow.h
deleted file mode 100644
index 018f962..0000000
--- a/dmr_c/src/flow.h
+++ /dev/null
@@ -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
-
-#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
diff --git a/dmr_c/src/gcc-attr-list.h b/dmr_c/src/gcc-attr-list.h
deleted file mode 100644
index 9aa2980..0000000
--- a/dmr_c/src/gcc-attr-list.h
+++ /dev/null
@@ -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)
diff --git a/dmr_c/src/ident-list.h b/dmr_c/src/ident-list.h
deleted file mode 100644
index 709ffce..0000000
--- a/dmr_c/src/ident-list.h
+++ /dev/null
@@ -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
diff --git a/dmr_c/src/inline.c b/dmr_c/src/inline.c
deleted file mode 100644
index 6f8b281..0000000
--- a/dmr_c/src/inline.c
+++ /dev/null
@@ -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
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-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);
-}
diff --git a/dmr_c/src/lib.c b/dmr_c/src/lib.c
deleted file mode 100644
index f36a33c..0000000
--- a/dmr_c/src/lib.c
+++ /dev/null
@@ -1,1493 +0,0 @@
-/*
-* 'sparse' library helper routines.
-*
-* 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
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define SPARSE_VERSION "0.5"
-#ifndef __GNUC__
-# define __GNUC__ 2
-# define __GNUC_MINOR__ 95
-# define __GNUC_PATCHLEVEL__ 0
-#endif
-
-int gcc_major = __GNUC__;
-int gcc_minor = __GNUC_MINOR__;
-int gcc_patchlevel = __GNUC_PATCHLEVEL__;
-
-long double dmrC_string_to_ld(const char *nptr, char **endptr)
-{
- return strtod(nptr, endptr);
-}
-
-struct token *dmrC_skip_to_token(struct token *token, int op)
-{
- while (!dmrC_match_op(token, op) && !dmrC_eof_token(token))
- token = token->next;
- return token;
-}
-
-struct token *dmrC_expect_token(struct dmr_C *C, struct token *token, int op, const char *where)
-{
- if (!dmrC_match_op(token, op)) {
- static struct token bad_token;
- if (token != &bad_token) {
- bad_token.next = token;
- dmrC_sparse_error(C, token->pos, "Expected %s %s", dmrC_show_special(C, op), where);
- dmrC_sparse_error(C, token->pos, "got %s", dmrC_show_token(C, token));
- }
- if (op == ';')
- return dmrC_skip_to_token(token, op);
- return &bad_token;
- }
- return token->next;
-}
-
-unsigned int dmrC_hexval(unsigned int c)
-{
- int retval = 256;
- switch (c) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- retval = c - '0';
- break;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- retval = c - 'a' + 10;
- break;
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- retval = c - 'A' + 10;
- break;
- }
- return retval;
-}
-
-static void do_warn(struct dmr_C *C, const char *type, struct position pos,
- const char *fmt, va_list args)
-{
- static char buffer[512];
- const char *name;
-
- vsprintf(buffer, fmt, args);
- name = dmrC_stream_name(C, pos.stream);
-
- fprintf(stderr, "%s:%d:%d: %s%s\n", name, pos.line, pos.pos, type,
- buffer);
-}
-
-void dmrC_info(struct dmr_C *C, struct position pos, const char *fmt, ...)
-{
- va_list args;
-
- if (!C->show_info)
- return;
- va_start(args, fmt);
- do_warn(C, "", pos, fmt, args);
- va_end(args);
-}
-
-static void do_error(struct dmr_C *C, struct position pos, const char *fmt,
- va_list args)
-{
- C->die_if_error = 1;
- C->show_info = 1;
- /* Shut up warnings after an error */
- C->has_error |= ERROR_CURR_PHASE;
- C->max_warnings = 0;
- if (C->errors > 100) {
- C->show_info = 0;
- if (C->once)
- return;
- fmt = "too many errors";
- C->once = 1;
- }
-
- do_warn(C, "error: ", pos, fmt, args);
- C->errors++;
-}
-
-
-void dmrC_warning(struct dmr_C *C, struct position pos, const char *fmt, ...)
-{
- va_list args;
-
- if (C->Wsparse_error) {
- va_start(args, fmt);
- do_error(C, pos, fmt, args);
- va_end(args);
- return;
- }
- if (!C->max_warnings || C->has_error) {
- C->show_info = 0;
- return;
- }
-
- if (!--C->max_warnings) {
- C->show_info = 0;
- fmt = "too many warnings";
- }
-
- va_start(args, fmt);
- do_warn(C, "warning: ", pos, fmt, args);
- va_end(args);
-}
-
-
-void dmrC_sparse_error(struct dmr_C *C, struct position pos, const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- do_error(C, pos, fmt, args);
- va_end(args);
-}
-
-void dmrC_expression_error(struct dmr_C *C, struct expression *expr, const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- do_error(C, expr->pos, fmt, args);
- va_end(args);
- expr->ctype = &C->S->bad_ctype;
-}
-
-void dmrC_error_die(struct dmr_C *C, struct position pos, const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- do_warn(C, "error: ", pos, fmt, args);
- va_end(args);
- longjmp(C->jmpbuf, 1);
-}
-
-void dmrC_die(struct dmr_C *C, const char *fmt, ...)
-{
- va_list args;
- static char buffer[512];
-
- (void)C;
- va_start(args, fmt);
- vsnprintf(buffer, sizeof(buffer), fmt, args);
- va_end(args);
-
- fprintf(stderr, "%s\n", buffer);
- longjmp(C->jmpbuf, 1);
-}
-
-#define ARCH_LP32 0
-#define ARCH_LP64 1
-#define ARCH_LLP64 2
-
-#if _WIN32 || _WIN64
-#if _WIN64
-#define ARCH_M64_DEFAULT ARCH_LLP64
-#else
-#define ARCH_M64_DEFAULT ARCH_LP32
-#endif
-#elif __GNUC__
-#ifdef __x86_64__
-#define ARCH_M64_DEFAULT ARCH_LP64
-#else
-#define ARCH_M64_DEFAULT ARCH_LP32
-#endif
-#else
-#error Unsupported compiler
-#endif
-
-#ifdef __BIG_ENDIAN__
-#define ARCH_BIG_ENDIAN 1
-#else
-#define ARCH_BIG_ENDIAN 0
-#endif
-
-#define xstr(s) str(s)
-#define str(s) #s
-
-struct dmr_C *new_dmr_C()
-{
- struct dmr_C *C = (struct dmr_C *)calloc(1, sizeof(struct dmr_C));
- C->standard = STANDARD_GNU89;
- C->arch_m64 = ARCH_M64_DEFAULT;
- C->arch_msize_long = 0;
- C->arch_big_endian = ARCH_BIG_ENDIAN;
-#ifdef GCC_BASE
- C->gcc_base_dir = xstr(GCC_BASE);
-#else
- C->gcc_base_dir = NULL;
-#endif
-#ifdef MULTIARCH_TRIPLET
- C->multiarch_dir = xstr(MULTIARCH_TRIPLET);
-#else
- C->multiarch_dir = NULL;
-#endif
-
- C->Waddress_space = 1;
- C->Wcast_truncate = 1;
- C->Wcontext = 1;
- C->Wdecl = 1;
- C->Wdeclarationafterstatement = -1;
- C->Wdesignated_init = 1;
- C->Wenum_mismatch = 1;
- C->Wnon_pointer_null = 1;
- C->Wold_initializer = 1;
- C->Wone_bit_signed_bitfield = 1;
- C->Wuninitialized = 1;
- C->Wunknown_attribute = 1;
- C->Wvla = 1;
- C->Woverride_init = 1;
- C->Wbitwise = 1;
- C->Wmemcpy_max_count = 1;
-
- C->max_warnings = 100;
- C->show_info = 1;
- C->fmemcpy_max_count = 100000;
-
- dmrC_allocator_init(&C->ptrlist_allocator, "ptrlist_nodes", sizeof(struct ptr_list),
- __alignof__(struct ptr_list), CHUNK);
- dmrC_allocator_init(&C->byte_allocator, "bytes", sizeof(char),
- __alignof__(char), CHUNK);
- dmrC_allocator_init(&C->ident_allocator, "identifiers", sizeof(struct ident),
- __alignof__(struct ident), CHUNK);
- dmrC_allocator_init(&C->string_allocator, "strings", sizeof(struct string),
- __alignof__(struct string), CHUNK);
- dmrC_allocator_init(&C->token_allocator, "tokens", sizeof(struct token),
- __alignof__(struct token), CHUNK);
- dmrC_allocator_init(&C->scope_allocator, "scopes", sizeof(struct scope),
- __alignof__(struct scope), CHUNK);
- dmrC_allocator_init(&C->expression_allocator, "expressions", sizeof(struct expression),
- __alignof__(struct expression), CHUNK);
- dmrC_allocator_init(&C->statement_allocator, "statements", sizeof(struct statement),
- __alignof__(struct statement), CHUNK);
-
- C->warnings[0].name = "address-space"; C->warnings[0].flag = &C->Waddress_space;
- C->warnings[1].name = "bitwise"; C->warnings[1].flag = &C->Wbitwise;
- C->warnings[2].name = "cast-to-as"; C->warnings[2].flag = &C->Wcast_to_as;
- C->warnings[3].name = "cast-truncate"; C->warnings[3].flag = &C->Wcast_truncate;
- C->warnings[4].name = "context"; C->warnings[4].flag = &C->Wcontext;
- C->warnings[5].name = "decl"; C->warnings[5].flag = &C->Wdecl;
- C->warnings[6].name = "declaration-after-statement"; C->warnings[6].flag = &C->Wdeclarationafterstatement;
- C->warnings[7].name = "default-bitfield-sign"; C->warnings[7].flag = &C->Wdefault_bitfield_sign;
- C->warnings[8].name = "designated-init"; C->warnings[8].flag = &C->Wdesignated_init;
- C->warnings[9].name = "do-while"; C->warnings[9].flag = &C->Wdo_while;
- C->warnings[10].name = "enum-mismatch"; C->warnings[10].flag = &C->Wenum_mismatch;
- C->warnings[11].name = "sparse-error"; C->warnings[11].flag = &C->Wsparse_error;
- C->warnings[12].name = "init-cstring"; C->warnings[12].flag = &C->Winit_cstring;
- C->warnings[13].name = "non-pointer-null"; C->warnings[13].flag = &C->Wnon_pointer_null;
- C->warnings[14].name = "old-initializer"; C->warnings[14].flag = &C->Wold_initializer;
- C->warnings[15].name = "one-bit-signed-bitfield"; C->warnings[15].flag = &C->Wone_bit_signed_bitfield;
- C->warnings[16].name = "paren-string"; C->warnings[16].flag = &C->Wparen_string;
- C->warnings[17].name = "ptr-subtraction-blows"; C->warnings[17].flag = &C->Wptr_subtraction_blows;
- C->warnings[18].name = "return-void"; C->warnings[18].flag = &C->Wreturn_void;
- C->warnings[19].name = "shadow"; C->warnings[19].flag = &C->Wshadow;
- C->warnings[20].name = "sizeof-bool"; C->warnings[20].flag = &C->Wsizeof_bool;
- C->warnings[21].name = "tautological-compare"; C->warnings[21].flag = &C->Wtautological_compare;
- C->warnings[22].name = "transparent-union"; C->warnings[22].flag = &C->Wtransparent_union;
- C->warnings[23].name = "typesign"; C->warnings[23].flag = &C->Wtypesign;
- C->warnings[24].name = "undef"; C->warnings[24].flag = &C->Wundef;
- C->warnings[25].name = "uninitialized"; C->warnings[25].flag = &C->Wuninitialized;
- C->warnings[26].name = "unknown-attribute"; C->warnings[26].flag = &C->Wunknown_attribute;
- C->warnings[27].name = "vla"; C->warnings[27].flag = &C->Wvla;
- C->warnings[28].name = "address"; C->warnings[28].flag = &C->Waddress;
- C->warnings[29].name = "memcpy-max-count"; C->warnings[29].flag = &C->Wmemcpy_max_count;
- C->warnings[30].name = "override-init"; C->warnings[30].flag = &C->Woverride_init;
- C->warnings[31].name = "override-init-all"; C->warnings[31].flag = &C->Woverride_init_all;
-
- C->debugs[0].name = "entry"; C->debugs[0].flag = &C->dbg_entry;
- C->debugs[1].name = "dead"; C->debugs[1].flag = &C->dbg_dead;
-
- C->dumps[0].name = "D"; C->dumps[0].flag = &C->dump_macro_defs;
-
- dmrC_init_target(C);
- dmrC_init_tokenizer(C);
- dmrC_init_preprocessor_state(C);
- dmrC_init_scope(C);
- dmrC_init_symbols(C);
- dmrC_init_ctype(C);
-#if !defined(PARSER_ONLY)
- dmrC_init_linearizer(C);
-#endif
- return C;
-}
-
-void destroy_dmr_C(struct dmr_C *C)
-{
- dmrC_destroy_all_scopes(C);
- dmrC_destroy_tokenizer(C);
- dmrC_destroy_target(C);
- dmrC_destroy_symbols(C);
-#if !defined(PARSER_ONLY)
- dmrC_destroy_linearizer(C);
-#endif
- dmrC_allocator_destroy(&C->token_allocator);
- dmrC_allocator_destroy(&C->protected_token_allocator);
- dmrC_allocator_destroy(&C->string_allocator);
- dmrC_allocator_destroy(&C->ident_allocator);
- dmrC_allocator_destroy(&C->byte_allocator);
- dmrC_allocator_destroy(&C->scope_allocator);
- dmrC_allocator_destroy(&C->expression_allocator);
- dmrC_allocator_destroy(&C->statement_allocator);
- dmrC_allocator_destroy(&C->ptrlist_allocator);
- free(C);
-}
-
-void dmrC_add_pre_buffer(struct dmr_C *C, const char *fmt, ...)
-{
- va_list args;
- unsigned int size;
- struct token *begin, *end;
- char buffer[4096];
-
- va_start(args, fmt);
- size = vsnprintf(buffer, sizeof(buffer), fmt, args);
- va_end(args);
- begin = dmrC_tokenize_buffer(C, (unsigned char *)buffer, size, &end);
- if (!C->pre_buffer_begin)
- C->pre_buffer_begin = begin;
- if (C->pre_buffer_end)
- C->pre_buffer_end->next = begin;
- C->pre_buffer_end = end;
-}
-
-static char **handle_switch_D(struct dmr_C *C, char *arg, char **next)
-{
- const char *name = arg + 1;
- const char *value = "1";
-
- if (!*name || isspace((unsigned char)*name))
- dmrC_die(C, "argument to `-D' is missing");
-
- for (;;) {
- char c;
- c = *++arg;
- if (!c)
- break;
- if (isspace((unsigned char)c) || c == '=') {
- *arg = '\0';
- value = arg + 1;
- break;
- }
- }
- dmrC_add_pre_buffer(C, "#define %s %s\n", name, value);
- return next;
-}
-
-static char **handle_switch_E(struct dmr_C *C, char *arg, char **next)
-{
- if (arg[1] == '\0')
- C->preprocess_only = 1;
- return next;
-}
-
-static char **handle_switch_I(struct dmr_C *C, char *arg, char **next)
-{
- char *path = arg + 1;
-
- switch (arg[1]) {
- case '-':
- dmrC_add_pre_buffer(C, "#split_include\n");
- break;
-
- case '\0': /* Plain "-I" */
- path = *++next;
- if (!path)
- dmrC_die(C, "missing argument for -I option");
- /* Fall through */
- default:
- dmrC_add_pre_buffer(C, "#add_include \"%s/\"\n", path);
- }
- return next;
-}
-
-static void add_cmdline_include(struct dmr_C *C, char *filename)
-{
- if (C->cmdline_include_nr >= CMDLINE_INCLUDE)
- dmrC_die(C, "too many include files for %s\n", filename);
- C->cmdline_include[C->cmdline_include_nr++] = filename;
-}
-
-static char **handle_switch_i(struct dmr_C *C, char *arg, char **next)
-{
- if (*next && !strcmp(arg, "include"))
- add_cmdline_include(C, *++next);
- else if (*next && !strcmp(arg, "imacros"))
- add_cmdline_include(C, *++next);
- else if (*next && !strcmp(arg, "isystem")) {
- char *path = *++next;
- if (!path)
- dmrC_die(C, "missing argument for -isystem option");
- dmrC_add_pre_buffer(C, "#add_isystem \"%s/\"\n", path);
- }
- else if (*next && !strcmp(arg, "idirafter")) {
- char *path = *++next;
- if (!path)
- dmrC_die(C, "missing argument for -idirafter option");
- dmrC_add_pre_buffer(C, "#add_dirafter \"%s/\"\n", path);
- }
- return next;
-}
-
-static char **handle_switch_M(struct dmr_C *C, char *arg, char **next)
-{
- if (!strcmp(arg, "MF") || !strcmp(arg, "MQ") || !strcmp(arg, "MT")) {
- if (!*next)
- dmrC_die(C, "missing argument for -%s option", arg);
- return next + 1;
- }
- return next;
-}
-
-static char **handle_multiarch_dir(struct dmr_C *C, char *arg, char **next)
-{
- (void)arg;
- C->multiarch_dir = *++next;
- if (!C->multiarch_dir)
- dmrC_die(C, "missing argument for -multiarch-dir option");
- return next;
-}
-static char **handle_switch_m(struct dmr_C *C, char *arg, char **next)
-{
- if (!strcmp(arg, "m64")) {
- C->arch_m64 = ARCH_LP64;
- } else if (!strcmp(arg, "m32")) {
- C->arch_m64 = ARCH_LP32;
- } else if (!strcmp(arg, "msize-llp64")) {
- C->arch_m64 = ARCH_LLP64;
- } else if (!strcmp(arg, "msize-long")) {
- C->arch_msize_long = 1;
- } else if (!strcmp(arg, "multiarch-dir")) {
- return handle_multiarch_dir(C, arg, next);
- } else if (!strcmp(arg, "mbig-endian")) {
- C->arch_big_endian = 1;
- } else if (!strcmp(arg, "mlittle-endian")) {
- C->arch_big_endian = 0;
- }
- return next;
-}
-
-static void handle_arch_m64_finalize(struct dmr_C *C)
-{
- switch (C->arch_m64) {
- case ARCH_LP32:
- C->target->bits_in_long = 32;
- C->target->max_int_alignment = 4;
- C->target->bits_in_pointer = 32;
- C->target->pointer_alignment = 4;
- break;
- case ARCH_LP64:
- C->target->bits_in_long = 64;
- C->target->max_int_alignment = 8;
- C->target->size_t_ctype = &C->S->ulong_ctype;
- C->target->ssize_t_ctype = &C->S->long_ctype;
- dmrC_add_pre_buffer(C, "#weak_define __LP64__ 1\n");
- dmrC_add_pre_buffer(C, "#weak_define _LP64 1\n");
- goto case_64bit_common;
- case ARCH_LLP64:
- C->target->bits_in_long = 32;
- C->target->max_int_alignment = 4;
- C->target->size_t_ctype = &C->S->ullong_ctype;
- C->target->ssize_t_ctype = &C->S->llong_ctype;
- dmrC_add_pre_buffer(C, "#weak_define __LLP64__ 1\n");
- goto case_64bit_common;
- case_64bit_common:
- C->target->bits_in_pointer = 64;
- C->target->pointer_alignment = 8;
-#ifdef __x86_64__
- dmrC_add_pre_buffer(C, "#weak_define __x86_64__ 1\n");
-#endif
- break;
- }
-}
-
-static void handle_arch_msize_long_finalize(struct dmr_C *C)
-{
- if (C->arch_msize_long) {
- C->target->size_t_ctype = &C->S->ulong_ctype;
- C->target->ssize_t_ctype = &C->S->long_ctype;
- }
-}
-
-static void handle_arch_finalize(struct dmr_C *C)
-{
- handle_arch_m64_finalize(C);
- handle_arch_msize_long_finalize(C);
-}
-
-
-static int handle_simple_switch(const char *arg, const char *name, int *flag)
-{
- int val = 1;
-
- // Prefixe "no-" mean to turn flag off.
- if (strncmp(arg, "no-", 3) == 0) {
- arg += 3;
- val = 0;
- }
-
- if (strcmp(arg, name) == 0) {
- *flag = val;
- return 1;
- }
-
- // not handled
- return 0;
-}
-
-static char **handle_switch_o(struct dmr_C *C, char *arg, char **next)
-{
- if (!strcmp(arg, "o")) { // "-o foo"
- if (!*++next)
- dmrC_die(C, "argument to '-o' is missing");
- }
- snprintf(C->output_file_name, sizeof C->output_file_name, "%s", *next);
- return next;
-}
-
-
-static char **handle_onoff_switch(struct dmr_C *C, char *arg, char **next, const struct warning warnings[], int n)
-{
- int flag = WARNING_ON;
- char *p = arg + 1;
- int i;
-
- if (strcmp(p, "sparse-all") == 0) {
- for (i = 0; i < n; i++) {
- if (*warnings[i].flag != WARNING_FORCE_OFF && warnings[i].flag != &C->Wsparse_error)
- *warnings[i].flag = WARNING_ON;
- }
- }
-
- // Prefixes "no" and "no-" mean to turn warning off.
- if (p[0] == 'n' && p[1] == 'o') {
- p += 2;
- if (p[0] == '-')
- p++;
- flag = WARNING_FORCE_OFF;
- }
-
- for (i = 0; i < n; i++) {
- if (!strcmp(p, warnings[i].name)) {
- *warnings[i].flag = flag;
- return next;
- }
- }
-
- // Unknown.
- return NULL;
-}
-
-static char **handle_switch_W(struct dmr_C *C, char *arg, char **next)
-{
- char ** ret = handle_onoff_switch(C, arg, next, C->warnings, 32);
- if (ret)
- return ret;
-
- // Unknown.
- return next;
-}
-
-static char **handle_switch_v(struct dmr_C *C, char *arg, char **next)
-{
- char ** ret = handle_onoff_switch(C, arg, next, C->debugs, 2);
- if (ret)
- return ret;
-
- // Unknown.
- do {
- C->verbose++;
- } while (*++arg == 'v');
- return next;
-}
-
-static char **handle_switch_d(struct dmr_C *C, char *arg, char **next)
-{
- char ** ret = handle_onoff_switch(C, arg, next, C->dumps, 1);
- if (ret)
- return ret;
-
- return next;
-}
-
-
-static void handle_onoff_switch_finalize(const struct warning warnings[], int n)
-{
- int i;
-
- for (i = 0; i < n; i++) {
- if (*warnings[i].flag == WARNING_FORCE_OFF)
- *warnings[i].flag = WARNING_OFF;
- }
-}
-
-static void handle_switch_W_finalize(struct dmr_C *C)
-{
- handle_onoff_switch_finalize(C->warnings, 32);
-
- /* default Wdeclarationafterstatement based on the C dialect */
- if (-1 == C->Wdeclarationafterstatement)
- {
- switch (C->standard)
- {
- case STANDARD_C89:
- case STANDARD_C94:
- C->Wdeclarationafterstatement = 1;
- break;
-
- case STANDARD_C99:
- case STANDARD_GNU89:
- case STANDARD_GNU99:
- case STANDARD_C11:
- case STANDARD_GNU11:
- C->Wdeclarationafterstatement = 0;
- break;
-
- default:
- assert(0);
- }
-
- }
-}
-
-static void handle_switch_v_finalize(struct dmr_C *C)
-{
- handle_onoff_switch_finalize(C->debugs, 2);
-}
-
-static char **handle_switch_U(struct dmr_C *C, char *arg, char **next)
-{
- const char *name = arg + 1;
- dmrC_add_pre_buffer(C, "#undef %s\n", name);
- return next;
-}
-
-static char **handle_switch_O(struct dmr_C *C, char *arg, char **next)
-{
- int level = 1;
- if (arg[1] >= '0' && arg[1] <= '9')
- level = arg[1] - '0';
- C->optimize = level;
- C->optimize_size = arg[1] == 's';
- return next;
-}
-
-static char **handle_switch_fmemcpy_max_count(struct dmr_C *C, char *arg, char **next)
-{
- unsigned long long val;
- char *end;
-
- val = strtoull(arg, &end, 0);
- if (*end != '\0' || end == arg)
- dmrC_die(C, "error: missing argument to \"-fmemcpy-max-count=\"");
-
- if (val == 0)
- val = ~0ULL;
- C->fmemcpy_max_count = val;
- return next;
-}
-
-static char **handle_switch_ftabstop(struct dmr_C *C, char *arg, char **next)
-{
- char *end;
- unsigned long val;
-
- if (*arg == '\0')
- dmrC_die(C, "error: missing argument to \"-ftabstop=\"");
-
- /* we silently ignore silly values */
- val = strtoul(arg, &end, 10);
- if (*end == '\0' && 1 <= val && val <= 100)
- C->T->tabstop = val;
-
- return next;
-}
-
-static char **handle_switch_fdump(struct dmr_C *C, char *arg, char **next)
-{
- if (!strncmp(arg, "linearize", 9)) {
- arg += 9;
- if (*arg == '\0')
- C->fdump_linearize = 1;
- else if (!strcmp(arg, "=only"))
- C->fdump_linearize = 2;
- }
-
- /* ignore others flags */
- return next;
-}
-
-static char **handle_switch_f(struct dmr_C *C, char *arg, char **next)
-{
- arg++;
-
- if (!strncmp(arg, "tabstop=", 8))
- return handle_switch_ftabstop(C, arg + 8, next);
- if (!strncmp(arg, "dump-", 5))
- return handle_switch_fdump(C, arg + 5, next);
- if (!strncmp(arg, "memcpy-max-count=", 17))
- return handle_switch_fmemcpy_max_count(C, arg + 17, next);
-
- /* handle switches w/ arguments above, boolean and only boolean below */
- if (handle_simple_switch(arg, "mem-report", &C->fmem_report))
- return next;
-
- return next;
-}
-
-static char **handle_switch_G(struct dmr_C *C, char *arg, char **next)
-{
- (void) C;
- if (!strcmp(arg, "G") && *next)
- return next + 1; // "-G 0"
- else
- return next; // "-G0" or (bogus) terminal "-G"
-}
-
-static char **handle_switch_a(struct dmr_C *C, char *arg, char **next)
-{
- if (!strcmp(arg, "ansi"))
- C->standard = STANDARD_C89;
-
- return next;
-}
-
-static char **handle_switch_s(struct dmr_C *C, char *arg, char **next)
-{
- if (!strncmp(arg, "std=", 4))
- {
- arg += 4;
-
- if (!strcmp(arg, "c89") ||
- !strcmp(arg, "iso9899:1990"))
- C->standard = STANDARD_C89;
-
- else if (!strcmp(arg, "iso9899:199409"))
- C->standard = STANDARD_C94;
-
- else if (!strcmp(arg, "c99") ||
- !strcmp(arg, "c9x") ||
- !strcmp(arg, "iso9899:1999") ||
- !strcmp(arg, "iso9899:199x"))
- C->standard = STANDARD_C99;
-
- else if (!strcmp(arg, "gnu89"))
- C->standard = STANDARD_GNU89;
-
- else if (!strcmp(arg, "gnu99") || !strcmp(arg, "gnu9x"))
- C->standard = STANDARD_GNU99;
-
- else if (!strcmp(arg, "c11") ||
- !strcmp(arg, "c1x") ||
- !strcmp(arg, "iso9899:2011"))
- C->standard = STANDARD_C11;
-
- else if (!strcmp(arg, "gnu11"))
- C->standard = STANDARD_GNU11;
-
- else
- dmrC_die(C, "Unsupported C dialect");
- }
-
- return next;
-}
-
-static char **handle_nostdinc(struct dmr_C *C, char *arg, char **next)
-{
- (void)arg;
- dmrC_add_pre_buffer(C, "#nostdinc\n");
- return next;
-}
-
-static char **handle_switch_n(struct dmr_C *C, char *arg, char **next)
-{
- if (!strcmp (arg, "nostdinc"))
- return handle_nostdinc(C, arg, next);
-
- return next;
-}
-static char **handle_base_dir(struct dmr_C *C, char *arg, char **next)
-{
- (void)arg;
- C->gcc_base_dir = *++next;
- if (!C->gcc_base_dir)
- dmrC_die(C, "missing argument for -gcc-base-dir option");
- return next;
-}
-
-static char **handle_switch_g(struct dmr_C *C, char *arg, char **next)
-{
- if (!strcmp (arg, "gcc-base-dir"))
- return handle_base_dir(C, arg, next);
-
- return next;
-}
-static char **handle_version(struct dmr_C *C, char *arg, char **next)
-{
- (void)C;
- (void)arg;
- (void)next;
- printf("%s\n", SPARSE_VERSION);
- exit(0);
-}
-
-static char **handle_param(struct dmr_C *C, char *arg, char **next)
-{
- char *value = NULL;
-
- /* For now just skip any '--param=*' or '--param *' */
- if (*arg == '\0') {
- value = *++next;
- } else if (isspace((unsigned char)*arg) || *arg == '=') {
- value = ++arg;
- }
-
- if (!value)
- dmrC_die(C, "missing argument for --param option");
-
- return next;
-}
-struct switches {
- const char *name;
- char **(*fn)(struct dmr_C *, char *, char **);
- unsigned int prefix:1;
-};
-
-static char **handle_long_options(struct dmr_C *C, char *arg, char **next)
-{
- static struct switches cmd[] = {
- { "param", handle_param, 1 },
- { "version", handle_version , 0},
- { NULL, NULL, 0 }
- };
- struct switches *s = cmd;
-
- while (s->name) {
- int optlen = (int) strlen(s->name);
- if (!strncmp(s->name, arg, optlen + !s->prefix))
- return s->fn(C, arg + optlen, next);
- s++;
- }
- return next;
-
-}
-
-static char **handle_switch(struct dmr_C *C, char *arg, char **next)
-{
- switch (*arg) {
- case 'a': return handle_switch_a(C, arg, next);
- case 'D': return handle_switch_D(C, arg, next);
- case 'd': return handle_switch_d(C, arg, next);
- case 'E': return handle_switch_E(C, arg, next);
- case 'f': return handle_switch_f(C, arg, next);
- case 'g': return handle_switch_g(C, arg, next);
- case 'G': return handle_switch_G(C, arg, next);
- case 'I': return handle_switch_I(C, arg, next);
- case 'i': return handle_switch_i(C, arg, next);
- case 'M': return handle_switch_M(C, arg, next);
- case 'm': return handle_switch_m(C, arg, next);
- case 'n': return handle_switch_n(C, arg, next);
- case 'o': return handle_switch_o(C, arg, next);
- case 'O': return handle_switch_O(C, arg, next);
- case 's': return handle_switch_s(C, arg, next);
- case 'U': return handle_switch_U(C, arg, next);
- case 'v': return handle_switch_v(C, arg, next);
- case 'W': return handle_switch_W(C, arg, next);
- case '-': return handle_long_options(C, arg + 1, next);
-
- default:
- break;
- }
-
- /*
- * Ignore unknown command line options:
- * they're probably gcc switches
- */
- return next;
-}
-
-static void predefined_sizeof(struct dmr_C *C, const char *name, unsigned bits)
-{
- dmrC_add_pre_buffer(C, "#weak_define __SIZEOF_%s__ %d\n", name, bits/8);
-}
-
-static void predefined_max(struct dmr_C *C, const char *name, const char *suffix, unsigned bits)
-{
- unsigned long long max = (1ULL << (bits - 1)) - 1;
-
- dmrC_add_pre_buffer(C, "#weak_define __%s_MAX__ %#llx%s\n", name, max, suffix);
-}
-
-static void predefined_type_size(struct dmr_C *C, const char *name, const char *suffix, unsigned bits)
-{
- predefined_max(C, name, suffix, bits);
-
- predefined_sizeof(C, name, bits);
-}
-
-static void predefined_macros(struct dmr_C *C)
-{
-#if LLVM_JIT
- dmrC_add_pre_buffer(C, "#define __LLVM_BACKEND__ 1\n");
-#elif NANO_JIT
- dmrC_add_pre_buffer(C, "#define __NANOJIT_BACKEND__ 1\n");
-#elif OMR_JIT
- dmrC_add_pre_buffer(C, "#define __OMR_BACKEND__ 1\n");
-#endif
- dmrC_add_pre_buffer(C, "#define __CHECKER__ 1\n");
-
- predefined_sizeof(C, "SHORT", C->target->bits_in_short);
- predefined_max(C, "SHRT", "", C->target->bits_in_short);
- predefined_max(C, "SCHAR", "", C->target->bits_in_char);
- predefined_max(C, "WCHAR", "", C->target->bits_in_wchar);
- dmrC_add_pre_buffer(C, "#weak_define __CHAR_BIT__ %d\n", C->target->bits_in_char);
-
- predefined_type_size(C, "INT", "", C->target->bits_in_int);
- predefined_type_size(C, "LONG", "L", C->target->bits_in_long);
- predefined_type_size(C, "LONG_LONG", "LL", C->target->bits_in_longlong);
-
- predefined_sizeof(C, "INT128", 128);
-
- predefined_sizeof(C, "SIZE_T", C->target->bits_in_pointer);
- predefined_sizeof(C, "PTRDIFF_T", C->target->bits_in_pointer);
- predefined_sizeof(C, "POINTER", C->target->bits_in_pointer);
-
- predefined_sizeof(C, "FLOAT", C->target->bits_in_float);
- predefined_sizeof(C, "DOUBLE", C->target->bits_in_double);
- predefined_sizeof(C, "LONG_DOUBLE", C->target->bits_in_longdouble);
- dmrC_add_pre_buffer(C, "#weak_define __%s_ENDIAN__ 1\n",
- C->arch_big_endian ? "BIG" : "LITTLE");
-
- dmrC_add_pre_buffer(C, "#weak_define __ORDER_LITTLE_ENDIAN__ 1234\n");
- dmrC_add_pre_buffer(C, "#weak_define __ORDER_BIG_ENDIAN__ 4321\n");
- dmrC_add_pre_buffer(C, "#weak_define __ORDER_PDP_ENDIAN__ 3412\n");
- dmrC_add_pre_buffer(C, "#weak_define __BYTE_ORDER__ __ORDER_%s_ENDIAN__\n",
- C->arch_big_endian ? "BIG" : "LITTLE");
-}
-
-void dmrC_declare_builtin_functions(struct dmr_C *C)
-{
- /* Gaah. gcc knows tons of builtin functions */
- dmrC_add_pre_buffer(C, "extern void *__builtin_memchr(const void *, int, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_memcpy(void *, const void *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_mempcpy(void *, const void *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_memmove(void *, const void *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_memset(void *, int, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_memcmp(const void *, const void *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strcat(char *, const char *);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strncat(char *, const char *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_strcmp(const char *, const char *);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_strncmp(const char *, const char *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_strcasecmp(const char *, const char *);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_strncasecmp(const char *, const char *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strchr(const char *, int);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strrchr(const char *, int);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strcpy(char *, const char *);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strncpy(char *, const char *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strdup(const char *);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strndup(const char *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern __SIZE_TYPE__ __builtin_strspn(const char *, const char *);\n");
- dmrC_add_pre_buffer(C, "extern __SIZE_TYPE__ __builtin_strcspn(const char *, const char *);\n");
- dmrC_add_pre_buffer(C, "extern char * __builtin_strpbrk(const char *, const char *);\n");
- dmrC_add_pre_buffer(C, "extern char* __builtin_stpcpy(const char *, const char*);\n");
- dmrC_add_pre_buffer(C, "extern char* __builtin_stpncpy(const char *, const char*, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern __SIZE_TYPE__ __builtin_strlen(const char *);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strstr(const char *, const char *);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strcasestr(const char *, const char *);\n");
- dmrC_add_pre_buffer(C, "extern char *__builtin_strnstr(const char *, const char *, __SIZE_TYPE__);\n");
-
- /* And even some from */
- dmrC_add_pre_buffer(C, "extern int __builtin_bcmp(const void *, const void *, __SIZE_TYPE_);\n");
- dmrC_add_pre_buffer(C, "extern void __builtin_bcopy(const void *, void *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void __builtin_bzero(void *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern char*__builtin_index(const char *, int);\n");
- dmrC_add_pre_buffer(C, "extern char*__builtin_rindex(const char *, int);\n");
-
- /* And bitwise operations.. */
- dmrC_add_pre_buffer(C, "extern int __builtin_clrsb(int);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_clrsbl(long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_clrsbll(long long);\n");
-
- /* And bitwise operations.. */
- dmrC_add_pre_buffer(C, "extern int __builtin_clz(int);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_clzl(long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_clzll(long long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_ctz(int);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_ctzl(long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_ctzll(long long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_ffs(int);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_ffsl(long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_ffsll(long long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_parity(unsigned int);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_parityl(unsigned long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_parityll(unsigned long long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_popcount(unsigned int);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_popcountl(unsigned long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_popcountll(unsigned long long);\n");
-
- /* And byte swaps.. */
- dmrC_add_pre_buffer(C, "extern unsigned short __builtin_bswap16(unsigned short);\n");
- dmrC_add_pre_buffer(C, "extern unsigned int __builtin_bswap32(unsigned int);\n");
- dmrC_add_pre_buffer(C, "extern unsigned long long __builtin_bswap64(unsigned long long);\n");
-
- /* And atomic memory access functions.. */
- dmrC_add_pre_buffer(C, "extern int __sync_fetch_and_add(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_fetch_and_sub(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_fetch_and_or(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_fetch_and_and(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_fetch_and_xor(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_fetch_and_nand(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_add_and_fetch(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_sub_and_fetch(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_or_and_fetch(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_and_and_fetch(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_xor_and_fetch(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_nand_and_fetch(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_bool_compare_and_swap(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __sync_val_compare_and_swap(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern void __sync_synchronize();\n");
- dmrC_add_pre_buffer(C, "extern int __sync_lock_test_and_set(void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern void __sync_lock_release(void *, ...);\n");
-
- /* And some random ones.. */
- dmrC_add_pre_buffer(C, "extern void *__builtin_return_address(unsigned int);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_extract_return_addr(void *);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_frame_address(unsigned int);\n");
- dmrC_add_pre_buffer(C, "extern void __builtin_trap(void);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_alloca(__SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void __builtin_prefetch (const void *, ...);\n");
- dmrC_add_pre_buffer(C, "extern long __builtin_alpha_extbl(long, long);\n");
- dmrC_add_pre_buffer(C, "extern long __builtin_alpha_extwl(long, long);\n");
- dmrC_add_pre_buffer(C, "extern long __builtin_alpha_insbl(long, long);\n");
- dmrC_add_pre_buffer(C, "extern long __builtin_alpha_inswl(long, long);\n");
- dmrC_add_pre_buffer(C, "extern long __builtin_alpha_insql(long, long);\n");
- dmrC_add_pre_buffer(C, "extern long __builtin_alpha_inslh(long, long);\n");
- dmrC_add_pre_buffer(C, "extern long __builtin_alpha_cmpbge(long, long);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_abs(int);\n");
- dmrC_add_pre_buffer(C, "extern long __builtin_labs(long);\n");
- dmrC_add_pre_buffer(C, "extern long long __builtin_llabs(long long);\n");
- dmrC_add_pre_buffer(C, "extern double __builtin_fabs(double);\n");
- dmrC_add_pre_buffer(C, "extern __SIZE_TYPE__ __builtin_va_arg_pack_len(void);\n");
-
- /* Add Blackfin-specific stuff */
- dmrC_add_pre_buffer(C,
- "#ifdef __bfin__\n"
- "extern void __builtin_bfin_csync(void);\n"
- "extern void __builtin_bfin_ssync(void);\n"
- "extern int __builtin_bfin_norm_fr1x32(int);\n"
- "#endif\n"
- );
-
- /* And some floating point stuff.. */
- dmrC_add_pre_buffer(C, "extern int __builtin_isgreater(float, float);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_isgreaterequal(float, float);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_isless(float, float);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_islessequal(float, float);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_islessgreater(float, float);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_isunordered(float, float);\n");
-
- /* And some INFINITY / NAN stuff.. */
- dmrC_add_pre_buffer(C, "extern double __builtin_huge_val(void);\n");
- dmrC_add_pre_buffer(C, "extern float __builtin_huge_valf(void);\n");
- dmrC_add_pre_buffer(C, "extern long double __builtin_huge_vall(void);\n");
- dmrC_add_pre_buffer(C, "extern double __builtin_inf(void);\n");
- dmrC_add_pre_buffer(C, "extern float __builtin_inff(void);\n");
- dmrC_add_pre_buffer(C, "extern long double __builtin_infl(void);\n");
- dmrC_add_pre_buffer(C, "extern double __builtin_nan(const char *);\n");
- dmrC_add_pre_buffer(C, "extern float __builtin_nanf(const char *);\n");
- dmrC_add_pre_buffer(C, "extern long double __builtin_nanl(const char *);\n");
-
- /* And some __FORTIFY_SOURCE ones.. */
- dmrC_add_pre_buffer(C, "extern __SIZE_TYPE__ __builtin_object_size(void *, int);\n");
- dmrC_add_pre_buffer(C, "extern void * __builtin___memcpy_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void * __builtin___memmove_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void * __builtin___mempcpy_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void * __builtin___memset_chk(void *, int, __SIZE_TYPE__, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin___sprintf_chk(char *, int, __SIZE_TYPE__, const char *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin___snprintf_chk(char *, __SIZE_TYPE__, int , __SIZE_TYPE__, const char *, ...);\n");
- dmrC_add_pre_buffer(C, "extern char * __builtin___stpcpy_chk(char *, const char *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern char * __builtin___strcat_chk(char *, const char *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern char * __builtin___strcpy_chk(char *, const char *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern char * __builtin___strncat_chk(char *, const char *, __SIZE_TYPE__, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern char * __builtin___strncpy_chk(char *, const char *, __SIZE_TYPE__, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin___vsprintf_chk(char *, int, __SIZE_TYPE__, const char *, __builtin_va_list);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin___vsnprintf_chk(char *, __SIZE_TYPE__, int, __SIZE_TYPE__, const char *, __builtin_va_list ap);\n");
- dmrC_add_pre_buffer(C, "extern void __builtin_unreachable(void);\n");
-
- /* And some from */
- dmrC_add_pre_buffer(C, "extern void __builtin_abort(void);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_calloc(__SIZE_TYPE__, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void __builtin_exit(int);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_malloc(__SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void *__builtin_realloc(void *, __SIZE_TYPE__);\n");
- dmrC_add_pre_buffer(C, "extern void __builtin_free(void *);\n");
-
- /* And some from */
- dmrC_add_pre_buffer(C, "extern int __builtin_printf(const char *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_sprintf(char *, const char *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_snprintf(char *, __SIZE_TYPE__, const char *, ...);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_puts(const char *);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_vprintf(const char *, __builtin_va_list);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_vsprintf(char *, const char *, __builtin_va_list);\n");
- dmrC_add_pre_buffer(C, "extern int __builtin_vsnprintf(char *, __SIZE_TYPE__, const char *, __builtin_va_list ap);\n");
-}
-
-void dmrC_create_builtin_stream(struct dmr_C *C)
-{
- dmrC_add_pre_buffer(C, "#define __DMR_C__ 1\n");
-
- dmrC_add_pre_buffer(C, "#weak_define __GNUC__ %d\n", gcc_major);
- dmrC_add_pre_buffer(C, "#weak_define __GNUC_MINOR__ %d\n", gcc_minor);
- dmrC_add_pre_buffer(C, "#weak_define __GNUC_PATCHLEVEL__ %d\n", gcc_patchlevel);
-
- /* add the multiarch include directories, if any */
- if (C->multiarch_dir && *C->multiarch_dir) {
- dmrC_add_pre_buffer(C, "#add_system \"/usr/include/%s\"\n", C->multiarch_dir);
- dmrC_add_pre_buffer(C, "#add_system \"/usr/local/include/%s\"\n", C->multiarch_dir);
- }
-
- /* We add compiler headers path here because we have to parse
- * the arguments to get it, falling back to default. */
- if (C->gcc_base_dir && *C->gcc_base_dir) {
- dmrC_add_pre_buffer(C, "#add_system \"%s/include\"\n", C->gcc_base_dir);
- dmrC_add_pre_buffer(C, "#add_system \"%s/include-fixed\"\n", C->gcc_base_dir);
- }
-
- dmrC_add_pre_buffer(C, "#define __extension__\n");
- dmrC_add_pre_buffer(C, "#define __pragma__\n");
- dmrC_add_pre_buffer(C, "#define _Pragma(x)\n");
-
-
- // gcc defines __SIZE_TYPE__ to be size_t. For linux/i86 and
- // solaris/sparc that is really "unsigned int" and for linux/x86_64
- // it is "long unsigned int". In either case we can probably
- // get away with this. We need the #weak_define as cgcc will define
- // the right __SIZE_TYPE__.
- if (C->target->size_t_ctype == &C->S->ullong_ctype)
- dmrC_add_pre_buffer(C, "#weak_define __SIZE_TYPE__ unsigned long long int\n");
- else if (C->target->size_t_ctype == &C->S->ulong_ctype)
- dmrC_add_pre_buffer(C, "#weak_define __SIZE_TYPE__ unsigned long int\n");
- else
- dmrC_add_pre_buffer(C, "#weak_define __SIZE_TYPE__ unsigned int\n");
- dmrC_add_pre_buffer(C, "#weak_define __STDC__ 1\n");
-
- switch (C->standard)
- {
- case STANDARD_C89:
- dmrC_add_pre_buffer(C, "#weak_define __STRICT_ANSI__\n");
- break;
-
- case STANDARD_C94:
- dmrC_add_pre_buffer(C, "#weak_define __STDC_VERSION__ 199409L\n");
- dmrC_add_pre_buffer(C, "#weak_define __STRICT_ANSI__\n");
- break;
-
- case STANDARD_C99:
- dmrC_add_pre_buffer(C, "#weak_define __STDC_VERSION__ 199901L\n");
- dmrC_add_pre_buffer(C, "#weak_define __STRICT_ANSI__\n");
- break;
-
- case STANDARD_GNU89:
- break;
-
- case STANDARD_GNU99:
- dmrC_add_pre_buffer(C, "#weak_define __STDC_VERSION__ 199901L\n");
- break;
-
- case STANDARD_C11:
- dmrC_add_pre_buffer(C, "#weak_define __STRICT_ANSI__ 1\n");
-
- case STANDARD_GNU11:
- dmrC_add_pre_buffer(C, "#weak_define __STDC_NO_ATOMICS__ 1\n");
- dmrC_add_pre_buffer(C, "#weak_define __STDC_NO_COMPLEX__ 1\n");
- dmrC_add_pre_buffer(C, "#weak_define __STDC_NO_THREADS__ 1\n");
- dmrC_add_pre_buffer(C, "#weak_define __STDC_VERSION__ 201112L\n");
- break;
-
- default:
- assert(0);
- }
-
- if (!C->codegen) {
- /* Do not output these macros when we are generating code e.g. via LLVM as these macros are not correct */
- dmrC_add_pre_buffer(C, "#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
- dmrC_add_pre_buffer(C, "#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
- dmrC_add_pre_buffer(C, "#define __builtin_ms_va_start(a,b) ((a) = (__builtin_ms_va_list)(&(b)))\n");
- dmrC_add_pre_buffer(C, "#define __builtin_va_arg(arg,type) ({ type __va_arg_ret = *(type *)(arg); arg += sizeof(type); __va_arg_ret; })\n");
- dmrC_add_pre_buffer(C, "#define __builtin_va_alist (*(void *)0)\n");
- dmrC_add_pre_buffer(C, "#define __builtin_va_arg_incr(x) ((x) + 1)\n");
- dmrC_add_pre_buffer(C, "#define __builtin_va_copy(dest, src) ({ dest = src; (void)0; })\n");
- dmrC_add_pre_buffer(C, "#define __builtin_ms_va_copy(dest, src) ({ dest = src; (void)0; })\n");
- dmrC_add_pre_buffer(C, "#define __builtin_va_end(arg)\n");
- dmrC_add_pre_buffer(C, "#define __builtin_ms_va_end(arg)\n");
- dmrC_add_pre_buffer(C, "#define __builtin_va_arg_pack()\n");
- }
-
- /* FIXME! We need to do these as special magic macros at expansion time! */
- dmrC_add_pre_buffer(C, "#define __BASE_FILE__ \"base_file.c\"\n");
-
- if (C->optimize)
- dmrC_add_pre_buffer(C, "#define __OPTIMIZE__ 1\n");
- if (C->optimize_size)
- dmrC_add_pre_buffer(C, "#define __OPTIMIZE_SIZE__ 1\n");
-
-}
-
-static struct symbol_list *sparse_tokenstream(struct dmr_C *C, struct token *token)
-{
- int builtin = token && !token->pos.stream;
-
- // Preprocess the stream
- token = dmrC_preprocess(C, token);
- if (C->die_if_error)
- return NULL;
-
- if (C->dump_macro_defs && !builtin)
- dmrC_dump_macro_definitions(C);
-
- if (C->preprocess_only) {
- while (!dmrC_eof_token(token)) {
- int prec = 1;
- struct token *next = token->next;
- const char *separator = "";
- if (next->pos.whitespace)
- separator = " ";
- if (next->pos.newline) {
- separator = "\n\t\t\t\t\t";
- prec = next->pos.pos;
- if (prec > 4)
- prec = 4;
- }
- printf("%s%.*s", dmrC_show_token(C, token), prec, separator);
- token = next;
- }
- putchar('\n');
-
- return NULL;
- }
-
- // Parse the resulting C code
- while (!dmrC_eof_token(token))
- token = dmrC_external_declaration(C, token, &C->S->translation_unit_used_list, NULL);
- return C->S->translation_unit_used_list;
-}
-
-static struct symbol_list *sparse_file(struct dmr_C *C, const char *filename)
-{
- int fd;
- struct token *token;
-
- if (strcmp(filename, "-") == 0) {
- fd = 0;
- } else {
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- dmrC_die(C, "No such file: %s", filename);
- }
-
- // Tokenize the input stream
- token = dmrC_tokenize(C, filename, fd, NULL, C->T->includepath);
- close(fd);
-
- return sparse_tokenstream(C, token);
-}
-
-/*
-* This handles the "-include" directive etc: we're in global
-* scope, and all types/macros etc will affect all the following
-* files.
-*
-* NOTE NOTE NOTE! "#undef" of anything in this stage will
-* affect all subsequent files too, i.e. we can have non-local
-* behaviour between files!
-*/
-static struct symbol_list *sparse_initial(struct dmr_C *C)
-{
- int i;
-
- // Prepend any "include" file to the stream.
- // We're in global scope, it will affect all files!
- for (i = 0; i < C->cmdline_include_nr; i++)
- dmrC_add_pre_buffer(C, "#argv_include \"%s\"\n", C->cmdline_include[i]);
-
- return sparse_tokenstream(C, C->pre_buffer_begin);
-}
-
-static void protect_token_alloc(struct dmr_C *C) {
- /* prevent tokens from being deallocated ? */
- dmrC_allocator_transfer(&C->token_allocator, &C->protected_token_allocator);
-}
-
-static void clear_token_alloc(struct dmr_C *C) {
- /* prevent tokens from being deallocated ? */
- dmrC_allocator_drop_all_allocations(&C->token_allocator);
-}
-
-struct symbol_list *dmrC_sparse_initialize(struct dmr_C *C, int argc, char **argv, struct string_list **filelist)
-{
- char **args;
- struct symbol_list *list;
-
- args = argv;
- for (; args < argv + argc;) {
- char *arg = *++args;
- if (!arg)
- break;
-
- if (arg[0] == '-' && arg[1]) {
- args = handle_switch(C, arg + 1, args);
- continue;
- }
- ptrlist_add((struct ptr_list **)filelist, arg, &C->ptrlist_allocator);
- }
- handle_switch_W_finalize(C);
- handle_switch_v_finalize(C);
-
- handle_arch_finalize(C);
-
- list = NULL;
- //if (!ptr_list_empty(filelist)) {
-
- dmrC_create_builtin_stream(C);
- predefined_macros(C);
- if (!C->preprocess_only)
- dmrC_declare_builtin_functions(C);
-
- list = sparse_initial(C);
-
- /*
- * Protect the initial token allocations, since
- * they need to survive all the others
- */
- protect_token_alloc(C);
- //}
- return list;
-}
-
-struct symbol_list * dmrC_sparse_keep_tokens(struct dmr_C *C, char *filename)
-{
- struct symbol_list *res;
-
- /* Clear previous symbol list */
- C->S->translation_unit_used_list = NULL;
-
- dmrC_new_file_scope(C);
- res = sparse_file(C, filename);
-
- /* And return it */
- return res;
-}
-
-
-struct symbol_list * dmrC__sparse(struct dmr_C *C, char *filename)
-{
- struct symbol_list *res;
-
- res = dmrC_sparse_keep_tokens(C, filename);
-
- /* Drop the tokens for this file after parsing */
- clear_token_alloc(C);
-
- /* And return it */
- return res;
-}
-
-struct symbol_list * dmrC_sparse(struct dmr_C *C, char *filename)
-{
- struct symbol_list *res = dmrC__sparse(C, filename);
-
- if (C->has_error & ERROR_CURR_PHASE)
- C->has_error = ERROR_PREV_PHASE;
-
- /* Evaluate the complete symbol list */
- if (res)
- dmrC_evaluate_symbol_list(C, res);
-
- return res;
-}
-
-struct symbol_list *dmrC_sparse_buffer(struct dmr_C *C, const char *name, char *buffer, int keep_tokens)
-{
- struct symbol_list *res;
-
- /* Clear previous symbol list */
- C->S->translation_unit_used_list = NULL;
- dmrC_new_file_scope(C);
-
- struct token *start;
- struct token *end;
- start = dmrC_tokenize_buffer_stream(C, name, (unsigned char *)buffer,
- (unsigned long)strlen(buffer), &end);
-
- res = sparse_tokenstream(C, start);
-
- if (!keep_tokens) {
- /* Drop the tokens for this file after parsing */
- clear_token_alloc(C);
- }
-
- /* Evaluate the complete symbol list */
- if (res)
- dmrC_evaluate_symbol_list(C, res);
-
- /* And return it */
- return res;
-}
diff --git a/dmr_c/src/lib.h b/dmr_c/src/lib.h
deleted file mode 100644
index 5db8948..0000000
--- a/dmr_c/src/lib.h
+++ /dev/null
@@ -1,302 +0,0 @@
-#ifndef DMR_LIB_H
-#define DMR_LIB_H
-
-/* This file is derived from lib.h in sparse */
-
-#include
-#include
-#include
-#include
-
-/*
-* 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
-#include
-
-#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
diff --git a/dmr_c/src/linearize.c b/dmr_c/src/linearize.c
deleted file mode 100644
index a5c96d3..0000000
--- a/dmr_c/src/linearize.c
+++ /dev/null
@@ -1,2741 +0,0 @@
-/*
- * 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
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#if 0
-#include
-#endif
-#include
-
-static pseudo_t linearize_statement(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt);
-static pseudo_t linearize_expression(struct dmr_C *C, struct entrypoint *ep, struct expression *expr);
-
-static pseudo_t add_binary_op(struct dmr_C *C, struct entrypoint *ep, struct symbol *ctype, int op, pseudo_t left, pseudo_t right);
-static pseudo_t add_setval(struct dmr_C *C, struct entrypoint *ep, struct symbol *ctype, struct expression *val);
-static pseudo_t linearize_one_symbol(struct dmr_C *C, struct entrypoint *ep, struct symbol *sym);
-
-struct access_data;
-static pseudo_t add_load(struct dmr_C *C, struct entrypoint *ep, struct access_data *);
-static pseudo_t linearize_initializer(struct dmr_C *C, struct entrypoint *ep, struct expression *initializer, struct access_data *);
-static pseudo_t cast_pseudo(struct dmr_C *C, struct entrypoint *ep, pseudo_t src, struct symbol *from, struct symbol *to);
-
-
-static struct instruction *alloc_instruction(struct dmr_C *C, int opcode, int size)
-{
- struct instruction * insn = (struct instruction *) dmrC_allocator_allocate(&C->L->instruction_allocator, 0);
- insn->opcode = opcode;
- insn->size = size;
- insn->pos = C->L->current_pos;
- return insn;
-}
-
-static inline int type_size(struct symbol *type)
-{
- return type ? type->bit_size > 0 ? type->bit_size : 0 : 0;
-}
-
-static struct instruction *alloc_typed_instruction(struct dmr_C *C, int opcode, struct symbol *type)
-{
- struct instruction *insn = alloc_instruction(C, opcode, type_size(type));
- insn->type = type;
- return insn;
-}
-
-static struct entrypoint *alloc_entrypoint(struct dmr_C *C)
-{
- return (struct entrypoint *) dmrC_allocator_allocate(&C->L->entrypoint_allocator, 0);
-}
-
-static struct basic_block *alloc_basic_block(struct dmr_C *C, struct entrypoint *ep, struct position pos)
-{
- struct basic_block *bb = (struct basic_block *) dmrC_allocator_allocate(&C->L->basic_block_allocator, 0);
- bb->context = -1;
- bb->pos = pos;
- bb->ep = ep;
- bb->nr = C->L->bb_nr++;
- return bb;
-}
-
-static struct multijmp *alloc_multijmp(struct dmr_C *C, struct basic_block *target, long long begin, long long end)
-{
- struct multijmp *multijmp = (struct multijmp *)dmrC_allocator_allocate(&C->L->multijmp_allocator, 0);
- multijmp->target = target;
- multijmp->begin = begin;
- multijmp->end = end;
- return multijmp;
-}
-
-#if 0
-static inline int regno(pseudo_t n)
-{
- int retval = -1;
- if (n && n->type == PSEUDO_REG)
- retval = n->nr;
- return retval;
-}
-#endif
-
-const char *dmrC_show_pseudo(struct dmr_C *C, pseudo_t pseudo)
-{
- char *buf;
- int i;
-
- if (!pseudo)
- return "no pseudo";
- if (pseudo == VOID_PSEUDO(C))
- return "VOID";
- buf = C->L->pseudo_buffer[3 & ++C->L->n];
- switch(pseudo->type) {
- case PSEUDO_SYM: {
- struct symbol *sym = pseudo->sym;
- struct expression *expr;
-
- if (sym->bb_target) {
- snprintf(buf, 64, ".L%u", sym->bb_target->nr);
- break;
- }
- if (sym->ident) {
- snprintf(buf, 64, "%s", dmrC_show_ident(C, sym->ident));
- break;
- }
- expr = sym->initializer;
- snprintf(buf, 64, "", sym);
- if (expr) {
- switch (expr->type) {
- case EXPR_VALUE:
- snprintf(buf, 64, "", expr->value);
- break;
- case EXPR_STRING:
- return dmrC_show_string(C, expr->string);
- default:
- break;
- }
- }
- break;
- }
- case PSEUDO_REG:
- i = snprintf(buf, 64, "%%r%d", pseudo->nr);
- if (pseudo->ident)
- sprintf(buf+i, "(%s)", dmrC_show_ident(C, pseudo->ident));
- break;
- case PSEUDO_VAL: {
- long long value = pseudo->value;
- if (value > 1000 || value < -1000)
- snprintf(buf, 64, "$%#llx", value);
- else
- snprintf(buf, 64, "$%lld", value);
- break;
- }
- case PSEUDO_ARG:
- snprintf(buf, 64, "%%arg%d", pseudo->nr);
- break;
- case PSEUDO_PHI:
- i = snprintf(buf, 64, "%%phi%d", pseudo->nr);
- if (pseudo->ident)
- sprintf(buf+i, "(%s)", dmrC_show_ident(C, pseudo->ident));
- break;
- default:
- snprintf(buf, 64, "", pseudo->type);
- }
- return buf;
-}
-
-static const char *opcodes[] = {
- [OP_BADOP] = "bad_op",
-
- /* Fn entrypoint */
- [OP_ENTRY] = "",
-
- /* Terminator */
- [OP_RET] = "ret",
- [OP_BR] = "br",
- [OP_CBR] = "cbr",
- [OP_SWITCH] = "switch",
- [OP_INVOKE] = "invoke",
- [OP_COMPUTEDGOTO] = "jmp *",
- [OP_UNWIND] = "unwind",
-
- /* Binary */
- [OP_ADD] = "add",
- [OP_SUB] = "sub",
- [OP_MULU] = "mulu",
- [OP_MULS] = "muls",
- [OP_DIVU] = "divu",
- [OP_DIVS] = "divs",
- [OP_MODU] = "modu",
- [OP_MODS] = "mods",
- [OP_SHL] = "shl",
- [OP_LSR] = "lsr",
- [OP_ASR] = "asr",
-
- /* Logical */
- [OP_AND] = "and",
- [OP_OR] = "or",
- [OP_XOR] = "xor",
- [OP_AND_BOOL] = "and-bool",
- [OP_OR_BOOL] = "or-bool",
-
- /* Binary comparison */
- [OP_SET_EQ] = "seteq",
- [OP_SET_NE] = "setne",
- [OP_SET_LE] = "setle",
- [OP_SET_GE] = "setge",
- [OP_SET_LT] = "setlt",
- [OP_SET_GT] = "setgt",
- [OP_SET_B] = "setb",
- [OP_SET_A] = "seta",
- [OP_SET_BE] = "setbe",
- [OP_SET_AE] = "setae",
-
- /* Uni */
- [OP_NOT] = "not",
- [OP_NEG] = "neg",
-
- /* Special three-input */
- [OP_SEL] = "select",
-
- /* Memory */
- [OP_MALLOC] = "malloc",
- [OP_FREE] = "free",
- [OP_ALLOCA] = "alloca",
- [OP_LOAD] = "load",
- [OP_STORE] = "store",
- [OP_SETVAL] = "set",
- [OP_SYMADDR] = "symaddr",
- [OP_GET_ELEMENT_PTR] = "getelem",
-
- /* Other */
- [OP_PHI] = "phi",
- [OP_PHISOURCE] = "phisrc",
- [OP_CAST] = "cast",
- [OP_SCAST] = "scast",
- [OP_FPCAST] = "fpcast",
- [OP_PTRCAST] = "ptrcast",
- [OP_INLINED_CALL] = "# call",
- [OP_CALL] = "call",
- [OP_VANEXT] = "va_next",
- [OP_VAARG] = "va_arg",
- [OP_SLICE] = "slice",
- [OP_SNOP] = "snop",
- [OP_LNOP] = "lnop",
- [OP_NOP] = "nop",
- [OP_DEATHNOTE] = "dead",
- [OP_ASM] = "asm",
-
- /* Sparse tagging (line numbers, context, whatever) */
- [OP_CONTEXT] = "context",
- [OP_RANGE] = "range-check",
-
- [OP_COPY] = "copy",
-};
-
-static char *show_asm_constraints(struct dmr_C *C, char *buf, const char *sep, struct asm_constraint_list *list)
-{
- struct asm_constraint *entry;
-
- FOR_EACH_PTR(list, entry) {
- buf += sprintf(buf, "%s\"%s\"", sep, entry->constraint);
- if (entry->pseudo)
- buf += sprintf(buf, " (%s)", dmrC_show_pseudo(C, entry->pseudo));
- if (entry->ident)
- buf += sprintf(buf, " [%s]", dmrC_show_ident(C, entry->ident));
- sep = ", ";
- } END_FOR_EACH_PTR(entry);
- return buf;
-}
-
-static char *show_asm(struct dmr_C *C, char *buf, struct instruction *insn)
-{
- struct asm_rules *rules = insn->asm_rules;
-
- buf += sprintf(buf, "\"%s\"", insn->string);
- buf = show_asm_constraints(C, buf, "\n\t\tout: ", rules->outputs);
- buf = show_asm_constraints(C, buf, "\n\t\tin: ", rules->inputs);
- buf = show_asm_constraints(C, buf, "\n\t\tclobber: ", rules->clobbers);
- return buf;
-}
-
-const char *dmrC_show_instruction(struct dmr_C *C, struct instruction *insn)
-{
- int opcode = insn->opcode;
- char *buf;
-
- buf = C->L->buffer;
- if (!insn->bb)
- buf += sprintf(buf, "# ");
-
- if (opcode < (int)ARRAY_SIZE(opcodes)) {
- const char *op = opcodes[opcode];
- if (!op)
- buf += sprintf(buf, "opcode:%d", opcode);
- else
- buf += sprintf(buf, "%s", op);
- if (insn->type && dmrC_is_float_type(C->S, insn->type))
- buf += sprintf(buf, ".f%d", insn->size);
- else if (insn->size)
- buf += sprintf(buf, ".%d", insn->size);
- if (insn->type) {
- if (dmrC_is_ptr_type(insn->type))
- buf += sprintf(buf, "*");
- }
-
- memset(buf, ' ', 20);
- buf++;
- }
-
- if (buf < C->L->buffer + 12)
- buf = C->L->buffer + 12;
- switch (opcode) {
- case OP_RET:
- if (insn->src && insn->src != VOID_PSEUDO(C))
- buf += sprintf(buf, "%s", dmrC_show_pseudo(C, insn->src));
- break;
- case OP_CBR:
- buf += sprintf(buf, "%s, .L%u, .L%u", dmrC_show_pseudo(C, insn->cond), insn->bb_true->nr, insn->bb_false->nr);
- break;
-
- case OP_BR:
- buf += sprintf(buf, ".L%u", insn->bb_true->nr);
- break;
-
- case OP_SYMADDR: {
- struct symbol *sym = insn->symbol->sym;
- buf += sprintf(buf, "%s <- ", dmrC_show_pseudo(C, insn->target));
-
- if (!insn->bb && !sym)
- break;
- if (sym->bb_target) {
- buf += sprintf(buf, ".L%u", sym->bb_target->nr);
- break;
- }
- if (sym->ident) {
- buf += sprintf(buf, "%s", dmrC_show_ident(C, sym->ident));
- break;
- }
- buf += sprintf(buf, "", sym);
- break;
- }
-
- case OP_SETVAL: {
- struct expression *expr = insn->val;
- struct symbol *sym;
- buf += sprintf(buf, "%s <- ", dmrC_show_pseudo(C, insn->target));
-
- if (!expr) {
- buf += sprintf(buf, "%s", "");
- break;
- }
-
- switch (expr->type) {
- case EXPR_VALUE:
- buf += sprintf(buf, "%lld", expr->value);
- break;
- case EXPR_FVALUE:
- buf += sprintf(buf, "%Lf", expr->fvalue);
- break;
- case EXPR_STRING:
- buf += sprintf(buf, "%.40s", dmrC_show_string(C, expr->string));
- break;
- case EXPR_SYMBOL:
- buf += sprintf(buf, "%s", dmrC_show_ident(C, expr->symbol->ident));
- break;
- case EXPR_LABEL:
- sym = expr->symbol;
- if (sym->bb_target)
- buf += sprintf(buf, ".L%u", sym->bb_target->nr);
- break;
- default:
- buf += sprintf(buf, "SETVAL EXPR TYPE %d", expr->type);
- }
- break;
- }
- case OP_SWITCH: {
- struct multijmp *jmp;
- buf += sprintf(buf, "%s", dmrC_show_pseudo(C, insn->cond));
- FOR_EACH_PTR(insn->multijmp_list, jmp) {
- if (jmp->begin == jmp->end)
- buf += sprintf(buf, ", %lld -> .L%u", jmp->begin, jmp->target->nr);
- else if (jmp->begin < jmp->end)
- buf += sprintf(buf, ", %lld ... %lld -> .L%u", jmp->begin, jmp->end, jmp->target->nr);
- else
- buf += sprintf(buf, ", default -> .L%u", jmp->target->nr);
- } END_FOR_EACH_PTR(jmp);
- break;
- }
- case OP_COMPUTEDGOTO: {
- struct multijmp *jmp;
- buf += sprintf(buf, "%s", dmrC_show_pseudo(C, insn->target));
- FOR_EACH_PTR(insn->multijmp_list, jmp) {
- buf += sprintf(buf, ", .L%u", jmp->target->nr);
- } END_FOR_EACH_PTR(jmp);
- break;
- }
-
- case OP_PHISOURCE: {
- struct instruction *phi;
- buf += sprintf(buf, "%s <- %s ", dmrC_show_pseudo(C, insn->target), dmrC_show_pseudo(C, insn->phi_src));
- FOR_EACH_PTR(insn->phi_users, phi) {
- buf += sprintf(buf, " (%s)", dmrC_show_pseudo(C, phi->target));
- } END_FOR_EACH_PTR(phi);
- break;
- }
-
- case OP_PHI: {
- pseudo_t phi;
- const char *s = " <-";
- buf += sprintf(buf, "%s", dmrC_show_pseudo(C, insn->target));
- FOR_EACH_PTR(insn->phi_list, phi) {
- buf += sprintf(buf, "%s %s", s, dmrC_show_pseudo(C, phi));
- s = ",";
- } END_FOR_EACH_PTR(phi);
- break;
- }
- case OP_LOAD: case OP_LNOP:
- buf += sprintf(buf, "%s <- %d[%s]", dmrC_show_pseudo(C, insn->target), insn->offset, dmrC_show_pseudo(C, insn->src));
- if (insn->orig_type) {
- struct symbol *sym = insn->orig_type;
- if (sym->ident) {
- buf += sprintf(buf, "; %s", dmrC_show_ident(C, sym->ident));
- }
- else {
- buf += sprintf(buf, "; ", sym);
- }
- }
- break;
- case OP_STORE: case OP_SNOP:
- buf += sprintf(buf, "%s -> %d[%s]", dmrC_show_pseudo(C, insn->target), insn->offset, dmrC_show_pseudo(C, insn->src));
- if (insn->orig_type) {
- struct symbol *sym = insn->orig_type;
- if (sym->ident) {
- buf += sprintf(buf, "; %s", dmrC_show_ident(C, sym->ident));
- }
- else {
- buf += sprintf(buf, "; ", sym);
- }
- }
- break;
- case OP_INLINED_CALL:
- case OP_CALL: {
- if (insn->target && insn->target != VOID_PSEUDO(C))
- buf += sprintf(buf, "%s <- ", dmrC_show_pseudo(C, insn->target));
- buf += sprintf(buf, "%s", dmrC_show_pseudo(C, insn->func));
- {
- struct pseudo *arg;
- FOR_EACH_PTR(insn->arguments, arg) {
- buf += sprintf(buf, ", %s", dmrC_show_pseudo(C, arg));
- } END_FOR_EACH_PTR(arg);
- }
- break;
- }
- case OP_CAST:
- case OP_SCAST:
- case OP_FPCAST:
- case OP_PTRCAST:
- buf += sprintf(buf, "%s <- (%d) %s",
- dmrC_show_pseudo(C, insn->target),
- type_size(insn->orig_type),
- dmrC_show_pseudo(C, insn->src));
- break;
- 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:
-
- buf += sprintf(buf, "%s <- %s, %s", dmrC_show_pseudo(C, insn->target), dmrC_show_pseudo(C, insn->src1), dmrC_show_pseudo(C, insn->src2));
- break;
-
- case OP_SEL:
- buf += sprintf(buf, "%s <- %s, %s, %s", dmrC_show_pseudo(C, insn->target),
- dmrC_show_pseudo(C, insn->src1), dmrC_show_pseudo(C, insn->src2), dmrC_show_pseudo(C, insn->src3));
- break;
-
- case OP_SLICE:
- buf += sprintf(buf, "%s <- %s, %d, %d", dmrC_show_pseudo(C, insn->target), dmrC_show_pseudo(C, insn->base), insn->from, insn->len);
- break;
-
- case OP_NOT: case OP_NEG:
- buf += sprintf(buf, "%s <- %s", dmrC_show_pseudo(C, insn->target), dmrC_show_pseudo(C, insn->src1));
- break;
-
- case OP_CONTEXT:
- buf += sprintf(buf, "%s%d", insn->check ? "check: " : "", insn->increment);
- break;
- case OP_RANGE:
- buf += sprintf(buf, "%s between %s..%s", dmrC_show_pseudo(C, insn->src1), dmrC_show_pseudo(C, insn->src2), dmrC_show_pseudo(C, insn->src3));
- break;
- case OP_NOP:
- buf += sprintf(buf, "%s <- %s", dmrC_show_pseudo(C, insn->target), dmrC_show_pseudo(C, insn->src1));
- break;
- case OP_DEATHNOTE:
- buf += sprintf(buf, "%s", dmrC_show_pseudo(C, insn->target));
- break;
- case OP_ASM:
- buf = show_asm(C, buf, insn);
- break;
- case OP_COPY:
- buf += sprintf(buf, "%s <- %s", dmrC_show_pseudo(C, insn->target), dmrC_show_pseudo(C, insn->src));
- break;
- default:
- break;
- }
-
- if (buf >= C->L->buffer + sizeof(C->L->buffer))
- dmrC_die(C, "instruction buffer overflowed %td\n", buf - C->L->buffer);
- do { --buf; } while (*buf == ' ');
- *++buf = 0;
- return C->L->buffer;
-}
-
-void dmrC_show_bb(struct dmr_C *C, struct basic_block *bb)
-{
- struct instruction *insn;
-
- printf(".L%u:\n", bb->nr);
- if (C->verbose) {
- pseudo_t needs, defines;
- printf("%s:%d\n", dmrC_stream_name(C, bb->pos.stream), bb->pos.line);
-
- FOR_EACH_PTR(bb->needs, needs) {
- struct instruction *def = needs->def;
- if (def->opcode != OP_PHI) {
- printf(" **uses %s (from .L%u)**\n", dmrC_show_pseudo(C, needs), def->bb->nr);
- } else {
- pseudo_t phi;
- const char *sep = " ";
- printf(" **uses %s (from", dmrC_show_pseudo(C, needs));
- FOR_EACH_PTR(def->phi_list, phi) {
- if (phi == VOID_PSEUDO(C))
- continue;
- printf("%s(%s:.L%u)", sep, dmrC_show_pseudo(C, phi), phi->def->bb->nr);
- sep = ", ";
- } END_FOR_EACH_PTR(phi);
- printf(")**\n");
- }
- } END_FOR_EACH_PTR(needs);
-
- FOR_EACH_PTR(bb->defines, defines) {
- printf(" **defines %s **\n", dmrC_show_pseudo(C, defines));
- } END_FOR_EACH_PTR(defines);
-
- if (bb->parents) {
- struct basic_block *from;
- FOR_EACH_PTR(bb->parents, from) {
- printf(" **from .L%u (%s:%d:%d)**\n", from->nr,
- dmrC_stream_name(C, from->pos.stream), from->pos.line, from->pos.pos);
- } END_FOR_EACH_PTR(from);
- }
-
- if (bb->children) {
- struct basic_block *to;
- FOR_EACH_PTR(bb->children, to) {
- printf(" **to .L%u (%s:%d:%d)**\n", to->nr,
- dmrC_stream_name(C, to->pos.stream), to->pos.line, to->pos.pos);
- } END_FOR_EACH_PTR(to);
- }
- }
-
- FOR_EACH_PTR(bb->insns, insn) {
- if (!insn->bb && C->verbose < 2)
- continue;
- printf("\t%s\n", dmrC_show_instruction(C, insn));
- } END_FOR_EACH_PTR(insn);
- if (!dmrC_bb_terminated(bb))
- printf("\tEND\n");
-}
-
-static void show_symbol_usage(struct dmr_C *C, pseudo_t pseudo)
-{
- struct pseudo_user *pu;
-
- if (pseudo) {
- FOR_EACH_PTR(pseudo->users, pu) {
- printf("\t%s\n", dmrC_show_instruction(C, pu->insn));
- } END_FOR_EACH_PTR(pu);
- }
-}
-
-void dmrC_show_entry(struct dmr_C *C, struct entrypoint *ep)
-{
- struct symbol *sym;
- struct basic_block *bb;
-
- printf("%s:\n", dmrC_show_ident(C, ep->name->ident));
-
- if (C->verbose) {
- printf("ep %p: %s\n", ep, dmrC_show_ident(C, ep->name->ident));
-
- FOR_EACH_PTR(ep->syms, sym) {
- if (!sym->pseudo)
- continue;
- if (!sym->pseudo->users)
- continue;
- printf(" sym: %p %s\n", sym, dmrC_show_ident(C, sym->ident));
- if (sym->ctype.modifiers & (MOD_EXTERN | MOD_STATIC | MOD_ADDRESSABLE))
- printf("\texternal visibility\n");
- show_symbol_usage(C, sym->pseudo);
- } END_FOR_EACH_PTR(sym);
-
- printf("\n");
- }
-
- FOR_EACH_PTR(ep->bbs, bb) {
- if (!bb)
- continue;
- if (!bb->parents && !bb->children && !bb->insns && C->verbose < 2)
- continue;
- dmrC_show_bb(C, bb);
- printf("\n");
- } END_FOR_EACH_PTR(bb);
-
- printf("\n");
-}
-
-static void bind_label(struct dmr_C *C, struct symbol *label, struct basic_block *bb, struct position pos)
-{
- if (label->bb_target)
- dmrC_warning(C, pos, "label '%s' already bound", dmrC_show_ident(C, label->ident));
- label->bb_target = bb;
-}
-
-static struct basic_block * get_bound_block(struct dmr_C *C, struct entrypoint *ep, struct symbol *label)
-{
- struct basic_block *bb = label->bb_target;
-
- if (!bb) {
- bb = alloc_basic_block(C, ep, label->pos);
- label->bb_target = bb;
- }
- return bb;
-}
-
-static void finish_block(struct entrypoint *ep)
-{
- struct basic_block *src = ep->active;
- if (dmrC_bb_reachable(src))
- ep->active = NULL;
-}
-
-static void add_goto(struct dmr_C *C, struct entrypoint *ep, struct basic_block *dst)
-{
- struct basic_block *src = ep->active;
- if (dmrC_bb_reachable(src)) {
- struct instruction *br = alloc_instruction(C, OP_BR, 0);
- br->bb_true = dst;
- dmrC_add_bb(C, &dst->parents, src);
- dmrC_add_bb(C, &src->children, dst);
- br->bb = src;
- dmrC_add_instruction(C, &src->insns, br);
- ep->active = NULL;
- }
-}
-
-static void add_one_insn(struct dmr_C *C, struct entrypoint *ep, struct instruction *insn)
-{
- struct basic_block *bb = ep->active;
-
- if (dmrC_bb_reachable(bb)) {
- insn->bb = bb;
- dmrC_add_instruction(C, &bb->insns, insn);
- }
-}
-
-static void set_activeblock(struct dmr_C *C, struct entrypoint *ep, struct basic_block *bb)
-{
- if (!dmrC_bb_terminated(ep->active))
- add_goto(C, ep, bb);
-
- ep->active = bb;
- if (dmrC_bb_reachable(bb))
- dmrC_add_bb(C, &ep->bbs, bb);
-}
-
-static void remove_parent(struct dmr_C *C, struct basic_block *child, struct basic_block *parent)
-{
- dmrC_remove_bb_from_list(&child->parents, parent, 1);
- if (!child->parents)
- C->L->repeat_phase |= REPEAT_CFG_CLEANUP;
-}
-
-/* Change a "switch" into a branch */
-void dmrC_insert_branch(struct dmr_C *C, struct basic_block *bb, struct instruction *jmp, struct basic_block *target)
-{
- struct instruction *br, *old;
- struct basic_block *child;
-
- /* Remove the switch */
- old = dmrC_delete_last_instruction(&bb->insns);
- assert(old == jmp);
- dmrC_kill_instruction(C, old);
-
- br = alloc_instruction(C, OP_BR, 0);
- br->bb = bb;
- br->bb_true = target;
- dmrC_add_instruction(C, &bb->insns, br);
-
- FOR_EACH_PTR(bb->children, child) {
- if (child == target) {
- target = NULL; /* Trigger just once */
- continue;
- }
- DELETE_CURRENT_PTR(child);
- remove_parent(C, child, bb);
- } END_FOR_EACH_PTR(child);
- ptrlist_pack((struct ptr_list **)&bb->children);
-}
-
-
-void dmrC_insert_select(struct dmr_C *C, struct basic_block *bb, struct instruction *br, struct instruction *phi_node, pseudo_t if_true, pseudo_t if_false)
-{
- pseudo_t target;
- struct instruction *select;
-
- /* Remove the 'br' */
- dmrC_delete_last_instruction(&bb->insns);
-
- select = alloc_typed_instruction(C, OP_SEL, phi_node->type);
- select->bb = bb;
-
- assert(br->cond);
- dmrC_use_pseudo(C, select, br->cond, &select->src1);
-
- target = phi_node->target;
- assert(target->def == phi_node);
- select->target = target;
- target->def = select;
-
- dmrC_use_pseudo(C, select, if_true, &select->src2);
- dmrC_use_pseudo(C, select, if_false, &select->src3);
-
- dmrC_add_instruction(C, &bb->insns, select);
- dmrC_add_instruction(C, &bb->insns, br);
-}
-
-static inline int bb_empty(struct basic_block *bb)
-{
- return !bb->insns;
-}
-
-/* Add a label to the currently active block, return new active block */
-static struct basic_block * add_label(struct dmr_C *C, struct entrypoint *ep, struct symbol *label)
-{
- struct basic_block *bb = label->bb_target;
-
- if (bb) {
- set_activeblock(C, ep, bb);
- return bb;
- }
- bb = ep->active;
- if (!dmrC_bb_reachable(bb) || !bb_empty(bb)) {
- bb = alloc_basic_block(C, ep, label->pos);
- set_activeblock(C, ep, bb);
- }
- label->bb_target = bb;
- return bb;
-}
-
-static void add_branch(struct dmr_C *C, struct entrypoint *ep, struct expression *expr, pseudo_t cond, struct basic_block *bb_true, struct basic_block *bb_false)
-{
- (void)expr;
- struct basic_block *bb = ep->active;
- struct instruction *br;
-
- if (dmrC_bb_reachable(bb)) {
- br = alloc_instruction(C, OP_CBR, 0);
- dmrC_use_pseudo(C, br, cond, &br->cond);
- br->bb_true = bb_true;
- br->bb_false = bb_false;
- dmrC_add_bb(C, &bb_true->parents, bb);
- dmrC_add_bb(C, &bb_false->parents, bb);
- dmrC_add_bb(C, &bb->children, bb_true);
- dmrC_add_bb(C, &bb->children, bb_false);
- add_one_insn(C, ep, br);
- }
-}
-
-/* Dummy pseudo allocator */
-pseudo_t dmrC_alloc_pseudo(struct dmr_C *C, struct instruction *def)
-{
- struct pseudo * pseudo = (pseudo_t)dmrC_allocator_allocate(&C->L->pseudo_allocator, 0);
- pseudo->type = PSEUDO_REG;
- pseudo->nr = ++C->L->nr;
- pseudo->def = def;
- return pseudo;
-}
-
-static pseudo_t symbol_pseudo(struct dmr_C *C, struct entrypoint *ep, struct symbol *sym)
-{
- pseudo_t pseudo;
-
- if (!sym)
- return VOID_PSEUDO(C);
-
- pseudo = sym->pseudo;
- if (!pseudo) {
- pseudo = (pseudo_t)dmrC_allocator_allocate(&C->L->pseudo_allocator, 0);
- pseudo->nr = -1;
- pseudo->type = PSEUDO_SYM;
- pseudo->sym = sym;
- pseudo->ident = sym->ident;
- sym->pseudo = pseudo;
- dmrC_add_pseudo(C, &ep->accesses, pseudo);
- }
- /* Symbol pseudos have neither nr, usage nor def */
- return pseudo;
-}
-
-unsigned int dmrC_value_size(long long value)
-{
- value >>= 8;
- if (!value)
- return 8;
- value >>= 8;
- if (!value)
- return 16;
- value >>= 16;
- if (!value)
- return 32;
- return 64;
-}
-
-pseudo_t dmrC_value_pseudo(struct dmr_C *C, struct symbol *type, long long val)
-{
- int hash = val & (MAX_VAL_HASH-1);
- struct pseudo_list **list = C->L->prev + hash;
- int size = type ? type->bit_size : dmrC_value_size(val);
- pseudo_t pseudo;
-
- assert(size == -1 || size <= (int)(sizeof(long long) * 8));
-
- FOR_EACH_PTR(*list, pseudo) {
- if (pseudo->value == val && pseudo->size == size)
- return pseudo;
- } END_FOR_EACH_PTR(pseudo);
-
- pseudo = (pseudo_t)dmrC_allocator_allocate(&C->L->pseudo_allocator, 0);
- pseudo->type = PSEUDO_VAL;
- pseudo->value = val;
- pseudo->size = size;
- dmrC_add_pseudo(C, list, pseudo);
-
- /* Value pseudos have neither nr, usage nor def */
- return pseudo;
-}
-
-static pseudo_t argument_pseudo(struct dmr_C *C, struct entrypoint *ep, int nr, struct symbol *arg)
-{
- pseudo_t pseudo = (pseudo_t)dmrC_allocator_allocate(&C->L->pseudo_allocator, 0);
- struct instruction *entry = ep->entry;
-
- pseudo->type = PSEUDO_ARG;
- pseudo->nr = nr;
- pseudo->sym = arg;
- dmrC_add_pseudo(C, &entry->arg_list, pseudo);
-
- /* Argument pseudos have neither usage nor def */
- return pseudo;
-}
-
-// From Luc: sssa-mini
-struct instruction *dmrC_alloc_phisrc(struct dmr_C *C, pseudo_t pseudo, struct symbol *type)
-{
- struct instruction *insn = alloc_typed_instruction(C, OP_PHISOURCE, type);
- pseudo_t phi = (pseudo_t)dmrC_allocator_allocate(&C->L->pseudo_allocator, 0);
- static int nr = 0;
-
- phi->type = PSEUDO_PHI;
- phi->nr = ++nr;
- phi->def = insn;
-
- dmrC_use_pseudo(C, insn, pseudo, &insn->phi_src);
- insn->target = phi;
- return insn;
-}
-
-// From Luc: sssa-mini
-pseudo_t dmrC_alloc_phi(struct dmr_C *C, struct basic_block *source, pseudo_t pseudo, struct symbol *type)
-{
- struct instruction *insn;
-
- if (!source)
- return VOID_PSEUDO(C);
-
- insn = dmrC_alloc_phisrc(C, pseudo, type);
- insn->bb = source;
- dmrC_add_instruction(C, &source->insns, insn);
- return insn->target;
-}
-
-// From Luc: sssa-mini
-pseudo_t dmrC_insert_phi_node(struct dmr_C *C, struct basic_block *bb, struct symbol *type)
-{
- struct instruction *phi_node = alloc_typed_instruction(C, OP_PHI, type);
- struct instruction *insn;
- pseudo_t phi;
-
- phi = dmrC_alloc_pseudo(C, phi_node);
- phi_node->target = phi;
- phi_node->bb = bb;
-
- FOR_EACH_PTR(bb->insns, insn) {
- enum opcode op = insn->opcode;
- if (op == OP_ENTRY || op == OP_PHI)
- continue;
- INSERT_CURRENT(phi_node, insn);
- return phi;
- } END_FOR_EACH_PTR(insn);
-
- dmrC_add_instruction(C, &bb->insns, phi_node);
- return phi;
-}
-
-/*
- * We carry the "access_data" structure around for any accesses,
- * which simplifies things a lot. It contains all the access
- * information in one place.
- */
-struct access_data {
- struct symbol *result_type; // result ctype
- struct symbol *source_type; // source ctype
- pseudo_t address; // pseudo containing address ..
- unsigned int offset; // byte offset
- struct position pos;
-};
-
-static void finish_address_gen(struct entrypoint *ep, struct access_data *ad)
-{
- (void)ep;
- (void)ad;
-}
-
-static int linearize_simple_address(struct dmr_C *C, struct entrypoint *ep,
- struct expression *addr,
- struct access_data *ad)
-{
- if (addr->type == EXPR_SYMBOL) {
- linearize_one_symbol(C, ep, addr->symbol);
- ad->address = symbol_pseudo(C, ep, addr->symbol);
- return 1;
- }
- if (addr->type == EXPR_BINOP) {
- if (addr->right->type == EXPR_VALUE) {
- if (addr->op == '+') {
- ad->offset += (unsigned int) dmrC_get_expression_value(C, addr->right);
- return linearize_simple_address(C, ep, addr->left, ad);
- }
- }
- }
- ad->address = linearize_expression(C, ep, addr);
- return 1;
-}
-
-static struct symbol *base_type(struct dmr_C *C, struct symbol *sym)
-{
- (void)C;
- struct symbol *base = sym;
-
- if (sym) {
- if (sym->type == SYM_NODE)
- base = base->ctype.base_type;
- if (base->type == SYM_BITFIELD)
- return base->ctype.base_type;
- }
- return sym;
-}
-
-static int linearize_address_gen(struct dmr_C *C, struct entrypoint *ep,
- struct expression *expr,
- struct access_data *ad)
-{
- struct symbol *ctype = expr->ctype;
-
- if (!ctype)
- return 0;
- ad->pos = expr->pos;
- ad->result_type = ctype;
- ad->source_type = base_type(C, ctype);
- if (expr->type == EXPR_PREOP && expr->op == '*')
- return linearize_simple_address(C, ep, expr->unop, ad);
-
- dmrC_warning(C, expr->pos, "generating address of non-lvalue (%d)", expr->type);
- return 0;
-}
-
-/* Try to get the actual struct type associated with a load or store */
-static struct symbol *get_base_symbol_type(struct dmr_C *C, struct access_data *ad) {
- (void) C;
- struct symbol *orig_type = NULL;
- if (ad->address->type == PSEUDO_SYM) {
- orig_type = ad->address->sym;
- }
- else if (ad->address->type == PSEUDO_REG) {
- if (ad->address->def->opcode == OP_LOAD) {
- orig_type = ad->address->def->orig_type;
- }
- }
- if (orig_type) {
- if (orig_type->type == SYM_NODE)
- orig_type = orig_type->ctype.base_type;
- if (orig_type->type == SYM_PTR)
- orig_type = orig_type->ctype.base_type;
- //dmrC_show_type(C, orig_type);
- }
- return orig_type;
-}
-
-static pseudo_t add_load(struct dmr_C *C, struct entrypoint *ep, struct access_data *ad)
-{
- struct instruction *insn;
- pseudo_t new;
-
- insn = alloc_typed_instruction(C, OP_LOAD, ad->source_type);
- /* save the address symbol so that backend can see what symbol we are accessing */
- insn->orig_type = get_base_symbol_type(C, ad);
- new = dmrC_alloc_pseudo(C, insn);
-
- insn->target = new;
- insn->offset = ad->offset;
- dmrC_use_pseudo(C, insn, ad->address, &insn->src);
- add_one_insn(C, ep, insn);
- return new;
-}
-
-static void add_store(struct dmr_C *C, struct entrypoint *ep, struct access_data *ad, pseudo_t value)
-{
- struct basic_block *bb = ep->active;
- if (dmrC_bb_reachable(bb)) {
- struct instruction *store = alloc_typed_instruction(C, OP_STORE, ad->source_type);
- store->offset = ad->offset;
- /* save the address symbol so that backend can see what symbol we are accessing */
- store->orig_type = get_base_symbol_type(C, ad);
- dmrC_use_pseudo(C, store, value, &store->target);
- dmrC_use_pseudo(C, store, ad->address, &store->src);
- add_one_insn(C, ep, store);
- }
-}
-
-static pseudo_t linearize_store_gen(struct dmr_C *C, struct entrypoint *ep,
- pseudo_t value,
- struct access_data *ad)
-{
- pseudo_t store = value;
-
- if (type_size(ad->source_type) != type_size(ad->result_type)) {
- struct symbol *ctype = ad->result_type;
- unsigned int shift = ctype->bit_offset;
- unsigned int size = ctype->bit_size;
- pseudo_t orig = add_load(C, ep, ad);
- unsigned long long mask = (1ULL << size) - 1;
-
- if (shift) {
- store = add_binary_op(C, ep, ad->source_type, OP_SHL, value, dmrC_value_pseudo(C, ctype, shift));
- mask <<= shift;
- }
- orig = add_binary_op(C, ep, ad->source_type, OP_AND, orig, dmrC_value_pseudo(C, ctype, ~mask));
- store = add_binary_op(C, ep, ad->source_type, OP_OR, orig, store);
- }
- add_store(C, ep, ad, store);
- return value;
-}
-
-static pseudo_t add_binary_op(struct dmr_C *C, struct entrypoint *ep, struct symbol *ctype, int op, pseudo_t left, pseudo_t right)
-{
- struct instruction *insn = alloc_typed_instruction(C, op, ctype);
- pseudo_t target = dmrC_alloc_pseudo(C, insn);
- insn->target = target;
- dmrC_use_pseudo(C, insn, left, &insn->src1);
- dmrC_use_pseudo(C, insn, right, &insn->src2);
- add_one_insn(C, ep, insn);
- return target;
-}
-
-static pseudo_t add_setval(struct dmr_C *C, struct entrypoint *ep, struct symbol *ctype, struct expression *val)
-{
- struct instruction *insn = alloc_typed_instruction(C, OP_SETVAL, ctype);
- pseudo_t target = dmrC_alloc_pseudo(C, insn);
- insn->target = target;
- insn->val = val;
- add_one_insn(C, ep, insn);
- return target;
-}
-
-static pseudo_t add_symbol_address(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- struct instruction *insn = alloc_typed_instruction(C, OP_SYMADDR, expr->ctype);
- struct symbol *sym = expr->symbol;
- pseudo_t target = dmrC_alloc_pseudo(C, insn);
-
- insn->target = target;
- dmrC_use_pseudo(C, insn, symbol_pseudo(C, ep, sym), &insn->symbol);
- add_one_insn(C, ep, insn);
- return target;
-}
-
-static pseudo_t linearize_load_gen(struct dmr_C *C, struct entrypoint *ep, struct access_data *ad)
-{
- struct symbol *ctype = ad->result_type;
- pseudo_t new = add_load(C, ep, ad);
-
- if (ctype->bit_offset) {
- pseudo_t shift = dmrC_value_pseudo(C, ctype, ctype->bit_offset);
- pseudo_t newval = add_binary_op(C, ep, ad->source_type, OP_LSR, new, shift);
- new = newval;
- }
-
- if (ctype->bit_size != type_size(ad->source_type))
- new = cast_pseudo(C, ep, new, ad->source_type, ad->result_type);
- return new;
-}
-
-static pseudo_t linearize_access(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- struct access_data ad;
- pseudo_t value;
-
- memset(&ad, 0, sizeof ad);
- if (!linearize_address_gen(C, ep, expr, &ad))
- return VOID_PSEUDO(C);
- value = linearize_load_gen(C, ep, &ad);
- finish_address_gen(ep, &ad);
- return value;
-}
-
-/* FIXME: FP */
-static pseudo_t linearize_inc_dec(struct dmr_C *C, struct entrypoint *ep, struct expression *expr, int postop)
-{
- struct access_data ad;
- pseudo_t old, new, one;
-
- memset(&ad, 0, sizeof ad);
- int op = expr->op == SPECIAL_INCREMENT ? OP_ADD : OP_SUB;
-
- if (!linearize_address_gen(C, ep, expr->unop, &ad))
- return VOID_PSEUDO(C);
-
- old = linearize_load_gen(C, ep, &ad);
- one = dmrC_value_pseudo(C, expr->ctype, expr->op_value);
- new = add_binary_op(C, ep, expr->ctype, op, old, one);
- linearize_store_gen(C, ep, new, &ad);
- finish_address_gen(ep, &ad);
- return postop ? old : new;
-}
-
-static pseudo_t add_uniop(struct dmr_C *C, struct entrypoint *ep, struct expression *expr, int op, pseudo_t src)
-{
- struct instruction *insn = alloc_typed_instruction(C, op, expr->ctype);
- pseudo_t new = dmrC_alloc_pseudo(C, insn);
-
- insn->target = new;
- dmrC_use_pseudo(C, insn, src, &insn->src1);
- add_one_insn(C, ep, insn);
- return new;
-}
-
-static pseudo_t linearize_slice(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- pseudo_t pre = linearize_expression(C, ep, expr->base);
- struct instruction *insn = alloc_typed_instruction(C, OP_SLICE, expr->ctype);
- pseudo_t new = dmrC_alloc_pseudo(C, insn);
-
- insn->target = new;
- insn->from = expr->r_bitpos;
- insn->len = expr->r_nrbits;
- dmrC_use_pseudo(C, insn, pre, &insn->base);
- add_one_insn(C, ep, insn);
- return new;
-}
-
-static pseudo_t linearize_regular_preop(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- pseudo_t pre = linearize_expression(C, ep, expr->unop);
- switch (expr->op) {
- case '+':
- return pre;
- case '!': {
- pseudo_t zero = dmrC_value_pseudo(C, expr->ctype, 0);
- return add_binary_op(C, ep, expr->ctype, OP_SET_EQ, pre, zero);
- }
- case '~':
- return add_uniop(C, ep, expr, OP_NOT, pre);
- case '-':
- return add_uniop(C, ep, expr, OP_NEG, pre);
- }
- return VOID_PSEUDO(C);
-}
-
-static pseudo_t linearize_preop(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- /*
- * '*' is an lvalue access, and is fundamentally different
- * from an arithmetic operation. Maybe it should have an
- * expression type of its own..
- */
- if (expr->op == '*')
- return linearize_access(C, ep, expr);
- if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
- return linearize_inc_dec(C, ep, expr, 0);
- return linearize_regular_preop(C, ep, expr);
-}
-
-static pseudo_t linearize_postop(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- return linearize_inc_dec(C, ep, expr, 1);
-}
-
-/*
- * Casts to pointers are "less safe" than other casts, since
- * they imply type-unsafe accesses. "void *" is a special
- * case, since you can't access through it anyway without another
- * cast.
- */
-static struct instruction *alloc_cast_instruction(struct dmr_C *C, struct symbol *src, struct symbol *ctype)
-{
- int opcode = OP_CAST;
- // https://patchwork.kernel.org/patch/9516077/
- struct symbol *base = ctype;
-
- if (src->ctype.modifiers & MOD_SIGNED)
- opcode = OP_SCAST;
- if (base->type == SYM_NODE)
- base = base->ctype.base_type;
- if (base->type == SYM_PTR) {
- base = base->ctype.base_type;
- if (base != &C->S->void_ctype)
- opcode = OP_PTRCAST;
- } else if (base->ctype.base_type == &C->S->fp_type)
- opcode = OP_FPCAST;
- return alloc_typed_instruction(C, opcode, ctype);
-}
-
-static pseudo_t cast_pseudo(struct dmr_C *C, struct entrypoint *ep, pseudo_t src, struct symbol *from, struct symbol *to)
-{
- pseudo_t result;
- struct instruction *insn;
-
- if (src == VOID_PSEUDO(C))
- return VOID_PSEUDO(C);
- if (!from || !to)
- return VOID_PSEUDO(C);
- if (from->bit_size < 0 || to->bit_size < 0)
- return VOID_PSEUDO(C);
- insn = alloc_cast_instruction(C, from, to);
- result = dmrC_alloc_pseudo(C, insn);
- insn->target = result;
- insn->orig_type = from;
- dmrC_use_pseudo(C, insn, src, &insn->src);
- add_one_insn(C, ep, insn);
- return result;
-}
-
-static int opcode_sign(struct dmr_C *C, int opcode, struct symbol *ctype)
-{
- (void)C;
- if (ctype && (ctype->ctype.modifiers & MOD_SIGNED)) {
- switch(opcode) {
- case OP_MULU: case OP_DIVU: case OP_MODU: case OP_LSR:
- opcode++;
- }
- }
- return opcode;
-}
-
-static inline pseudo_t add_convert_to_bool(struct dmr_C *C, struct entrypoint *ep, pseudo_t src, struct symbol *type)
-{
- pseudo_t zero;
- int op;
-
- if (dmrC_is_bool_type(C->S, type))
- return src;
- zero = dmrC_value_pseudo(C, type, 0);
- op = OP_SET_NE;
- return add_binary_op(C, ep, &C->S->bool_ctype, op, src, zero);
-}
-
-static pseudo_t linearize_expression_to_bool(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- pseudo_t dst;
- dst = linearize_expression(C, ep, expr);
- dst = add_convert_to_bool(C, ep, dst, expr->ctype);
- return dst;
-}
-static pseudo_t linearize_assignment(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- struct access_data ad;
- struct expression *target = expr->left;
- struct expression *src = expr->right;
- struct symbol *ctype;
- pseudo_t value;
-
- memset(&ad, 0, sizeof ad);
- value = linearize_expression(C, ep, src);
- if (!target || !linearize_address_gen(C, ep, target, &ad))
- return value;
- if (expr->op != '=') {
- pseudo_t oldvalue = linearize_load_gen(C, ep, &ad);
- pseudo_t dst;
- static const int op_trans[] = {
- [SPECIAL_ADD_ASSIGN - SPECIAL_BASE] = OP_ADD,
- [SPECIAL_SUB_ASSIGN - SPECIAL_BASE] = OP_SUB,
- [SPECIAL_MUL_ASSIGN - SPECIAL_BASE] = OP_MULU,
- [SPECIAL_DIV_ASSIGN - SPECIAL_BASE] = OP_DIVU,
- [SPECIAL_MOD_ASSIGN - SPECIAL_BASE] = OP_MODU,
- [SPECIAL_SHL_ASSIGN - SPECIAL_BASE] = OP_SHL,
- [SPECIAL_SHR_ASSIGN - SPECIAL_BASE] = OP_LSR,
- [SPECIAL_AND_ASSIGN - SPECIAL_BASE] = OP_AND,
- [SPECIAL_OR_ASSIGN - SPECIAL_BASE] = OP_OR,
- [SPECIAL_XOR_ASSIGN - SPECIAL_BASE] = OP_XOR
- };
- int opcode;
-
- if (!src)
- return VOID_PSEUDO(C);
-
- ctype = src->ctype;
- oldvalue = cast_pseudo(C, ep, oldvalue, target->ctype, ctype);
- opcode = opcode_sign(C, op_trans[expr->op - SPECIAL_BASE], ctype);
- dst = add_binary_op(C, ep, ctype, opcode, oldvalue, value);
-
- value = cast_pseudo(C, ep, dst, ctype, expr->ctype);
- }
- value = linearize_store_gen(C, ep, value, &ad);
- finish_address_gen(ep, &ad);
- return value;
-}
-
-static pseudo_t linearize_call_expression(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- struct expression *arg, *fn;
- struct instruction *insn = alloc_typed_instruction(C, OP_CALL, expr->ctype);
- pseudo_t retval, call;
- struct ctype *ctype = NULL;
- struct symbol *fntype;
- struct context *context;
-
- if (!expr->ctype) {
- dmrC_warning(C, expr->pos, "call with no type!");
- return VOID_PSEUDO(C);
- }
-
- // first generate all the parameters
- FOR_EACH_PTR(expr->args, arg) {
- pseudo_t new = linearize_expression(C, ep, arg);
- dmrC_use_pseudo(C, insn, new, dmrC_add_pseudo(C, &insn->arguments, new));
- } END_FOR_EACH_PTR(arg);
-
- fn = expr->fn;
-
- if (fn->ctype)
- ctype = &fn->ctype->ctype;
-
- fntype = fn->ctype;
- if (fntype) {
- if (fntype->type == SYM_NODE)
- fntype = fntype->ctype.base_type;
- }
- insn->fntype = fntype;
-
- 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)
- fn = fn->unop;
- }
- }
- if (fn->type == EXPR_SYMBOL) {
- call = symbol_pseudo(C, ep, fn->symbol);
- } else {
- call = linearize_expression(C, ep, fn);
- }
- dmrC_use_pseudo(C, insn, call, &insn->func);
- retval = VOID_PSEUDO(C);
- if (expr->ctype != &C->S->void_ctype)
- retval = dmrC_alloc_pseudo(C, insn);
- insn->target = retval;
- add_one_insn(C, ep, insn);
-
- if (ctype) {
- FOR_EACH_PTR(ctype->contexts, context) {
- int in = context->in;
- int out = context->out;
- int check = 0;
- int context_diff;
- if (in < 0) {
- check = 1;
- in = 0;
- }
- if (out < 0) {
- check = 0;
- out = 0;
- }
- context_diff = out - in;
- if (check || context_diff) {
- insn = alloc_instruction(C, OP_CONTEXT, 0);
- insn->increment = context_diff;
- insn->check = check;
- insn->context_expr = context->context_expr;
- add_one_insn(C, ep, insn);
- }
- } END_FOR_EACH_PTR(context);
- }
-
- return retval;
-}
-
-static pseudo_t linearize_binop_bool(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- pseudo_t src1, src2, dst;
- int op = (expr->op == SPECIAL_LOGICAL_OR) ? OP_OR_BOOL : OP_AND_BOOL;
-
- src1 = linearize_expression_to_bool(C, ep, expr->left);
- src2 = linearize_expression_to_bool(C, ep, expr->right);
- dst = add_binary_op(C, ep, &C->S->bool_ctype, op, src1, src2);
- if (expr->ctype != &C->S->bool_ctype)
- dst = cast_pseudo(C, ep, dst, &C->S->bool_ctype, expr->ctype);
- return dst;
-}
-static pseudo_t linearize_binop(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- pseudo_t src1, src2, dst;
- static const int opcode[] = {
- ['+'] = OP_ADD, ['-'] = OP_SUB,
- ['*'] = OP_MULU, ['/'] = OP_DIVU,
- ['%'] = OP_MODU, ['&'] = OP_AND,
- ['|'] = OP_OR, ['^'] = OP_XOR,
- [SPECIAL_LEFTSHIFT] = OP_SHL,
- [SPECIAL_RIGHTSHIFT] = OP_LSR,
- };
- int op;
-
- src1 = linearize_expression(C, ep, expr->left);
- src2 = linearize_expression(C, ep, expr->right);
- op = opcode_sign(C, opcode[expr->op], expr->ctype);
- dst = add_binary_op(C, ep, expr->ctype, op, src1, src2);
- return dst;
-}
-
-static pseudo_t linearize_logical_branch(struct dmr_C *C, struct entrypoint *ep, struct expression *expr, struct basic_block *bb_true, struct basic_block *bb_false);
-
-static pseudo_t linearize_cond_branch(struct dmr_C *C, struct entrypoint *ep, struct expression *expr, struct basic_block *bb_true, struct basic_block *bb_false);
-
-static pseudo_t linearize_select(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- pseudo_t cond, true, false, res;
- struct instruction *insn;
-
- true = linearize_expression(C, ep, expr->cond_true);
- false = linearize_expression(C, ep, expr->cond_false);
- cond = linearize_expression(C, ep, expr->conditional);
-
- insn = alloc_typed_instruction(C, OP_SEL, expr->ctype);
- if (!expr->cond_true)
- true = cond;
- dmrC_use_pseudo(C, insn, cond, &insn->src1);
- dmrC_use_pseudo(C, insn, true, &insn->src2);
- dmrC_use_pseudo(C, insn, false, &insn->src3);
-
- res = dmrC_alloc_pseudo(C, insn);
- insn->target = res;
- add_one_insn(C, ep, insn);
- return res;
-}
-
-static pseudo_t add_join_conditional(struct dmr_C *C, struct entrypoint *ep, struct expression *expr,
- pseudo_t phi1, pseudo_t phi2)
-{
- pseudo_t target;
- struct instruction *phi_node;
-
- if (phi1 == VOID_PSEUDO(C))
- return phi2;
- if (phi2 == VOID_PSEUDO(C))
- return phi1;
-
- phi_node = alloc_typed_instruction(C, OP_PHI, expr->ctype);
- dmrC_use_pseudo(C, phi_node, phi1, dmrC_add_pseudo(C, &phi_node->phi_list, phi1));
- dmrC_use_pseudo(C, phi_node, phi2, dmrC_add_pseudo(C, &phi_node->phi_list, phi2));
- phi_node->target = target = dmrC_alloc_pseudo(C, phi_node);
- add_one_insn(C, ep, phi_node);
- return target;
-}
-
-static pseudo_t linearize_short_conditional(struct dmr_C *C, struct entrypoint *ep, struct expression *expr,
- struct expression *cond,
- struct expression *expr_false)
-{
- pseudo_t src1, src2;
- struct basic_block *bb_false;
- struct basic_block *merge = alloc_basic_block(C, ep, expr->pos);
- pseudo_t phi1, phi2;
-
- if (!expr_false || !ep->active)
- return VOID_PSEUDO(C);
-
- bb_false = alloc_basic_block(C, ep, expr_false->pos);
- src1 = linearize_expression(C, ep, cond);
- phi1 = dmrC_alloc_phi(C, ep->active, src1, expr->ctype);
- add_branch(C, ep, expr, src1, merge, bb_false);
-
- set_activeblock(C, ep, bb_false);
- src2 = linearize_expression(C, ep, expr_false);
- phi2 = dmrC_alloc_phi(C, ep->active, src2, expr->ctype);
- set_activeblock(C, ep, merge);
-
- return add_join_conditional(C, ep, expr, phi1, phi2);
-}
-
-static pseudo_t linearize_conditional(struct dmr_C *C, struct entrypoint *ep, struct expression *expr,
- struct expression *cond,
- struct expression *expr_true,
- struct expression *expr_false)
-{
- pseudo_t src1, src2;
- pseudo_t phi1, phi2;
- struct basic_block *bb_true, *bb_false, *merge;
-
- if (!cond || !expr_true || !expr_false || !ep->active)
- return VOID_PSEUDO(C);
- bb_true = alloc_basic_block(C, ep, expr_true->pos);
- bb_false = alloc_basic_block(C, ep, expr_false->pos);
- merge = alloc_basic_block(C, ep, expr->pos);
-
- linearize_cond_branch(C, ep, cond, bb_true, bb_false);
-
- set_activeblock(C, ep, bb_true);
- src1 = linearize_expression(C, ep, expr_true);
- phi1 = dmrC_alloc_phi(C, ep->active, src1, expr->ctype);
- add_goto(C, ep, merge);
-
- set_activeblock(C, ep, bb_false);
- src2 = linearize_expression(C, ep, expr_false);
- phi2 = dmrC_alloc_phi(C, ep->active, src2, expr->ctype);
- set_activeblock(C, ep, merge);
-
- return add_join_conditional(C, ep, expr, phi1, phi2);
-}
-
-static pseudo_t linearize_logical(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- struct expression *shortcut;
-
- shortcut = dmrC_alloc_const_expression(C, expr->pos, expr->op == SPECIAL_LOGICAL_OR);
- shortcut->ctype = expr->ctype;
- if (expr->op == SPECIAL_LOGICAL_OR)
- return linearize_conditional(C, ep, expr, expr->left, shortcut, expr->right);
- return linearize_conditional(C, ep, expr, expr->left, expr->right, shortcut);
-}
-
-static pseudo_t linearize_compare(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- static const int cmpop[] = {
- ['>'] = OP_SET_GT, ['<'] = OP_SET_LT,
- [SPECIAL_EQUAL] = OP_SET_EQ,
- [SPECIAL_NOTEQUAL] = OP_SET_NE,
- [SPECIAL_GTE] = OP_SET_GE,
- [SPECIAL_LTE] = OP_SET_LE,
- [SPECIAL_UNSIGNED_LT] = OP_SET_B,
- [SPECIAL_UNSIGNED_GT] = OP_SET_A,
- [SPECIAL_UNSIGNED_LTE] = OP_SET_BE,
- [SPECIAL_UNSIGNED_GTE] = OP_SET_AE,
- };
-
- pseudo_t src1 = linearize_expression(C, ep, expr->left);
- pseudo_t src2 = linearize_expression(C, ep, expr->right);
- pseudo_t dst = add_binary_op(C, ep, expr->ctype, cmpop[expr->op], src1, src2);
- return dst;
-}
-
-
-static pseudo_t linearize_cond_branch(struct dmr_C *C, struct entrypoint *ep, struct expression *expr, struct basic_block *bb_true, struct basic_block *bb_false)
-{
- pseudo_t cond;
-
- if (!expr || !dmrC_bb_reachable(ep->active))
- return VOID_PSEUDO(C);
-
- switch (expr->type) {
-
- case EXPR_STRING:
- case EXPR_VALUE:
- add_goto(C, ep, expr->value ? bb_true : bb_false);
- return VOID_PSEUDO(C);
-
- case EXPR_FVALUE:
- add_goto(C, ep, expr->fvalue ? bb_true : bb_false);
- return VOID_PSEUDO(C);
-
- case EXPR_LOGICAL:
- linearize_logical_branch(C, ep, expr, bb_true, bb_false);
- return VOID_PSEUDO(C);
-
- case EXPR_COMPARE:
- cond = linearize_compare(C, ep, expr);
- add_branch(C, ep, expr, cond, bb_true, bb_false);
- break;
-
- case EXPR_PREOP:
- if (expr->op == '!')
- return linearize_cond_branch(C, ep, expr->unop, bb_false, bb_true);
- /* fall through */
- default: {
- cond = linearize_expression(C, ep, expr);
- add_branch(C, ep, expr, cond, bb_true, bb_false);
-
- return VOID_PSEUDO(C);
- }
- }
- return VOID_PSEUDO(C);
-}
-
-
-
-static pseudo_t linearize_logical_branch(struct dmr_C *C, struct entrypoint *ep, struct expression *expr, struct basic_block *bb_true, struct basic_block *bb_false)
-{
- struct basic_block *next = alloc_basic_block(C, ep, expr->pos);
-
- if (expr->op == SPECIAL_LOGICAL_OR)
- linearize_cond_branch(C, ep, expr->left, bb_true, next);
- else
- linearize_cond_branch(C, ep, expr->left, next, bb_false);
- set_activeblock(C, ep, next);
- linearize_cond_branch(C, ep, expr->right, bb_true, bb_false);
- return VOID_PSEUDO(C);
-}
-
-static pseudo_t linearize_cast(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- pseudo_t src;
- struct expression *orig = expr->cast_expression;
-
- if (!orig)
- return VOID_PSEUDO(C);
-
- src = linearize_expression(C, ep, orig);
- return cast_pseudo(C, ep, src, orig->ctype, expr->ctype);
-}
-
-static pseudo_t linearize_position(struct dmr_C *C, struct entrypoint *ep, struct expression *pos, struct access_data *ad)
-{
- struct expression *init_expr = pos->init_expr;
-
- ad->offset = pos->init_offset;
- ad->source_type = base_type(C, init_expr->ctype);
- ad->result_type = init_expr->ctype;
- return linearize_initializer(C, ep, init_expr, ad);
-}
-
-static pseudo_t linearize_initializer(struct dmr_C *C, struct entrypoint *ep, struct expression *initializer, struct access_data *ad)
-{
- switch (initializer->type) {
- case EXPR_INITIALIZER: {
- struct expression *expr;
- FOR_EACH_PTR(initializer->expr_list, expr) {
- linearize_initializer(C, ep, expr, ad);
- } END_FOR_EACH_PTR(expr);
- break;
- }
- case EXPR_POS:
- linearize_position(C, ep, initializer, ad);
- break;
- default: {
- pseudo_t value = linearize_expression(C, ep, initializer);
- ad->source_type = base_type(C, initializer->ctype);
- ad->result_type = initializer->ctype;
- linearize_store_gen(C, ep, value, ad);
- return value;
- }
- }
-
- return VOID_PSEUDO(C);
-}
-
-static void linearize_argument(struct dmr_C *C, struct entrypoint *ep, struct symbol *arg, int nr)
-{
- struct access_data ad;
-
- memset(&ad, 0, sizeof ad);
- ad.source_type = arg;
- ad.result_type = arg;
- ad.address = symbol_pseudo(C, ep, arg);
- linearize_store_gen(C, ep, argument_pseudo(C, ep, nr, arg), &ad);
- finish_address_gen(ep, &ad);
-}
-
-static pseudo_t linearize_expression(struct dmr_C *C, struct entrypoint *ep, struct expression *expr)
-{
- if (!expr)
- return VOID_PSEUDO(C);
-
- C->L->current_pos = expr->pos;
- switch (expr->type) {
- case EXPR_SYMBOL:
- linearize_one_symbol(C, ep, expr->symbol);
- return add_symbol_address(C, ep, expr);
-
- case EXPR_VALUE:
- return dmrC_value_pseudo(C, expr->ctype, expr->value);
-
- case EXPR_STRING: case EXPR_FVALUE: case EXPR_LABEL:
- return add_setval(C, ep, expr->ctype, expr);
-
- case EXPR_STATEMENT:
- return linearize_statement(C, ep, expr->statement);
-
- case EXPR_CALL:
- return linearize_call_expression(C, ep, expr);
-
- case EXPR_BINOP:
- if (expr->op == SPECIAL_LOGICAL_AND || expr->op == SPECIAL_LOGICAL_OR)
- return linearize_binop_bool(C, ep, expr);
- return linearize_binop(C, ep, expr);
-
- case EXPR_LOGICAL:
- return linearize_logical(C, ep, expr);
-
- case EXPR_COMPARE:
- return linearize_compare(C, ep, expr);
-
- case EXPR_SELECT:
- return linearize_select(C, ep, expr);
-
- case EXPR_CONDITIONAL:
- if (!expr->cond_true)
- return linearize_short_conditional(C, ep, expr, expr->conditional, expr->cond_false);
-
- return linearize_conditional(C, ep, expr, expr->conditional,
- expr->cond_true, expr->cond_false);
-
- case EXPR_COMMA:
- linearize_expression(C, ep, expr->left);
- return linearize_expression(C, ep, expr->right);
-
- case EXPR_ASSIGNMENT:
- return linearize_assignment(C, ep, expr);
-
- case EXPR_PREOP:
- return linearize_preop(C, ep, expr);
-
- case EXPR_POSTOP:
- return linearize_postop(C, ep, expr);
-
- case EXPR_CAST:
- case EXPR_FORCE_CAST:
- case EXPR_IMPLIED_CAST:
- return linearize_cast(C, ep, expr);
-
- case EXPR_SLICE:
- return linearize_slice(C, ep, expr);
-
- case EXPR_INITIALIZER:
- case EXPR_POS:
- dmrC_warning(C, expr->pos, "unexpected initializer expression (%d %d)", expr->type, expr->op);
- return VOID_PSEUDO(C);
- default:
- dmrC_warning(C, expr->pos, "unknown expression (%d %d)", expr->type, expr->op);
- return VOID_PSEUDO(C);
- }
- return VOID_PSEUDO(C);
-}
-
-static pseudo_t linearize_one_symbol(struct dmr_C *C, struct entrypoint *ep, struct symbol *sym)
-{
- struct access_data ad;
- pseudo_t value;
-
- memset(&ad, 0, sizeof ad);
- if (!sym || !sym->initializer || sym->initialized)
- return VOID_PSEUDO(C);
-
- /* We need to output these puppies some day too.. */
- if (sym->ctype.modifiers & (MOD_STATIC | MOD_TOPLEVEL))
- return VOID_PSEUDO(C);
-
- sym->initialized = 1;
- ad.address = symbol_pseudo(C, ep, sym);
- value = linearize_initializer(C, ep, sym->initializer, &ad);
- finish_address_gen(ep, &ad);
- return value;
-}
-
-static pseudo_t linearize_compound_statement(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- pseudo_t pseudo;
- struct statement *s;
- struct symbol *ret = stmt->ret;
-
- pseudo = VOID_PSEUDO(C);
- FOR_EACH_PTR(stmt->stmts, s) {
- pseudo = linearize_statement(C, ep, s);
- } END_FOR_EACH_PTR(s);
-
- if (ret) {
- struct basic_block *bb = add_label(C, ep, ret);
- struct instruction *phi_node = dmrC_first_instruction(bb->insns);
-
- if (!phi_node)
- return pseudo;
-#if 0
- /* https://github.com/lucvoo/sparse/commit/1609176c9 */
- if (dmrC_pseudo_list_size(phi_node->phi_list)==1) {
- pseudo = dmrC_first_pseudo(phi_node->phi_list);
- assert(pseudo->type == PSEUDO_PHI);
- return pseudo->def->src1;
- }
-#endif
- return phi_node->target;
- }
-
- return pseudo;
-}
-
-static pseudo_t linearize_inlined_call(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- struct instruction *insn = alloc_instruction(C, OP_INLINED_CALL, 0);
- struct statement *args = stmt->args;
- struct basic_block *bb;
- pseudo_t pseudo;
-
- if (args) {
- struct symbol *sym;
-
- dmrC_concat_symbol_list(args->declaration, &ep->syms);
- FOR_EACH_PTR(args->declaration, sym) {
- pseudo_t value = linearize_one_symbol(C, ep, sym);
- dmrC_use_pseudo(C, insn, value, dmrC_add_pseudo(C, &insn->arguments, value));
- } END_FOR_EACH_PTR(sym);
- }
-
- insn->target = pseudo = linearize_compound_statement(C, ep, stmt);
- dmrC_use_pseudo(C, insn, symbol_pseudo(C, ep, stmt->inline_fn), &insn->func);
- bb = ep->active;
- if (bb && !bb->insns)
- bb->pos = stmt->pos;
- add_one_insn(C, ep, insn);
- return pseudo;
-}
-
-static pseudo_t linearize_context(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- struct instruction *insn = alloc_instruction(C, OP_CONTEXT, 0);
- struct expression *expr = stmt->expression;
- int value = 0;
-
- if (expr->type == EXPR_VALUE)
- value = (int) expr->value;
-
- insn->increment = value;
- insn->context_expr = stmt->context;
- add_one_insn(C, ep, insn);
- return VOID_PSEUDO(C);
-}
-
-static pseudo_t linearize_range(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- struct instruction *insn = alloc_instruction(C, OP_RANGE, 0);
-
- dmrC_use_pseudo(C, insn, linearize_expression(C, ep, stmt->range_expression), &insn->src1);
- dmrC_use_pseudo(C, insn, linearize_expression(C, ep, stmt->range_low), &insn->src2);
- dmrC_use_pseudo(C, insn, linearize_expression(C, ep, stmt->range_high), &insn->src3);
- add_one_insn(C, ep, insn);
- return VOID_PSEUDO(C);
-}
-
-static void add_asm_input(struct dmr_C *C, struct entrypoint *ep, struct instruction *insn, struct expression *expr,
- const char *constraint, const struct ident *ident)
-{
- pseudo_t pseudo = linearize_expression(C, ep, expr);
- struct asm_constraint *rule = (struct asm_constraint *)dmrC_allocator_allocate(&C->L->asm_constraint_allocator, 0);
-
- rule->ident = ident;
- rule->constraint = constraint;
- dmrC_use_pseudo(C, insn, pseudo, &rule->pseudo);
- ptrlist_add((struct ptr_list **)&insn->asm_rules->inputs, rule, &C->ptrlist_allocator);
-}
-
-static void add_asm_output(struct dmr_C *C, struct entrypoint *ep, struct instruction *insn, struct expression *expr,
- const char *constraint, const struct ident *ident)
-{
- struct access_data ad;
- pseudo_t pseudo = dmrC_alloc_pseudo(C, insn);
- struct asm_constraint *rule;
-
- memset(&ad, 0, sizeof ad);
- if (!expr || !linearize_address_gen(C, ep, expr, &ad))
- return;
- linearize_store_gen(C, ep, pseudo, &ad);
- finish_address_gen(ep, &ad);
- rule = (struct asm_constraint *) dmrC_allocator_allocate(&C->L->asm_constraint_allocator, 0);
- rule->ident = ident;
- rule->constraint = constraint;
- dmrC_use_pseudo(C, insn, pseudo, &rule->pseudo);
- ptrlist_add((struct ptr_list **)&insn->asm_rules->outputs, rule, &C->ptrlist_allocator);
-}
-
-static pseudo_t linearize_asm_statement(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- int state;
- struct expression *expr;
- struct instruction *insn;
- struct asm_rules *rules;
- const char *constraint;
- struct ident *ident;
-
- insn = alloc_instruction(C, OP_ASM, 0);
- expr = stmt->asm_string;
- if (!expr || expr->type != EXPR_STRING) {
- dmrC_warning(C, stmt->pos, "expected string in inline asm");
- return VOID_PSEUDO(C);
- }
- insn->string = expr->string->data;
-
- rules = (struct asm_rules *) dmrC_allocator_allocate(&C->L->asm_rules_allocator, 0);
- insn->asm_rules = rules;
-
- /* Gather the inputs.. */
- state = 0;
- ident = NULL;
- constraint = NULL;
- FOR_EACH_PTR(stmt->asm_inputs, expr) {
- switch (state) {
- case 0: /* Identifier */
- state = 1;
- ident = (struct ident *)expr;
- continue;
-
- case 1: /* Constraint */
- state = 2;
- constraint = expr ? expr->string->data : "";
- continue;
-
- case 2: /* Expression */
- state = 0;
- add_asm_input(C, ep, insn, expr, constraint, ident);
- }
- } END_FOR_EACH_PTR(expr);
-
- add_one_insn(C, ep, insn);
-
- /* Assign the outputs */
- state = 0;
- ident = NULL;
- constraint = NULL;
- FOR_EACH_PTR(stmt->asm_outputs, expr) {
- switch (state) {
- case 0: /* Identifier */
- state = 1;
- ident = (struct ident *)expr;
- continue;
-
- case 1: /* Constraint */
- state = 2;
- constraint = expr ? expr->string->data : "";
- continue;
-
- case 2:
- state = 0;
- add_asm_output(C, ep, insn, expr, constraint, ident);
- }
- } END_FOR_EACH_PTR(expr);
-
- return VOID_PSEUDO(C);
-}
-
-static int multijmp_cmp(void *ud, const void *_a, const void *_b)
-{
- (void) ud;
- const struct multijmp *a = (const struct multijmp *)_a;
- const struct multijmp *b = (const struct multijmp *)_b;
-
- // "default" case?
- if (a->begin > a->end) {
- if (b->begin > b->end)
- return 0;
- return 1;
- }
- if (b->begin > b->end)
- return -1;
- if (a->begin == b->begin) {
- if (a->end == b->end)
- return 0;
- return (a->end < b->end) ? -1 : 1;
- }
- return a->begin < b->begin ? -1 : 1;
-}
-
-static void sort_switch_cases(struct dmr_C *C, struct instruction *insn)
-{
- ptrlist_sort((struct ptr_list **)&insn->multijmp_list, C, multijmp_cmp);
-}
-
-static pseudo_t linearize_declaration(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- struct symbol *sym;
-
- dmrC_concat_symbol_list(stmt->declaration, &ep->syms);
-
- FOR_EACH_PTR(stmt->declaration, sym) {
- linearize_one_symbol(C, ep, sym);
- } END_FOR_EACH_PTR(sym);
- return VOID_PSEUDO(C);
-}
-
-static pseudo_t linearize_return(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- struct expression *expr = stmt->expression;
- struct basic_block *bb_return = get_bound_block(C, ep, stmt->ret_target);
- struct basic_block *active;
- pseudo_t src = linearize_expression(C, ep, expr);
- active = ep->active;
- if (active && src != VOID_PSEUDO(C)) {
- struct instruction *phi_node = dmrC_first_instruction(bb_return->insns);
- pseudo_t phi;
- if (!phi_node) {
- phi_node = alloc_typed_instruction(C, OP_PHI, expr->ctype);
- phi_node->target = dmrC_alloc_pseudo(C, phi_node);
- phi_node->bb = bb_return;
- dmrC_add_instruction(C, &bb_return->insns, phi_node);
- }
- phi = dmrC_alloc_phi(C, active, src, expr->ctype);
- phi->ident = C->S->return_ident;
- dmrC_use_pseudo(C, phi_node, phi, dmrC_add_pseudo(C, &phi_node->phi_list, phi));
- }
- add_goto(C, ep, bb_return);
- return VOID_PSEUDO(C);
-}
-
-static pseudo_t linearize_switch(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- struct symbol *sym;
- struct instruction *switch_ins;
- struct basic_block *switch_end = alloc_basic_block(C, ep, stmt->pos);
- struct basic_block *active, *default_case;
- struct expression *expr = stmt->switch_expression;
- struct multijmp *jmp;
- pseudo_t pseudo;
-
- pseudo = linearize_expression(C, ep, expr);
-
- active = ep->active;
- if (!dmrC_bb_reachable(active))
- return VOID_PSEUDO(C);
-
- switch_ins = alloc_typed_instruction(C, OP_SWITCH, expr->ctype);
- dmrC_use_pseudo(C, switch_ins, pseudo, &switch_ins->cond);
- add_one_insn(C, ep, switch_ins);
- finish_block(ep);
-
- default_case = NULL;
- FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
- struct statement *case_stmt = sym->stmt;
- struct basic_block *bb_case = get_bound_block(C, ep, sym);
-
- if (!case_stmt->case_expression) {
- default_case = bb_case;
- continue;
- } else {
- long long begin, end;
-
- begin = end = case_stmt->case_expression->value;
- if (case_stmt->case_to)
- end = case_stmt->case_to->value;
- if (begin > end)
- jmp = alloc_multijmp(C, bb_case, end, begin);
- else
- jmp = alloc_multijmp(C, bb_case, begin, end);
-
- }
- dmrC_add_multijmp(C, &switch_ins->multijmp_list, jmp);
- dmrC_add_bb(C, &bb_case->parents, active);
- dmrC_add_bb(C, &active->children, bb_case);
- } END_FOR_EACH_PTR(sym);
-
- bind_label(C, stmt->switch_break, switch_end, stmt->pos);
-
- /* And linearize the actual statement */
- linearize_statement(C, ep, stmt->switch_statement);
- set_activeblock(C, ep, switch_end);
-
- if (!default_case)
- default_case = switch_end;
-
- jmp = alloc_multijmp(C, default_case, 1, 0);
- dmrC_add_multijmp(C, &switch_ins->multijmp_list, jmp);
- dmrC_add_bb(C, &default_case->parents, active);
- dmrC_add_bb(C, &active->children, default_case);
- sort_switch_cases(C, switch_ins);
-
- return VOID_PSEUDO(C);
-}
-
-static pseudo_t linearize_iterator(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- 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;
- struct basic_block *loop_top, *loop_body, *loop_continue, *loop_end;
- struct symbol *sym;
-
- FOR_EACH_PTR(stmt->iterator_syms, sym) {
- linearize_one_symbol(C, ep, sym);
- } END_FOR_EACH_PTR(sym);
-
- dmrC_concat_symbol_list(stmt->iterator_syms, &ep->syms);
- linearize_statement(C, ep, pre_statement);
-
- loop_body = loop_top = alloc_basic_block(C, ep, stmt->pos);
- loop_continue = alloc_basic_block(C, ep, stmt->pos);
- loop_end = alloc_basic_block(C, ep, stmt->pos);
-
- /* An empty post-condition means that it's the same as the pre-condition */
- if (!post_condition) {
- loop_top = alloc_basic_block(C, ep, stmt->pos);
- set_activeblock(C, ep, loop_top);
- }
-
- if (pre_condition)
- linearize_cond_branch(C, ep, pre_condition, loop_body, loop_end);
-
- bind_label(C, stmt->iterator_continue, loop_continue, stmt->pos);
- bind_label(C, stmt->iterator_break, loop_end, stmt->pos);
-
- set_activeblock(C, ep, loop_body);
- linearize_statement(C, ep, statement);
- add_goto(C, ep, loop_continue);
-
- set_activeblock(C, ep, loop_continue);
- linearize_statement(C, ep, post_statement);
- if (!post_condition)
- add_goto(C, ep, loop_top);
- else
- linearize_cond_branch(C, ep, post_condition, loop_top, loop_end);
- set_activeblock(C, ep, loop_end);
-
- return VOID_PSEUDO(C);
-}
-
-static pseudo_t linearize_statement(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt)
-{
- struct basic_block *bb;
-
- if (!stmt)
- return VOID_PSEUDO(C);
-
- bb = ep->active;
- if (bb && !bb->insns)
- bb->pos = stmt->pos;
- C->L->current_pos = stmt->pos;
-
- switch (stmt->type) {
- case STMT_NONE:
- break;
-
- case STMT_DECLARATION:
- return linearize_declaration(C, ep, stmt);
-
- case STMT_CONTEXT:
- return linearize_context(C, ep, stmt);
-
- case STMT_RANGE:
- return linearize_range(C, ep, stmt);
-
- case STMT_EXPRESSION:
- return linearize_expression(C, ep, stmt->expression);
-
- case STMT_ASM:
- return linearize_asm_statement(C, ep, stmt);
-
- case STMT_RETURN:
- return linearize_return(C, ep, stmt);
-
- case STMT_CASE: {
- add_label(C, ep, stmt->case_label);
- linearize_statement(C, ep, stmt->case_statement);
- break;
- }
-
- case STMT_LABEL: {
- struct symbol *label = stmt->label_identifier;
-
- if (label->used) {
- bb = add_label(C, ep, label);
- }
- return linearize_statement(C, ep, stmt->label_statement);
- }
-
- case STMT_GOTO: {
- struct symbol *sym;
- struct expression *expr;
- struct instruction *goto_ins;
- struct basic_block *active;
- pseudo_t pseudo;
-
- active = ep->active;
- if (!dmrC_bb_reachable(active))
- break;
-
- if (stmt->goto_label) {
- add_goto(C, ep, get_bound_block(C, ep, stmt->goto_label));
- break;
- }
-
- expr = stmt->goto_expression;
- if (!expr)
- break;
-
- /* This can happen as part of simplification */
- if (expr->type == EXPR_LABEL) {
- add_goto(C, ep, get_bound_block(C, ep, expr->label_symbol));
- break;
- }
-
- pseudo = linearize_expression(C, ep, expr);
- goto_ins = alloc_instruction(C, OP_COMPUTEDGOTO, 0);
- dmrC_use_pseudo(C, goto_ins, pseudo, &goto_ins->target);
- add_one_insn(C, ep, goto_ins);
-
- FOR_EACH_PTR(stmt->target_list, sym) {
- struct basic_block *bb_computed = get_bound_block(C, ep, sym);
- struct multijmp *jmp = alloc_multijmp(C, bb_computed, 1, 0);
- dmrC_add_multijmp(C, &goto_ins->multijmp_list, jmp);
- dmrC_add_bb(C, &bb_computed->parents, ep->active);
- dmrC_add_bb(C, &active->children, bb_computed);
- } END_FOR_EACH_PTR(sym);
-
- finish_block(ep);
- break;
- }
-
- case STMT_COMPOUND:
- if (stmt->inline_fn)
- return linearize_inlined_call(C, ep, stmt);
- return linearize_compound_statement(C, ep, stmt);
-
- /*
- * This could take 'likely/unlikely' into account, and
- * switch the arms around appropriately..
- */
- case STMT_IF: {
- struct basic_block *bb_true, *bb_false, *endif;
- struct expression *cond = stmt->if_conditional;
-
- bb_true = alloc_basic_block(C, ep, stmt->pos);
- bb_false = endif = alloc_basic_block(C, ep, stmt->pos);
-
- linearize_cond_branch(C, ep, cond, bb_true, bb_false);
-
- set_activeblock(C, ep, bb_true);
- linearize_statement(C, ep, stmt->if_true);
-
- if (stmt->if_false) {
- endif = alloc_basic_block(C, ep, stmt->pos);
- add_goto(C, ep, endif);
- set_activeblock(C, ep, bb_false);
- linearize_statement(C, ep, stmt->if_false);
- }
- set_activeblock(C, ep, endif);
- break;
- }
-
- case STMT_SWITCH:
- return linearize_switch(C, ep, stmt);
-
- case STMT_ITERATOR:
- return linearize_iterator(C, ep, stmt);
-
- default:
- break;
- }
- return VOID_PSEUDO(C);
-}
-
-static struct entrypoint *linearize_fn(struct dmr_C *C, struct symbol *sym, struct symbol *base_type)
-{
- struct entrypoint *ep;
- struct basic_block *bb;
- struct symbol *arg;
- struct instruction *entry;
- pseudo_t result;
- int i;
-
- if (!base_type->stmt)
- return NULL;
-
- ep = alloc_entrypoint(C);
- bb = alloc_basic_block(C, ep, sym->pos);
-
- ep->name = sym;
- sym->ep = ep;
- set_activeblock(C, ep, bb);
-
- entry = alloc_instruction(C, OP_ENTRY, 0);
- add_one_insn(C, ep, entry);
- ep->entry = entry;
-
- dmrC_concat_symbol_list(base_type->arguments, &ep->syms);
-
- /* FIXME!! We should do something else about varargs.. */
- i = 0;
- FOR_EACH_PTR(base_type->arguments, arg) {
- linearize_argument(C, ep, arg, ++i);
- } END_FOR_EACH_PTR(arg);
-
- result = linearize_statement(C, ep, base_type->stmt);
- if (dmrC_bb_reachable(ep->active) && !dmrC_bb_terminated(ep->active)) {
- struct symbol *ret_type = base_type->ctype.base_type;
- struct instruction *insn = alloc_typed_instruction(C, OP_RET, ret_type);
-
- if (type_size(ret_type) > 0)
- dmrC_use_pseudo(C, insn, result, &insn->src);
- add_one_insn(C, ep, insn);
- }
-
- int show_details = C->verbose > 2;
-
- if (show_details) {
- printf("%s(%d): pre dmrC_kill_unreachable_bbs()\n", __FILE__, __LINE__);
- dmrC_show_entry(C, ep);
- }
- if (C->fdump_linearize) {
- if (C->fdump_linearize == 2)
- return ep;
- dmrC_show_entry(C, ep);
- }
-
-
- /*
- * Do trivial flow simplification - branches to
- * branches, kill dead basicblocks etc
- */
- dmrC_kill_unreachable_bbs(C, ep);
-
-#if 0
- if (C->optimize) {
-
- if (show_details) {
- printf("%s(%d): pre dmrC_simplify_symbol_usage()\n", __FILE__, __LINE__);
- dmrC_show_entry(C, ep);
- }
-
- /*
- * Turn symbols into pseudos
- */
- dmrC_simplify_symbol_usage(C, ep);
- repeat:
- /*
- * Remove trivial instructions, and try to CSE
- * the rest.
- */
- do {
- if (show_details) {
- printf("%s(%d): pre dmrC_cleanup_and_cse()\n", __FILE__, __LINE__);
- dmrC_show_entry(C, ep);
- }
- dmrC_cleanup_and_cse(C, ep);
- if (show_details) {
- printf("%s(%d): pre dmrC_pack_basic_blocks()\n", __FILE__, __LINE__);
- dmrC_show_entry(C, ep);
- }
- dmrC_pack_basic_blocks(C, ep);
- } while (C->L->repeat_phase & REPEAT_CSE);
-
- if (show_details) {
- printf("%s(%d): pre dmrC_kill_unreachable_bbs() and dmrC_vrfy_flow()\n", __FILE__, __LINE__);
- dmrC_show_entry(C, ep);
- }
- dmrC_kill_unreachable_bbs(C, ep);
- dmrC_vrfy_flow(ep);
-
- if (show_details) {
- printf("%s(%d): pre clear_symbol_pseudos()\n", __FILE__, __LINE__);
- dmrC_show_entry(C, ep);
- }
-
- /* Cleanup */
- clear_symbol_pseudos(ep);
-
- if (show_details) {
- printf("%s(%d): pre dmrC_track_pseudo_liveness()\n", __FILE__, __LINE__);
- dmrC_show_entry(C, ep);
- }
-
- /* And track pseudo register usage */
- dmrC_track_pseudo_liveness(C, ep);
-
- if (show_details) {
- printf("%s(%d): pre dmrC_simplify_flow()\n", __FILE__, __LINE__);
- dmrC_show_entry(C, ep);
- }
- /*
- * Some flow optimizations can only effectively
- * be done when we've done liveness analysis. But
- * if they trigger, we need to start all over
- * again
- */
- if (dmrC_simplify_flow(C, ep)) {
-
- if (show_details) {
- printf("%s(%d): pre dmrC_clear_liveness()\n", __FILE__, __LINE__);
- dmrC_show_entry(C, ep);
- }
-
- dmrC_clear_liveness(ep);
- goto repeat;
- }
- }
-#endif
-
- /* Finally, add deathnotes to pseudos now that we have them */
- if (C->dbg_dead)
- /* Note that this sets phi_users list on phisrc instructions which are relied upon by the
- LLVM backend */
- dmrC_track_pseudo_death(C, ep);
-
- return ep;
-}
-
-struct entrypoint *dmrC_linearize_symbol(struct dmr_C *C, struct symbol *sym)
-{
- struct symbol *base_type;
-
- if (!sym)
- return NULL;
- C->L->current_pos = sym->pos;
- base_type = sym->ctype.base_type;
- if (!base_type)
- return NULL;
- if (base_type->type == SYM_FN)
- return linearize_fn(C, sym, base_type);
- return NULL;
-}
-
-static void mark_bb_reachable(struct basic_block *bb, unsigned long generation)
-{
- struct basic_block *child;
-
- if (bb->generation == generation)
- return;
- bb->generation = generation;
- FOR_EACH_PTR(bb->children, child) {
- mark_bb_reachable(child, generation);
- } END_FOR_EACH_PTR(child);
-}
-
-void dmrC_kill_unreachable_bbs(struct dmr_C *C, struct entrypoint *ep)
-{
- struct basic_block *bb;
- unsigned long generation = ++C->L->bb_generation;
-
- mark_bb_reachable(ep->entry->bb, generation);
- FOR_EACH_PTR(ep->bbs, bb) {
- if (bb->generation == generation)
- continue;
- /* Mark it as being dead */
- dmrC_kill_bb(C, bb);
- bb->ep = NULL;
- DELETE_CURRENT_PTR(bb);
- } END_FOR_EACH_PTR(bb);
- ptrlist_pack((struct ptr_list **) &ep->bbs);
-}
-
-static int delete_pseudo_user_list_entry(struct dmr_C *C, struct pseudo_user_list **list, pseudo_t *entry, int count)
-{
- (void)C;
- struct pseudo_user *pu;
-
- FOR_EACH_PTR(*list, pu) {
- if (pu->userp == entry) {
- MARK_CURRENT_DELETED(struct pseudo_user *, pu);
- if (!--count)
- goto out;
- }
- } END_FOR_EACH_PTR(pu);
- assert(count <= 0);
-out:
- if (ptrlist_size((struct ptr_list *)*list) == 0)
- *list = NULL;
- return count;
-}
-
-static inline void remove_usage(struct dmr_C *C, pseudo_t p, pseudo_t *usep)
-{
- if (dmrC_has_use_list(p)) {
- delete_pseudo_user_list_entry(C, &p->users, usep, 1);
- if (!p->users)
- dmrC_kill_instruction(C, p->def);
- }
-}
-
-static inline void concat_user_list(struct pseudo_user_list *src, struct pseudo_user_list **dst)
-{
- ptrlist_concat((struct ptr_list *)src, (struct ptr_list **)dst);
-}
-
-void dmrC_convert_instruction_target(struct dmr_C *C, struct instruction *insn, pseudo_t src)
-{
- pseudo_t target;
- struct pseudo_user *pu;
- /*
- * Go through the "insn->users" list and replace them all..
- */
- target = insn->target;
- if (target == src)
- return;
- FOR_EACH_PTR(target->users, pu) {
- if (*pu->userp != VOID_PSEUDO(C)) {
- assert(*pu->userp == target);
- *pu->userp = src;
- }
- } END_FOR_EACH_PTR(pu);
- if (dmrC_has_use_list(src))
- concat_user_list(target->users, &src->users);
- target->users = NULL;
-}
-
-static void kill_defs(struct dmr_C *C, struct instruction *insn)
-{
- pseudo_t target = insn->target;
-
- if (!dmrC_has_use_list(target))
- return;
- if (target->def != insn)
- return;
-
- dmrC_convert_instruction_target(C, insn, VOID_PSEUDO(C));
-}
-
-void dmrC_kill_bb(struct dmr_C *C, struct basic_block *bb)
-{
- struct instruction *insn;
- struct basic_block *child, *parent;
-
- FOR_EACH_PTR(bb->insns, insn) {
- dmrC_kill_instruction_force(C, insn);
- kill_defs(C, insn);
- /*
- * We kill unreachable instructions even if they
- * otherwise aren't "killable" (e.g. volatile loads)
- */
- } END_FOR_EACH_PTR(insn);
- bb->insns = NULL;
-
- FOR_EACH_PTR(bb->children, child) {
- dmrC_remove_bb_from_list(&child->parents, bb, 0);
- } END_FOR_EACH_PTR(child);
- bb->children = NULL;
-
- FOR_EACH_PTR(bb->parents, parent) {
- dmrC_remove_bb_from_list(&parent->children, bb, 0);
- } END_FOR_EACH_PTR(parent);
- bb->parents = NULL;
-}
-
-
-void dmrC_kill_use(struct dmr_C *C, pseudo_t *usep)
-{
- if (usep) {
- pseudo_t p = *usep;
- *usep = VOID_PSEUDO(C);
- remove_usage(C, p, usep);
- }
-}
-
-static void kill_use_list(struct dmr_C *C, struct pseudo_list *list)
-{
- pseudo_t p;
- FOR_EACH_PTR(list, p) {
- if (p == VOID_PSEUDO(C))
- continue;
- dmrC_kill_use(C, THIS_ADDRESS(pseudo_t, p));
- } END_FOR_EACH_PTR(p);
-}
-
-/*
- * kill an instruction:
- * - remove it from its bb
- * - remove the usage of all its operands
- * If forse is zero, the normal case, the function only for
- * instructions free of (possible) side-effects. Otherwise
- * the function does that unconditionally (must only be used
- * for unreachable instructions.
- */
-void dmrC_kill_insn(struct dmr_C *C, struct instruction *insn, int force)
-{
- if (!insn || !insn->bb)
- return;
-
- switch (insn->opcode) {
- case OP_SEL:
- case OP_RANGE:
- dmrC_kill_use(C, &insn->src3);
- /* fall through */
-
- 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:
-
- /* Logical */
- 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:
- dmrC_kill_use(C, &insn->src2);
- /* fall through */
-
- case OP_CAST:
- case OP_SCAST:
- case OP_FPCAST:
- case OP_PTRCAST:
- case OP_SETVAL:
- case OP_NOT: case OP_NEG:
- case OP_SLICE:
- dmrC_kill_use(C, &insn->src1);
- break;
-
- case OP_PHI:
- kill_use_list(C, insn->phi_list);
- break;
- case OP_PHISOURCE:
- dmrC_kill_use(C, &insn->phi_src);
- break;
-
- case OP_SYMADDR:
- C->L->repeat_phase |= REPEAT_SYMBOL_CLEANUP;
- break;
-
- case OP_CBR:
- /* fall through */
- case OP_COMPUTEDGOTO:
- dmrC_kill_use(C, &insn->cond);
- break;
-
- case OP_CALL:
- if (!force) {
- /* a "pure" function can be killed too */
- if (!(insn->func->type == PSEUDO_SYM))
- return;
- if (!(insn->func->sym->ctype.modifiers & MOD_PURE))
- return;
- }
- kill_use_list(C, insn->arguments);
- if (insn->func->type == PSEUDO_REG)
- dmrC_kill_use(C, &insn->func);
- break;
-
- case OP_LOAD:
- if (!force && insn->type->ctype.modifiers & MOD_VOLATILE)
- return;
- dmrC_kill_use(C, &insn->src);
- break;
-
- case OP_STORE:
- if (!force)
- return;
- dmrC_kill_use(C, &insn->src);
- dmrC_kill_use(C, &insn->target);
- break;
-
- case OP_ENTRY:
- /* ignore */
- return;
-
- case OP_BR:
- default:
- break;
- }
-
- insn->bb = NULL;
- C->L->repeat_phase |= REPEAT_CSE;
- return;
-}
-
-void dmrC_init_linearizer(struct dmr_C *C) {
- struct linearizer_state_t *L = (struct linearizer_state_t *)calloc(1, sizeof(struct linearizer_state_t));
- dmrC_allocator_init(&L->asm_rules_allocator, "asm rules", sizeof(struct asm_rules),
- __alignof__(struct asm_rules), CHUNK);
- dmrC_allocator_init(&L->pseudo_allocator, "pseudos", sizeof(struct pseudo),
- __alignof__(struct pseudo), CHUNK);
- dmrC_allocator_init(&L->pseudo_user_allocator, "pseudo_users", sizeof(struct pseudo_user),
- __alignof__(struct pseudo_user), CHUNK);
- dmrC_allocator_init(&L->asm_constraint_allocator, "asm_constraints", sizeof(struct asm_constraint),
- __alignof__(struct asm_constraint), CHUNK);
- dmrC_allocator_init(&L->multijmp_allocator, "multijmps", sizeof(struct multijmp),
- __alignof__(struct multijmp), CHUNK);
- dmrC_allocator_init(&L->basic_block_allocator, "basic_blocks", sizeof(struct basic_block),
- __alignof__(struct basic_block), CHUNK);
- dmrC_allocator_init(&L->entrypoint_allocator, "entrypoints", sizeof(struct entrypoint),
- __alignof__(struct entrypoint), CHUNK);
- dmrC_allocator_init(&L->instruction_allocator, "instructions", sizeof(struct instruction),
- __alignof__(struct instruction), CHUNK);
- C->L = L;
-}
-
-void dmrC_destroy_linearizer(struct dmr_C *C) {
- struct linearizer_state_t *L = C->L;
- assert(L);
- dmrC_allocator_destroy(&L->asm_rules_allocator);
- dmrC_allocator_destroy(&L->pseudo_allocator);
- dmrC_allocator_destroy(&L->pseudo_user_allocator);
- dmrC_allocator_destroy(&L->asm_constraint_allocator);
- dmrC_allocator_destroy(&L->multijmp_allocator);
- dmrC_allocator_destroy(&L->basic_block_allocator);
- dmrC_allocator_destroy(&L->entrypoint_allocator);
- dmrC_allocator_destroy(&L->instruction_allocator);
- free(L);
- C->L = NULL;
-}
\ No newline at end of file
diff --git a/dmr_c/src/linearize.h b/dmr_c/src/linearize.h
deleted file mode 100644
index 0e94d28..0000000
--- a/dmr_c/src/linearize.h
+++ /dev/null
@@ -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
-#include
-#include
-#include
-#include
-
-#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 */
-
diff --git a/dmr_c/src/liveness.c b/dmr_c/src/liveness.c
deleted file mode 100644
index 73a0db0..0000000
--- a/dmr_c/src/liveness.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Register - track pseudo usage, maybe eventually try to do register
- * allocation.
- *
- * Copyright (C) 2004 Linus Torvalds
- */
-
-#include
-
-#include
-#include
-#include
-#include
-//#include
-
-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);
-}
diff --git a/dmr_c/src/memops.c b/dmr_c/src/memops.c
deleted file mode 100644
index d497ab9..0000000
--- a/dmr_c/src/memops.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * memops - try to combine memory ops.
- *
- * Copyright (C) 2004 Linus Torvalds
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-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);
-}
diff --git a/dmr_c/src/parse.c b/dmr_c/src/parse.c
deleted file mode 100644
index 5904d3a..0000000
--- a/dmr_c/src/parse.c
+++ /dev/null
@@ -1,2968 +0,0 @@
-/*
- * Stupid C parser, version 1e-6.
- *
- * Let's see how hard this is to do.
- *
- * Copyright (C) 2003 Transmeta Corp.
- * 2003-2004 Linus Torvalds
- * Copyright (C) 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
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-static struct token *statement(struct dmr_C *C, struct token *token, struct statement **tree);
-static struct token *handle_attributes(struct dmr_C *C, struct token *token, struct decl_state *ctx, unsigned int keywords);
-struct token *dmrC_compound_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-struct token *dmrC_initializer(struct dmr_C *C, struct expression **tree, struct token *token);
-
-typedef struct token *declarator_t(struct dmr_C *C, struct token *, struct decl_state *);
-static declarator_t
- struct_specifier, union_specifier, enum_specifier,
- attribute_specifier, typeof_specifier, parse_asm_declarator,
- typedef_specifier, inline_specifier, auto_specifier,
- register_specifier, static_specifier, extern_specifier,
- thread_specifier, const_qualifier, volatile_qualifier;
-
-static struct token *parse_if_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_return_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_loop_iterator(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_default_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_case_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_switch_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_for_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_while_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_do_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_goto_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_context_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_range_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *parse_asm_statement(struct dmr_C *C, struct token *token, struct statement *stmt);
-static struct token *toplevel_asm_declaration(struct dmr_C *C, struct token *token, struct symbol_list **list);
-static struct token *parse_static_assert(struct dmr_C *C, struct token *token, struct symbol_list **unused);
-static struct token *parameter_type_list(struct dmr_C *C, struct token *, struct symbol *);
-static struct token *identifier_list(struct dmr_C *C, struct token *, struct symbol *);
-static struct token *declarator(struct dmr_C *C, struct token *token, struct decl_state *ctx);
-
-typedef struct token *attr_t(struct dmr_C *C, struct token *, struct symbol *,
- struct decl_state *);
-
-static attr_t
- attribute_packed, attribute_aligned, attribute_modifier,
- attribute_bitwise,
- attribute_address_space, attribute_context,
- attribute_designated_init,
- attribute_transparent_union, ignore_attribute,
- attribute_mode, attribute_force;
-
-typedef struct symbol *to_mode_t(struct dmr_C *C, struct symbol *);
-
-static to_mode_t
- to_QI_mode, to_HI_mode, to_SI_mode, to_DI_mode, to_TI_mode, to_word_mode;
-
-enum {
- Set_T = 1,
- Set_S = 2,
- Set_Char = 4,
- Set_Int = 8,
- Set_Double = 16,
- Set_Float = 32,
- Set_Signed = 64,
- Set_Unsigned = 128,
- Set_Short = 256,
- Set_Long = 512,
- Set_Vlong = 1024,
- Set_Int128 = 2048,
- Set_Any = Set_T | Set_Short | Set_Long | Set_Signed | Set_Unsigned
-};
-
-enum {
- CInt = 0, CSInt, CUInt, CReal, CChar, CSChar, CUChar,
-};
-
-enum {
- SNone = 0, STypedef, SAuto, SRegister, SExtern, SStatic, SForced, SMax,
-};
-
-static struct symbol_op typedef_op = {
- .type = KW_MODIFIER,
- .declarator = typedef_specifier,
-};
-
-static struct symbol_op inline_op = {
- .type = KW_MODIFIER,
- .declarator = inline_specifier,
-};
-
-static declarator_t noreturn_specifier;
-static struct symbol_op noreturn_op = {
- .type = KW_MODIFIER,
- .declarator = noreturn_specifier,
-};
-
-static declarator_t alignas_specifier;
-static struct symbol_op alignas_op = {
- .type = KW_MODIFIER,
- .declarator = alignas_specifier,
-};
-
-static struct symbol_op auto_op = {
- .type = KW_MODIFIER,
- .declarator = auto_specifier,
-};
-
-static struct symbol_op register_op = {
- .type = KW_MODIFIER,
- .declarator = register_specifier,
-};
-
-static struct symbol_op static_op = {
- .type = KW_MODIFIER,
- .declarator = static_specifier,
-};
-
-static struct symbol_op extern_op = {
- .type = KW_MODIFIER,
- .declarator = extern_specifier,
-};
-
-static struct symbol_op thread_op = {
- .type = KW_MODIFIER,
- .declarator = thread_specifier,
-};
-
-static struct symbol_op const_op = {
- .type = KW_QUALIFIER,
- .declarator = const_qualifier,
-};
-
-static struct symbol_op volatile_op = {
- .type = KW_QUALIFIER,
- .declarator = volatile_qualifier,
-};
-
-static struct symbol_op restrict_op = {
- .type = KW_QUALIFIER,
-};
-
-static struct symbol_op typeof_op = {
- .type = KW_SPECIFIER,
- .declarator = typeof_specifier,
- .test = Set_Any,
- .set = Set_S|Set_T,
-};
-
-static struct symbol_op attribute_op = {
- .type = KW_ATTRIBUTE,
- .declarator = attribute_specifier,
-};
-
-static struct symbol_op struct_op = {
- .type = KW_SPECIFIER,
- .declarator = struct_specifier,
- .test = Set_Any,
- .set = Set_S|Set_T,
-};
-
-static struct symbol_op union_op = {
- .type = KW_SPECIFIER,
- .declarator = union_specifier,
- .test = Set_Any,
- .set = Set_S|Set_T,
-};
-
-static struct symbol_op enum_op = {
- .type = KW_SPECIFIER,
- .declarator = enum_specifier,
- .test = Set_Any,
- .set = Set_S|Set_T,
-};
-
-static struct symbol_op spec_op = {
- .type = KW_SPECIFIER | KW_EXACT,
- .test = Set_Any,
- .set = Set_S|Set_T,
-};
-
-static struct symbol_op char_op = {
- .type = KW_SPECIFIER,
- .test = Set_T|Set_Long|Set_Short,
- .set = Set_T|Set_Char,
- .cls = CChar,
-};
-
-static struct symbol_op int_op = {
- .type = KW_SPECIFIER,
- .test = Set_T,
- .set = Set_T|Set_Int,
-};
-
-static struct symbol_op double_op = {
- .type = KW_SPECIFIER,
- .test = Set_T|Set_Signed|Set_Unsigned|Set_Short|Set_Vlong,
- .set = Set_T|Set_Double,
- .cls = CReal,
-};
-
-static struct symbol_op float_op = {
- .type = KW_SPECIFIER | KW_SHORT,
- .test = Set_T|Set_Signed|Set_Unsigned|Set_Short|Set_Long,
- .set = Set_T|Set_Float,
- .cls = CReal,
-};
-
-static struct symbol_op short_op = {
- .type = KW_SPECIFIER | KW_SHORT,
- .test = Set_S|Set_Char|Set_Float|Set_Double|Set_Long|Set_Short,
- .set = Set_Short,
-};
-
-static struct symbol_op signed_op = {
- .type = KW_SPECIFIER,
- .test = Set_S|Set_Float|Set_Double|Set_Signed|Set_Unsigned,
- .set = Set_Signed,
- .cls = CSInt,
-};
-
-static struct symbol_op unsigned_op = {
- .type = KW_SPECIFIER,
- .test = Set_S|Set_Float|Set_Double|Set_Signed|Set_Unsigned,
- .set = Set_Unsigned,
- .cls = CUInt,
-};
-
-static struct symbol_op long_op = {
- .type = KW_SPECIFIER | KW_LONG,
- .test = Set_S|Set_Char|Set_Float|Set_Short|Set_Vlong,
- .set = Set_Long,
-};
-
-static struct symbol_op int128_op = {
- .type = KW_SPECIFIER | KW_LONG,
- .test = Set_S|Set_T|Set_Char|Set_Short|Set_Int|Set_Float|Set_Double|Set_Long|Set_Vlong|Set_Int128,
- .set = Set_T|Set_Int128,
-};
-
-static struct symbol_op if_op = {
- .statement = parse_if_statement,
-};
-
-static struct symbol_op return_op = {
- .statement = parse_return_statement,
-};
-
-static struct symbol_op loop_iter_op = {
- .statement = parse_loop_iterator,
-};
-
-static struct symbol_op default_op = {
- .statement = parse_default_statement,
-};
-
-static struct symbol_op case_op = {
- .statement = parse_case_statement,
-};
-
-static struct symbol_op switch_op = {
- .statement = parse_switch_statement,
-};
-
-static struct symbol_op for_op = {
- .statement = parse_for_statement,
-};
-
-static struct symbol_op while_op = {
- .statement = parse_while_statement,
-};
-
-static struct symbol_op do_op = {
- .statement = parse_do_statement,
-};
-
-static struct symbol_op goto_op = {
- .statement = parse_goto_statement,
-};
-
-static struct symbol_op __context___op = {
- .statement = parse_context_statement,
-};
-
-static struct symbol_op range_op = {
- .statement = parse_range_statement,
-};
-
-static struct symbol_op asm_op = {
- .type = KW_ASM,
- .declarator = parse_asm_declarator,
- .statement = parse_asm_statement,
- .toplevel = toplevel_asm_declaration,
-};
-
-static struct symbol_op static_assert_op = {
- .toplevel = parse_static_assert,
-};
-
-static struct symbol_op packed_op = {
- .attribute = attribute_packed,
-};
-
-static struct symbol_op aligned_op = {
- .attribute = attribute_aligned,
-};
-
-static struct symbol_op attr_mod_op = {
- .attribute = attribute_modifier,
-};
-
-static struct symbol_op attr_bitwise_op = {
- .attribute = attribute_bitwise,
-};
-
-static struct symbol_op attr_force_op = {
- .attribute = attribute_force,
-};
-
-static struct symbol_op address_space_op = {
- .attribute = attribute_address_space,
-};
-
-static struct symbol_op mode_op = {
- .attribute = attribute_mode,
-};
-
-static struct symbol_op context_op = {
- .attribute = attribute_context,
-};
-
-static struct symbol_op designated_init_op = {
- .attribute = attribute_designated_init,
-};
-
-static struct symbol_op transparent_union_op = {
- .attribute = attribute_transparent_union,
-};
-
-static struct symbol_op ignore_attr_op = {
- .attribute = ignore_attribute,
-};
-
-static struct symbol_op mode_QI_op = {
- .type = KW_MODE,
- .to_mode = to_QI_mode
-};
-
-static struct symbol_op mode_HI_op = {
- .type = KW_MODE,
- .to_mode = to_HI_mode
-};
-
-static struct symbol_op mode_SI_op = {
- .type = KW_MODE,
- .to_mode = to_SI_mode
-};
-
-static struct symbol_op mode_DI_op = {
- .type = KW_MODE,
- .to_mode = to_DI_mode
-};
-
-static struct symbol_op mode_TI_op = {
- .type = KW_MODE,
- .to_mode = to_TI_mode
-};
-
-static struct symbol_op mode_word_op = {
- .type = KW_MODE,
- .to_mode = to_word_mode
-};
-
-
-static const char *ignored_attributes[] = {
-
-#define GCC_ATTR(x) \
- STRINGIFY(x), \
- STRINGIFY(__##x##__),
-
-#include "gcc-attr-list.h"
-
-#undef GCC_ATTR
-
- "bounded",
- "__bounded__",
- "__noclone",
- "__nonnull",
- "__nothrow",
-};
-
-
-void dmrC_init_parser(struct dmr_C *C, int stream)
-{
- /* Using NS_TYPEDEF will also make the keyword a reserved one */
- struct init_keyword {
- const char *name;
- enum namespace_type ns;
- unsigned long modifiers;
- struct symbol_op *op;
- struct symbol *type;
- } keyword_table[] = {
-
- /* Type qualifiers */
- { "const", NS_TYPEDEF,.op = &const_op },
- { "__const", NS_TYPEDEF,.op = &const_op },
- { "__const__", NS_TYPEDEF,.op = &const_op },
- { "volatile", NS_TYPEDEF,.op = &volatile_op },
- { "__volatile", NS_TYPEDEF,.op = &volatile_op },
- { "__volatile__", NS_TYPEDEF,.op = &volatile_op },
-
- /* Typedef.. */
- { "typedef", NS_TYPEDEF,.op = &typedef_op },
-
- /* Type specifiers */
- { "void", NS_TYPEDEF,.type = &C->S->void_ctype,.op = &spec_op },
- { "char", NS_TYPEDEF,.op = &char_op },
- { "short", NS_TYPEDEF,.op = &short_op },
- { "int", NS_TYPEDEF,.op = &int_op },
- { "long", NS_TYPEDEF,.op = &long_op },
- { "float", NS_TYPEDEF,.op = &float_op },
- { "double", NS_TYPEDEF,.op = &double_op },
- { "signed", NS_TYPEDEF,.op = &signed_op },
- { "__signed", NS_TYPEDEF,.op = &signed_op },
- { "__signed__", NS_TYPEDEF,.op = &signed_op },
- { "unsigned", NS_TYPEDEF,.op = &unsigned_op },
- { "__int128", NS_TYPEDEF, .op = &int128_op },
- { "_Bool", NS_TYPEDEF,.type = &C->S->bool_ctype,.op = &spec_op },
-
- /* Predeclared types */
- { "__builtin_va_list", NS_TYPEDEF,.type = &C->S->ptr_ctype,.op = &spec_op },
- { "__builtin_ms_va_list", NS_TYPEDEF,.type = &C->S->ptr_ctype,.op = &spec_op },
- { "__int128_t", NS_TYPEDEF,.type = &C->S->lllong_ctype,.op = &spec_op },
- { "__uint128_t",NS_TYPEDEF,.type = &C->S->ulllong_ctype,.op = &spec_op },
-
-
- /* Extended types */
- { "typeof", NS_TYPEDEF,.op = &typeof_op },
- { "__typeof", NS_TYPEDEF,.op = &typeof_op },
- { "__typeof__", NS_TYPEDEF,.op = &typeof_op },
-
- { "__attribute", NS_TYPEDEF,.op = &attribute_op },
- { "__attribute__", NS_TYPEDEF,.op = &attribute_op },
-
- { "struct", NS_TYPEDEF,.op = &struct_op },
- { "union", NS_TYPEDEF,.op = &union_op },
- { "enum", NS_TYPEDEF,.op = &enum_op },
-
- { "inline", NS_TYPEDEF,.op = &inline_op },
- { "__inline", NS_TYPEDEF,.op = &inline_op },
- { "__inline__", NS_TYPEDEF,.op = &inline_op },
-
- { "_Noreturn", NS_TYPEDEF, .op = &noreturn_op },
-
- { "_Alignas", NS_TYPEDEF, .op = &alignas_op },
-
- /* Ignored for now.. */
- { "restrict", NS_TYPEDEF,.op = &restrict_op },
- { "__restrict", NS_TYPEDEF,.op = &restrict_op },
- { "__restrict__", NS_TYPEDEF,.op = &restrict_op },
-
- /* Static assertion */
- { "_Static_assert", NS_KEYWORD, .op = &static_assert_op },
- /* Storage class */
- { "auto", NS_TYPEDEF,.op = &auto_op },
- { "register", NS_TYPEDEF,.op = ®ister_op },
- { "static", NS_TYPEDEF,.op = &static_op },
- { "extern", NS_TYPEDEF,.op = &extern_op },
- { "__thread", NS_TYPEDEF,.op = &thread_op },
- { "_Thread_local", NS_TYPEDEF, .op = &thread_op },
-
- /* Statement */
- { "if", NS_KEYWORD,.op = &if_op },
- { "return", NS_KEYWORD,.op = &return_op },
- { "break", NS_KEYWORD,.op = &loop_iter_op },
- { "continue", NS_KEYWORD,.op = &loop_iter_op },
- { "default", NS_KEYWORD,.op = &default_op },
- { "case", NS_KEYWORD,.op = &case_op },
- { "switch", NS_KEYWORD,.op = &switch_op },
- { "for", NS_KEYWORD,.op = &for_op },
- { "while", NS_KEYWORD,.op = &while_op },
- { "do", NS_KEYWORD,.op = &do_op },
- { "goto", NS_KEYWORD,.op = &goto_op },
- { "__context__",NS_KEYWORD,.op = &__context___op },
- { "__range__", NS_KEYWORD,.op = &range_op },
- { "asm", NS_KEYWORD,.op = &asm_op },
- { "__asm", NS_KEYWORD,.op = &asm_op },
- { "__asm__", NS_KEYWORD,.op = &asm_op },
-
- /* Attribute */
- { "packed", NS_KEYWORD,.op = &packed_op },
- { "__packed__", NS_KEYWORD,.op = &packed_op },
- { "aligned", NS_KEYWORD,.op = &aligned_op },
- { "__aligned__",NS_KEYWORD,.op = &aligned_op },
- { "nocast", NS_KEYWORD, MOD_NOCAST,.op = &attr_mod_op },
- { "noderef", NS_KEYWORD, MOD_NODEREF,.op = &attr_mod_op },
- { "safe", NS_KEYWORD, MOD_SAFE,.op = &attr_mod_op },
- { "force", NS_KEYWORD,.op = &attr_force_op },
- { "bitwise", NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op },
- { "__bitwise__",NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op },
- { "address_space",NS_KEYWORD,.op = &address_space_op },
- { "mode", NS_KEYWORD,.op = &mode_op },
- { "context", NS_KEYWORD,.op = &context_op },
- { "designated_init", NS_KEYWORD,.op = &designated_init_op },
- { "__transparent_union__", NS_KEYWORD,.op = &transparent_union_op },
- { "noreturn", NS_KEYWORD, MOD_NORETURN,.op = &attr_mod_op },
- { "__noreturn__", NS_KEYWORD, MOD_NORETURN,.op = &attr_mod_op },
- { "pure", NS_KEYWORD, MOD_PURE,.op = &attr_mod_op },
- { "__pure__", NS_KEYWORD, MOD_PURE,.op = &attr_mod_op },
- { "const", NS_KEYWORD, MOD_PURE,.op = &attr_mod_op },
- { "__const", NS_KEYWORD, MOD_PURE,.op = &attr_mod_op },
- { "__const__", NS_KEYWORD, MOD_PURE,.op = &attr_mod_op },
-
- { "__mode__", NS_KEYWORD,.op = &mode_op },
- { "QI", NS_KEYWORD, MOD_CHAR,.op = &mode_QI_op },
- { "__QI__", NS_KEYWORD, MOD_CHAR,.op = &mode_QI_op },
- { "HI", NS_KEYWORD, MOD_SHORT,.op = &mode_HI_op },
- { "__HI__", NS_KEYWORD, MOD_SHORT,.op = &mode_HI_op },
- { "SI", NS_KEYWORD,.op = &mode_SI_op },
- { "__SI__", NS_KEYWORD,.op = &mode_SI_op },
- { "DI", NS_KEYWORD, MOD_LONGLONG,.op = &mode_DI_op },
- { "__DI__", NS_KEYWORD, MOD_LONGLONG,.op = &mode_DI_op },
- { "TI", NS_KEYWORD, MOD_LONGLONGLONG,.op = &mode_TI_op },
- { "__TI__", NS_KEYWORD, MOD_LONGLONGLONG,.op = &mode_TI_op },
- { "word", NS_KEYWORD, MOD_LONG,.op = &mode_word_op },
- { "__word__", NS_KEYWORD, MOD_LONG,.op = &mode_word_op },
- };
-
- C->P = (struct parse_state_t *) calloc(1, sizeof(struct parse_state_t));
-
- int i;
- for (i = 0; i < (int)ARRAY_SIZE(keyword_table); i++) {
- struct init_keyword *ptr = keyword_table + i;
- struct symbol *sym = dmrC_create_symbol(C->S, stream, ptr->name, SYM_KEYWORD, ptr->ns);
- sym->ident->keyword = 1;
- if (ptr->ns == NS_TYPEDEF)
- sym->ident->reserved = 1;
- sym->ctype.modifiers = ptr->modifiers;
- sym->ctype.base_type = ptr->type;
- sym->op = ptr->op;
- }
-
- for (i = 0; i < (int)ARRAY_SIZE(ignored_attributes); i++) {
- const char * name = ignored_attributes[i];
- struct symbol *sym = dmrC_create_symbol(C->S, stream, name, SYM_KEYWORD,
- NS_KEYWORD);
- if (!sym->op) {
- sym->ident->keyword = 1;
- sym->op = &ignore_attr_op;
- }
- }
-
- C->P->int_types[0] = &C->S->short_ctype;
- C->P->int_types[1] = &C->S->int_ctype;
- C->P->int_types[2] = &C->S->long_ctype;
- C->P->int_types[3] = &C->S->llong_ctype;
- C->P->signed_types[0] = &C->S->sshort_ctype;
- C->P->signed_types[1] = &C->S->sint_ctype;
- C->P->signed_types[2] = &C->S->slong_ctype;
- C->P->signed_types[3] = &C->S->sllong_ctype;
- C->P->signed_types[4] = &C->S->slllong_ctype;
- C->P->unsigned_types[0] = &C->S->ushort_ctype;
- C->P->unsigned_types[1] = &C->S->uint_ctype;
- C->P->unsigned_types[2] = &C->S->ulong_ctype;
- C->P->unsigned_types[3] = &C->S->ullong_ctype;
- C->P->unsigned_types[4] = &C->S->ulllong_ctype;
- C->P->real_types[0] = &C->S->float_ctype;
- C->P->real_types[1] = &C->S->double_ctype;
- C->P->real_types[2] = &C->S->ldouble_ctype;
- C->P->char_types[0] = &C->S->char_ctype;
- C->P->char_types[1] = &C->S->schar_ctype;
- C->P->char_types[2] = &C->S->uchar_ctype;
- C->P->types[0] = C->P->int_types + 1;
- C->P->types[1] = C->P->signed_types + 1;
- C->P->types[2] = C->P->unsigned_types + 1;
- C->P->types[3] = C->P->real_types + 1;
- C->P->types[4] = C->P->char_types;
- C->P->types[5] = C->P->char_types + 1;
- C->P->types[6] = C->P->char_types + 2;
-}
-
-void dmrC_destroy_parser(struct dmr_C *C) {
- free(C->P);
- C->P = NULL;
-}
-
-
-// Add a symbol to the list of function-local symbols
-static void fn_local_symbol(struct dmr_C *C, struct symbol *sym)
-{
- if (C->P->function_symbol_list)
- dmrC_add_symbol(C, C->P->function_symbol_list, sym);
-}
-
-static int SENTINEL_ATTR match_idents(struct dmr_C *C, struct token *token, ...)
-{
- va_list args;
- struct ident * next;
-
- (void) C;
-
- if (dmrC_token_type(token) != TOKEN_IDENT)
- return 0;
-
- va_start(args, token);
- do {
- next = va_arg(args, struct ident *);
- } while (next && token->ident != next);
- va_end(args);
-
- return next && token->ident == next;
-}
-
-
-struct statement *dmrC_alloc_statement(struct dmr_C *C, struct position pos, int type)
-{
- struct statement *stmt = (struct statement *)dmrC_allocator_allocate(&C->statement_allocator, 0);
- stmt->type = type;
- stmt->pos = pos;
- return stmt;
-}
-
-static struct token *struct_declaration_list(struct dmr_C *C, struct token *token, struct symbol_list **list);
-
-static void apply_modifiers(struct dmr_C *C, struct position pos, struct decl_state *ctx)
-{
- struct symbol *ctype;
- if (!ctx->mode)
- return;
- ctype = ctx->mode->to_mode(C, ctx->ctype.base_type);
- if (!ctype)
- dmrC_sparse_error(C, pos, "don't know how to apply mode to %s",
- dmrC_show_typename(C, ctx->ctype.base_type));
- else
- ctx->ctype.base_type = ctype;
-
-}
-
-static struct symbol * alloc_indirect_symbol(struct dmr_C *C, struct position pos, struct ctype *ctype, int type)
-{
- struct symbol *sym = dmrC_alloc_symbol(C->S, pos, type);
-
- sym->ctype.base_type = ctype->base_type;
- sym->ctype.modifiers = ctype->modifiers;
-
- ctype->base_type = sym;
- ctype->modifiers = 0;
- return sym;
-}
-
-/*
- * NOTE! NS_LABEL is not just a different namespace,
- * it also ends up using function scope instead of the
- * regular symbol scope.
- */
-struct symbol *dmrC_label_symbol(struct dmr_C *C, struct token *token)
-{
- struct symbol *sym = dmrC_lookup_symbol(token->ident, NS_LABEL);
- if (!sym) {
- sym = dmrC_alloc_symbol(C->S, token->pos, SYM_LABEL);
- dmrC_bind_symbol(C->S, sym, token->ident, NS_LABEL);
- fn_local_symbol(C, sym);
- }
- return sym;
-}
-
-static struct token *struct_union_enum_specifier(struct dmr_C *C, enum type type,
- struct token *token, struct decl_state *ctx,
- struct token *(*parse)(struct dmr_C *C, struct token *, struct symbol *))
-{
- struct symbol *sym;
- struct position *repos;
-
- token = handle_attributes(C, token, ctx, KW_ATTRIBUTE);
- if (dmrC_token_type(token) == TOKEN_IDENT) {
- sym = dmrC_lookup_symbol(token->ident, NS_STRUCT);
- if (!sym ||
- (dmrC_is_outer_scope(C, sym->scope) &&
- (dmrC_match_op(token->next,';') || dmrC_match_op(token->next,'{')))) {
- // Either a new symbol, or else an out-of-scope
- // symbol being redefined.
- sym = dmrC_alloc_symbol(C->S, token->pos, type);
- dmrC_bind_symbol(C->S, sym, token->ident, NS_STRUCT);
- }
- if (sym->type != type)
- dmrC_error_die(C, token->pos, "invalid tag applied to %s", dmrC_show_typename (C, sym));
- ctx->ctype.base_type = sym;
- repos = &token->pos;
- token = token->next;
- if (dmrC_match_op(token, '{')) {
- // The following test is actually wrong for empty
- // structs, but (1) they are not C99, (2) gcc does
- // the same thing, and (3) it's easier.
- if (sym->symbol_list)
- dmrC_error_die(C, token->pos, "redefinition of %s", dmrC_show_typename (C, sym));
- sym->pos = *repos;
- token = parse(C, token->next, sym);
- token = dmrC_expect_token(C, token, '}', "at end of struct-union-enum-specifier");
-
- // Mark the structure as needing re-examination
- sym->examined = 0;
- sym->endpos = token->pos;
- }
- return token;
- }
-
- // private struct/union/enum type
- if (!dmrC_match_op(token, '{')) {
- dmrC_sparse_error(C, token->pos, "expected declaration");
- ctx->ctype.base_type = &C->S->bad_ctype;
- return token;
- }
-
- sym = dmrC_alloc_symbol(C->S, token->pos, type);
- token = parse(C, token->next, sym);
- ctx->ctype.base_type = sym;
- token = dmrC_expect_token(C, token, '}', "at end of specifier");
- sym->endpos = token->pos;
-
- return token;
-}
-
-static struct token *parse_struct_declaration(struct dmr_C *C, struct token *token, struct symbol *sym)
-{
- struct symbol *field, *last = NULL;
- struct token *res;
- res = struct_declaration_list(C, token, &sym->symbol_list);
- FOR_EACH_PTR(sym->symbol_list, field) {
- if (!field->ident) {
- struct symbol *base = field->ctype.base_type;
- if (base && base->type == SYM_BITFIELD)
- continue;
- }
- if (last)
- last->next_subobject = field;
- last = field;
- } END_FOR_EACH_PTR(field);
- return res;
-}
-
-static struct token *parse_union_declaration(struct dmr_C *C, struct token *token, struct symbol *sym)
-{
- return struct_declaration_list(C, token, &sym->symbol_list);
-}
-
-static struct token *struct_specifier(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- return struct_union_enum_specifier(C, SYM_STRUCT, token, ctx, parse_struct_declaration);
-}
-
-static struct token *union_specifier(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- return struct_union_enum_specifier(C, SYM_UNION, token, ctx, parse_union_declaration);
-}
-
-
-typedef struct {
- int x;
- unsigned long long y;
-} Num;
-
-static void upper_boundary(Num *n, Num *v)
-{
- if (n->x > v->x)
- return;
- if (n->x < v->x) {
- *n = *v;
- return;
- }
- if (n->y < v->y)
- n->y = v->y;
-}
-
-static void lower_boundary(Num *n, Num *v)
-{
- if (n->x < v->x)
- return;
- if (n->x > v->x) {
- *n = *v;
- return;
- }
- if (n->y > v->y)
- n->y = v->y;
-}
-
-static int type_is_ok(struct dmr_C *C, struct symbol *type, Num *upper, Num *lower)
-{
- (void) C;
- int shift = type->bit_size;
- int is_unsigned = type->ctype.modifiers & MOD_UNSIGNED;
-
- if (!is_unsigned)
- shift--;
- if (upper->x == 0 && upper->y >> shift)
- return 0;
- if (lower->x == 0 || (!is_unsigned && (~lower->y >> shift) == 0))
- return 1;
- return 0;
-}
-
-static struct symbol *bigger_enum_type(struct dmr_C *C, struct symbol *s1, struct symbol *s2)
-{
- if (s1->bit_size < s2->bit_size) {
- s1 = s2;
- } else if (s1->bit_size == s2->bit_size) {
- if (s2->ctype.modifiers & MOD_UNSIGNED)
- s1 = s2;
- }
- if (s1->bit_size < C->target->bits_in_int)
- return &C->S->int_ctype;
- return s1;
-}
-
-static void cast_enum_list(struct dmr_C *C, struct symbol_list *list, struct symbol *base_type)
-{
- struct symbol *sym;
-
- FOR_EACH_PTR(list, sym) {
- struct expression *expr = sym->initializer;
- struct symbol *ctype;
- if (expr->type != EXPR_VALUE)
- continue;
- ctype = expr->ctype;
- if (ctype->bit_size == base_type->bit_size)
- continue;
- dmrC_cast_value(C, expr, base_type, expr, ctype);
- } END_FOR_EACH_PTR(sym);
-}
-
-static struct token *parse_enum_declaration(struct dmr_C *C, struct token *token, struct symbol *parent)
-{
- unsigned long long lastval = 0;
- struct symbol *ctype = NULL, *base_type = NULL;
- Num upper = {-1, 0}, lower = {1, 0};
-
- parent->examined = 1;
- parent->ctype.base_type = &C->S->int_ctype;
- while (dmrC_token_type(token) == TOKEN_IDENT) {
- struct expression *expr = NULL;
- struct token *next = token->next;
- struct symbol *sym;
-
- if (dmrC_match_op(next, '=')) {
- next = dmrC_constant_expression(C, next->next, &expr);
- lastval = dmrC_get_expression_value(C, expr);
- ctype = &C->S->void_ctype;
- if (expr && expr->ctype)
- ctype = expr->ctype;
- } else if (!ctype) {
- ctype = &C->S->int_ctype;
- } else if (dmrC_is_int_type(C->S, ctype)) {
- lastval++;
- } else {
- dmrC_error_die(C, token->pos, "can't increment the last enum member");
- }
-
- if (!expr) {
- expr = dmrC_alloc_expression(C, token->pos, EXPR_VALUE);
- expr->value = lastval;
- expr->ctype = ctype;
- }
-
- sym = dmrC_alloc_symbol(C->S, token->pos, SYM_NODE);
- dmrC_bind_symbol(C->S, sym, token->ident, NS_SYMBOL);
- sym->ctype.modifiers &= ~MOD_ADDRESSABLE;
- sym->initializer = expr;
- sym->enum_member = 1;
- sym->ctype.base_type = parent;
- dmrC_add_symbol(C, &parent->symbol_list, sym);
-
- if (base_type != &C->S->bad_ctype) {
- if (ctype->type == SYM_NODE)
- ctype = ctype->ctype.base_type;
- if (ctype->type == SYM_ENUM) {
- if (ctype == parent)
- ctype = base_type;
- else
- ctype = ctype->ctype.base_type;
- }
- /*
- * base_type rules:
- * - if all enums are of the same type, then
- * the base_type is that type (two first
- * cases)
- * - if enums are of different types, they
- * all have to be integer types, and the
- * base type is at least "int_ctype".
- * - otherwise the base_type is "bad_ctype".
- */
- if (!base_type) {
- base_type = ctype;
- } else if (ctype == base_type) {
- /* nothing */
- } else if (dmrC_is_int_type(C->S, base_type) && dmrC_is_int_type(C->S, ctype)) {
- base_type = bigger_enum_type(C, base_type, ctype);
- } else
- base_type = &C->S->bad_ctype;
- parent->ctype.base_type = base_type;
- }
- if (dmrC_is_int_type(C->S, base_type)) {
- Num v = {.y = lastval};
- if (ctype->ctype.modifiers & MOD_UNSIGNED)
- v.x = 0;
- else if ((long long)lastval >= 0)
- v.x = 0;
- else
- v.x = -1;
- upper_boundary(&upper, &v);
- lower_boundary(&lower, &v);
- }
- token = next;
-
- sym->endpos = token->pos;
-
- if (!dmrC_match_op(token, ','))
- break;
- token = token->next;
- }
- if (!base_type) {
- dmrC_sparse_error(C, token->pos, "bad enum definition");
- base_type = &C->S->bad_ctype;
- }
- else if (!dmrC_is_int_type(C->S, base_type))
- ; //base_type = base_type;
- else if (type_is_ok(C, base_type, &upper, &lower))
- ; //base_type = base_type;
- else if (type_is_ok(C, &C->S->int_ctype, &upper, &lower))
- base_type = &C->S->int_ctype;
- else if (type_is_ok(C, &C->S->uint_ctype, &upper, &lower))
- base_type = &C->S->uint_ctype;
- else if (type_is_ok(C, &C->S->long_ctype, &upper, &lower))
- base_type = &C->S->long_ctype;
- else if (type_is_ok(C, &C->S->ulong_ctype, &upper, &lower))
- base_type = &C->S->ulong_ctype;
- else if (type_is_ok(C, &C->S->llong_ctype, &upper, &lower))
- base_type = &C->S->llong_ctype;
- else if (type_is_ok(C, &C->S->ullong_ctype, &upper, &lower))
- base_type = &C->S->ullong_ctype;
- else
- base_type = &C->S->bad_ctype;
- parent->ctype.base_type = base_type;
- parent->ctype.modifiers |= (base_type->ctype.modifiers & MOD_UNSIGNED);
- parent->examined = 0;
-
- cast_enum_list(C, parent->symbol_list, base_type);
-
- return token;
-}
-
-static struct token *enum_specifier(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- struct token *ret = struct_union_enum_specifier(C, SYM_ENUM, token, ctx, parse_enum_declaration);
- struct ctype *ctype = &ctx->ctype.base_type->ctype;
-
- if (!ctype->base_type)
- ctype->base_type = &C->S->incomplete_ctype;
-
- return ret;
-}
-
-static void apply_ctype(struct dmr_C *C, struct position pos, struct ctype *thistype, struct ctype *ctype);
-struct token *dmrC_typename(struct dmr_C *C, struct token *token, struct symbol **p, int *forced);
-
-static struct token *typeof_specifier(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- struct symbol *sym;
-
- if (!dmrC_match_op(token, '(')) {
- dmrC_sparse_error(C, token->pos, "expected '(' after typeof");
- return token;
- }
- if (dmrC_lookup_type(token->next)) {
- token = dmrC_typename(C, token->next, &sym, NULL);
- ctx->ctype.base_type = sym->ctype.base_type;
- apply_ctype(C, token->pos, &sym->ctype, &ctx->ctype);
- } else {
- struct symbol *typeof_sym = dmrC_alloc_symbol(C->S, token->pos, SYM_TYPEOF);
- token = dmrC_parse_expression(C, token->next, &typeof_sym->initializer);
-
- typeof_sym->endpos = token->pos;
- if (!typeof_sym->initializer) {
- dmrC_sparse_error(C, token->pos, "expected expression after the '(' token");
- typeof_sym = &C->S->bad_ctype;
- }
- ctx->ctype.base_type = typeof_sym;
- }
- return dmrC_expect_token(C, token, ')', "after typeof");
-}
-
-static struct token *ignore_attribute(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- (void) ctx;
- (void) attr;
- struct expression *expr = NULL;
- if (dmrC_match_op(token, '('))
- token = dmrC_parens_expression(C, token, &expr, "in attribute");
- return token;
-}
-
-static struct token *attribute_packed(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- (void) C;
- (void) attr;
- if (!ctx->ctype.alignment)
- ctx->ctype.alignment = 1;
- return token;
-}
-
-static struct token *attribute_aligned(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- (void) attr;
- int alignment = C->target->max_alignment;
- struct expression *expr = NULL;
-
- if (dmrC_match_op(token, '(')) {
- token = dmrC_parens_expression(C, token, &expr, "in attribute");
- if (expr)
- alignment = (int) dmrC_const_expression_value(C, expr);
- }
- if (alignment & (alignment-1)) {
- dmrC_warning(C, token->pos, "I don't like non-power-of-2 alignments");
- return token;
- } else if (alignment > (int)ctx->ctype.alignment)
- ctx->ctype.alignment = alignment;
- return token;
-}
-
-static void apply_qualifier(struct dmr_C *C, struct position *pos, struct ctype *ctx, unsigned long qual)
-{
- if (ctx->modifiers & qual)
- dmrC_warning(C, *pos, "duplicate %s", dmrC_modifier_string(C, qual));
- ctx->modifiers |= qual;
-}
-
-static struct token *attribute_modifier(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- apply_qualifier(C, &token->pos, &ctx->ctype, attr->ctype.modifiers);
- return token;
-}
-
-static struct token *attribute_bitwise(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- if (C->Wbitwise)
- attribute_modifier(C, token, attr, ctx);
- return token;
-}
-
-static struct token *attribute_address_space(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- (void) attr;
- struct expression *expr = NULL;
- int as;
- token = dmrC_expect_token(C, token, '(', "after address_space attribute");
- token = dmrC_conditional_expression(C, token, &expr);
- if (expr) {
- as = (int) dmrC_const_expression_value(C, expr);
- if (C->Waddress_space && as)
- ctx->ctype.as = as;
- }
- token = dmrC_expect_token(C, token, ')', "after address_space attribute");
- return token;
-}
-
-static struct symbol *to_QI_mode(struct dmr_C *C, struct symbol *ctype)
-{
- if (ctype->ctype.base_type != &C->S->int_type)
- return NULL;
- if (ctype == &C->S->char_ctype)
- return ctype;
- return ctype->ctype.modifiers & MOD_UNSIGNED ? &C->S->uchar_ctype
- : &C->S->schar_ctype;
-}
-
-static struct symbol *to_HI_mode(struct dmr_C *C, struct symbol *ctype)
-{
- if (ctype->ctype.base_type != &C->S->int_type)
- return NULL;
- return ctype->ctype.modifiers & MOD_UNSIGNED ? &C->S->ushort_ctype
- : &C->S->sshort_ctype;
-}
-
-static struct symbol *to_SI_mode(struct dmr_C *C, struct symbol *ctype)
-{
- if (ctype->ctype.base_type != &C->S->int_type)
- return NULL;
- return ctype->ctype.modifiers & MOD_UNSIGNED ? &C->S->uint_ctype
- : &C->S->sint_ctype;
-}
-
-static struct symbol *to_DI_mode(struct dmr_C *C, struct symbol *ctype)
-{
- if (ctype->ctype.base_type != &C->S->int_type)
- return NULL;
- return ctype->ctype.modifiers & MOD_UNSIGNED ? &C->S->ullong_ctype
- : &C->S->sllong_ctype;
-}
-
-static struct symbol *to_TI_mode(struct dmr_C *C, struct symbol *ctype)
-{
- if (ctype->ctype.base_type != &C->S->int_type)
- return NULL;
- return ctype->ctype.modifiers & MOD_UNSIGNED ? &C->S->ulllong_ctype
- : &C->S->slllong_ctype;
-}
-
-static struct symbol *to_word_mode(struct dmr_C *C, struct symbol *ctype)
-{
- if (ctype->ctype.base_type != &C->S->int_type)
- return NULL;
- return ctype->ctype.modifiers & MOD_UNSIGNED ? &C->S->ulong_ctype
- : &C->S->slong_ctype;
-}
-
-static struct token *attribute_mode(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- (void) attr;
- token = dmrC_expect_token(C, token, '(', "after mode attribute");
- if (dmrC_token_type(token) == TOKEN_IDENT) {
- struct symbol *mode = dmrC_lookup_keyword(token->ident, NS_KEYWORD);
- if (mode && mode->op->type == KW_MODE)
- ctx->mode = mode->op;
- else
- dmrC_sparse_error(C, token->pos, "unknown mode attribute %s\n", dmrC_show_ident(C, token->ident));
- token = token->next;
- } else
- dmrC_sparse_error(C, token->pos, "expect attribute mode symbol\n");
- token = dmrC_expect_token(C, token, ')', "after mode attribute");
- return token;
-}
-
-static struct token *attribute_context(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- (void) attr;
- struct context *context = (struct context *)dmrC_allocator_allocate(&C->S->context_allocator, 0);
- struct expression *args[3];
- int argc = 0;
-
- token = dmrC_expect_token(C, token, '(', "after context attribute");
- while (!dmrC_match_op(token, ')')) {
- struct expression *expr = NULL;
- token = dmrC_conditional_expression(C, token, &expr);
- if (!expr)
- break;
- if (argc < 3)
- args[argc++] = expr;
- if (!dmrC_match_op(token, ','))
- break;
- token = token->next;
- }
-
- switch(argc) {
- case 0:
- dmrC_sparse_error(C, token->pos, "expected context input/output values");
- break;
- case 1:
- context->in = (unsigned int)dmrC_get_expression_value(C, args[0]);
- break;
- case 2:
- context->in = (unsigned int)dmrC_get_expression_value(C, args[0]);
- context->out = (unsigned int)dmrC_get_expression_value(C, args[1]);
- break;
- case 3:
- context->context_expr = args[0];
- context->in = (unsigned int)dmrC_get_expression_value(C, args[1]);
- context->out = (unsigned int)dmrC_get_expression_value(C, args[2]);
- break;
- }
-
- if (argc)
- dmrC_add_context(C, &ctx->ctype.contexts, context);
-
- token = dmrC_expect_token(C, token, ')', "after context attribute");
- return token;
-}
-
-static struct token *attribute_designated_init(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- (void) attr;
- if (ctx->ctype.base_type && ctx->ctype.base_type->type == SYM_STRUCT)
- ctx->ctype.base_type->designated_init = 1;
- else
- dmrC_warning(C, token->pos, "attribute designated_init applied to non-structure type");
- return token;
-}
-
-static struct token *attribute_transparent_union(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- (void) attr;
- if (C->Wtransparent_union)
- dmrC_warning(C, token->pos, "attribute __transparent_union__");
- if (ctx->ctype.base_type && ctx->ctype.base_type->type == SYM_UNION)
- ctx->ctype.base_type->transparent_union = 1;
- else
- dmrC_warning(C, token->pos, "attribute __transparent_union__ applied to non-union type");
- return token;
-}
-
-static struct token *recover_unknown_attribute(struct dmr_C *C, struct token *token)
-{
- struct expression *expr = NULL;
-
- if (C->Wunknown_attribute)
- dmrC_warning(C, token->pos, "attribute '%s': unknown attribute", dmrC_show_ident(C, token->ident));
- token = token->next;
- if (dmrC_match_op(token, '('))
- token = dmrC_parens_expression(C, token, &expr, "in attribute");
- return token;
-}
-
-static struct token *attribute_specifier(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- token = dmrC_expect_token(C, token, '(', "after attribute");
- token = dmrC_expect_token(C, token, '(', "after attribute");
-
- for (;;) {
- struct ident *attribute_name;
- struct symbol *attr;
-
- if (dmrC_eof_token(token))
- break;
- if (dmrC_match_op(token, ';'))
- break;
- if (dmrC_token_type(token) != TOKEN_IDENT)
- break;
- attribute_name = token->ident;
- attr = dmrC_lookup_keyword(attribute_name, NS_KEYWORD);
- if (attr && attr->op->attribute)
- token = attr->op->attribute(C, token->next, attr, ctx);
- else
- token = recover_unknown_attribute(C, token);
-
- if (!dmrC_match_op(token, ','))
- break;
- token = token->next;
- }
-
- token = dmrC_expect_token(C, token, ')', "after attribute");
- token = dmrC_expect_token(C, token, ')', "after attribute");
- return token;
-}
-
-static const char *storage_class[] =
-{
- [STypedef] = "typedef",
- [SAuto] = "auto",
- [SExtern] = "extern",
- [SStatic] = "static",
- [SRegister] = "register",
- [SForced] = "[force]"
-};
-
-static unsigned long storage_modifiers(struct dmr_C *C, struct decl_state *ctx)
-{
- (void) C;
- static unsigned long mod[SMax] =
- {
- [SAuto] = MOD_AUTO,
- [SExtern] = MOD_EXTERN,
- [SStatic] = MOD_STATIC,
- [SRegister] = MOD_REGISTER
- };
- return mod[ctx->storage_class] | (ctx->is_inline ? MOD_INLINE : 0)
- | (ctx->is_tls ? MOD_TLS : 0);
-}
-
-static void set_storage_class(struct dmr_C *C, struct position *pos, struct decl_state *ctx, int klass)
-{
- /* __thread can be used alone, or with extern or static */
- if (ctx->is_tls && (klass != SStatic && klass != SExtern)) {
- dmrC_sparse_error(C, *pos, "__thread can only be used alone, or with "
- "extern or static");
- return;
- }
-
- if (!ctx->storage_class) {
- ctx->storage_class = klass;
- return;
- }
- if (ctx->storage_class == klass)
- dmrC_sparse_error(C, *pos, "duplicate %s", storage_class[klass]);
- else
- dmrC_sparse_error(C, *pos, "multiple storage classes");
-}
-
-static struct token *typedef_specifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- set_storage_class(C, &next->pos, ctx, STypedef);
- return next;
-}
-
-static struct token *auto_specifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- set_storage_class(C, &next->pos, ctx, SAuto);
- return next;
-}
-
-static struct token *register_specifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- set_storage_class(C, &next->pos, ctx, SRegister);
- return next;
-}
-
-static struct token *static_specifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- set_storage_class(C, &next->pos, ctx, SStatic);
- return next;
-}
-
-static struct token *extern_specifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- set_storage_class(C, &next->pos, ctx, SExtern);
- return next;
-}
-
-static struct token *thread_specifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- /* This GCC extension can be used alone, or with extern or static */
- if (!ctx->storage_class || ctx->storage_class == SStatic
- || ctx->storage_class == SExtern) {
- ctx->is_tls = 1;
- } else {
- dmrC_sparse_error(C, next->pos, "__thread can only be used alone, or "
- "with extern or static");
- }
-
- return next;
-}
-
-static struct token *attribute_force(struct dmr_C *C, struct token *token, struct symbol *attr, struct decl_state *ctx)
-{
- (void) attr;
- set_storage_class(C, &token->pos, ctx, SForced);
- return token;
-}
-
-static struct token *inline_specifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- (void) C;
- ctx->is_inline = 1;
- return next;
-}
-
-static struct token *noreturn_specifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- apply_qualifier(C, &next->pos, &ctx->ctype, MOD_NORETURN);
- return next;
-}
-
-static struct token *alignas_specifier(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- int alignment = 0;
-
- if (!dmrC_match_op(token, '(')) {
- dmrC_sparse_error(C, token->pos, "expected '(' after _Alignas");
- return token;
- }
- if (dmrC_lookup_type(token->next)) {
- struct symbol *sym = NULL;
- token = dmrC_typename(C, token->next, &sym, NULL);
- sym = dmrC_examine_symbol_type(C->S, sym);
- alignment = sym->ctype.alignment;
- token = dmrC_expect_token(C, token, ')', "after _Alignas(...");
- } else {
- struct expression *expr = NULL;
- token = dmrC_parens_expression(C, token, &expr, "after _Alignas");
- if (!expr)
- return token;
- alignment = (int) dmrC_const_expression_value(C, expr);
- }
-
- if (alignment < 0) {
- dmrC_warning(C, token->pos, "non-positive alignment");
- return token;
- }
- if (alignment & (alignment-1)) {
- dmrC_warning(C, token->pos, "non-power-of-2 alignment");
- return token;
- }
- if (alignment > (int)ctx->ctype.alignment)
- ctx->ctype.alignment = alignment;
- return token;
-}
-static struct token *const_qualifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- apply_qualifier(C, &next->pos, &ctx->ctype, MOD_CONST);
- return next;
-}
-
-static struct token *volatile_qualifier(struct dmr_C *C, struct token *next, struct decl_state *ctx)
-{
- apply_qualifier(C, &next->pos, &ctx->ctype, MOD_VOLATILE);
- return next;
-}
-
-static void apply_ctype(struct dmr_C *C, struct position pos, struct ctype *thistype, struct ctype *ctype)
-{
- unsigned long mod = thistype->modifiers;
-
- if (mod)
- apply_qualifier(C, &pos, ctype, mod);
-
- /* Context */
- dmrC_concat_context_list(thistype->contexts, &ctype->contexts);
-
- /* Alignment */
- if (thistype->alignment > ctype->alignment)
- ctype->alignment = thistype->alignment;
-
- /* Address space */
- if (thistype->as)
- ctype->as = thistype->as;
-}
-
-static void specifier_conflict(struct dmr_C *C, struct position pos, int what, struct ident *news)
-{
- const char *old;
- if (what & (Set_S | Set_T))
- goto Catch_all;
- if (what & Set_Char)
- old = "char";
- else if (what & Set_Double)
- old = "double";
- else if (what & Set_Float)
- old = "float";
- else if (what & Set_Signed)
- old = "signed";
- else if (what & Set_Unsigned)
- old = "unsigned";
- else if (what & Set_Short)
- old = "short";
- else if (what & Set_Long)
- old = "long";
- else
- old = "long long";
- dmrC_sparse_error(C, pos, "impossible combination of type specifiers: %s %s",
- old, dmrC_show_ident(C, news));
- return;
-
-Catch_all:
- dmrC_sparse_error(C, pos, "two or more data types in declaration specifiers");
-}
-
-struct symbol *dmrC_ctype_integer(struct dmr_C *C, int size, int want_unsigned)
-{
- return C->P->types[want_unsigned ? CUInt : CInt][size];
-}
-
-static struct token *handle_qualifiers(struct dmr_C *C, struct token *t, struct decl_state *ctx)
-{
- while (dmrC_token_type(t) == TOKEN_IDENT) {
- struct symbol *s = dmrC_lookup_symbol(t->ident, NS_TYPEDEF);
- if (!s)
- break;
- if (s->type != SYM_KEYWORD)
- break;
- if (!(s->op->type & (KW_ATTRIBUTE | KW_QUALIFIER)))
- break;
- t = t->next;
- if (s->op->declarator)
- t = s->op->declarator(C, t, ctx);
- }
- return t;
-}
-
-static struct token *declaration_specifiers(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- int seen = 0;
- int cls = CInt;
- int size = 0;
-
- while (dmrC_token_type(token) == TOKEN_IDENT) {
- struct symbol *s = dmrC_lookup_symbol(token->ident,
- NS_TYPEDEF | NS_SYMBOL);
- if (!s || !(s->ns & NS_TYPEDEF))
- break;
- if (s->type != SYM_KEYWORD) {
- if (seen & Set_Any)
- break;
- seen |= Set_S | Set_T;
- ctx->ctype.base_type = s->ctype.base_type;
- apply_ctype(C, token->pos, &s->ctype, &ctx->ctype);
- token = token->next;
- continue;
- }
- if (s->op->type & KW_SPECIFIER) {
- if (seen & s->op->test) {
- specifier_conflict(C, token->pos,
- seen & s->op->test,
- token->ident);
- break;
- }
- seen |= s->op->set;
- cls += s->op->cls;
- if (s->op->set & Set_Int128)
- size = 2;
- if (s->op->type & KW_SHORT) {
- size = -1;
- } else if (s->op->type & KW_LONG && size++) {
- if (cls == CReal) {
- specifier_conflict(C, token->pos,
- Set_Vlong,
- C->S->double_ident);
- break;
- }
- seen |= Set_Vlong;
- }
- }
- token = token->next;
- if (s->op->declarator)
- token = s->op->declarator(C, token, ctx);
- if (s->op->type & KW_EXACT) {
- ctx->ctype.base_type = s->ctype.base_type;
- ctx->ctype.modifiers |= s->ctype.modifiers;
- }
- }
-
- if (!(seen & Set_S)) { /* not set explicitly? */
- struct symbol *base = &C->S->incomplete_ctype;
- if (seen & Set_Any)
- base = C->P->types[cls][size];
- ctx->ctype.base_type = base;
- }
-
- if (ctx->ctype.modifiers & MOD_BITWISE) {
- struct symbol *type;
- ctx->ctype.modifiers &= ~MOD_BITWISE;
- if (!dmrC_is_int_type(C->S, ctx->ctype.base_type)) {
- dmrC_sparse_error(C, token->pos, "invalid modifier");
- return token;
- }
- type = dmrC_alloc_symbol(C->S, token->pos, SYM_BASETYPE);
- *type = *ctx->ctype.base_type;
- type->ctype.modifiers &= ~MOD_SPECIFIER;
- type->ctype.base_type = ctx->ctype.base_type;
- type->type = SYM_RESTRICT;
- ctx->ctype.base_type = type;
- dmrC_create_fouled(C->S, type);
- }
- return token;
-}
-
-static struct token *abstract_array_static_declarator(struct dmr_C *C, struct token *token, int *has_static)
-{
- while (token->ident == C->S->static_ident) {
- if (*has_static)
- dmrC_sparse_error(C, token->pos, "duplicate array static declarator");
-
- *has_static = 1;
- token = token->next;
- }
- return token;
-
-}
-static struct token *abstract_array_declarator(struct dmr_C *C, struct token *token, struct symbol *sym)
-{
- struct expression *expr = NULL;
- int has_static = 0;
-
- token = abstract_array_static_declarator(C, token, &has_static);
-
- if (match_idents(C, token, C->S->restrict_ident, C->S->__restrict_ident, C->S->__restrict___ident, NULL))
- token = abstract_array_static_declarator(C, token->next, &has_static);
- token = dmrC_parse_expression(C, token, &expr);
- sym->array_size = expr;
- return token;
-}
-
-static struct token *skip_attribute(struct dmr_C *C, struct token *token)
-{
- (void) C;
- token = token->next;
- if (dmrC_match_op(token, '(')) {
- int depth = 1;
- token = token->next;
- while (depth && !dmrC_eof_token(token)) {
- if (dmrC_token_type(token) == TOKEN_SPECIAL) {
- if (token->special == '(')
- depth++;
- else if (token->special == ')')
- depth--;
- }
- token = token->next;
- }
- }
- return token;
-}
-
-static struct token *skip_attributes(struct dmr_C *C, struct token *token)
-{
- struct symbol *keyword;
- for (;;) {
- if (dmrC_token_type(token) != TOKEN_IDENT)
- break;
- keyword = dmrC_lookup_keyword(token->ident, NS_KEYWORD | NS_TYPEDEF);
- if (!keyword || keyword->type != SYM_KEYWORD)
- break;
- if (!(keyword->op->type & KW_ATTRIBUTE))
- break;
- token = dmrC_expect_token(C, token->next, '(', "after attribute");
- token = dmrC_expect_token(C, token, '(', "after attribute");
- for (;;) {
- if (dmrC_eof_token(token))
- break;
- if (dmrC_match_op(token, ';'))
- break;
- if (dmrC_token_type(token) != TOKEN_IDENT)
- break;
- token = skip_attribute(C, token);
- if (!dmrC_match_op(token, ','))
- break;
- token = token->next;
- }
- token = dmrC_expect_token(C, token, ')', "after attribute");
- token = dmrC_expect_token(C, token, ')', "after attribute");
- }
- return token;
-}
-
-static struct token *handle_attributes(struct dmr_C *C, struct token *token, struct decl_state *ctx, unsigned int keywords)
-{
- struct symbol *keyword;
- for (;;) {
- if (dmrC_token_type(token) != TOKEN_IDENT)
- break;
- keyword = dmrC_lookup_keyword(token->ident, NS_KEYWORD | NS_TYPEDEF);
- if (!keyword || keyword->type != SYM_KEYWORD)
- break;
- if (!(keyword->op->type & keywords))
- break;
- token = keyword->op->declarator(C, token->next, ctx);
- keywords &= KW_ATTRIBUTE;
- }
- return token;
-}
-
-static int is_nested(struct dmr_C *C, struct token *token, struct token **p,
- int prefer_abstract)
-{
- /*
- * This can be either a parameter list or a grouping.
- * For the direct (non-abstract) case, we know if must be
- * a parameter list if we already saw the identifier.
- * For the abstract case, we know if must be a parameter
- * list if it is empty or starts with a type.
- */
- struct token *next = token->next;
-
- *p = next = skip_attributes(C, next);
-
- if (dmrC_token_type(next) == TOKEN_IDENT) {
- if (dmrC_lookup_type(next))
- return !prefer_abstract;
- return 1;
- }
-
- if (dmrC_match_op(next, ')') || dmrC_match_op(next, SPECIAL_ELLIPSIS))
- return 0;
-
- return 1;
-}
-
-enum kind {
- Empty, K_R, Proto, Bad_Func,
-};
-
-static enum kind which_func(struct dmr_C *C, struct token *token,
- struct ident **n,
- int prefer_abstract)
-{
- struct token *next = token->next;
-
- if (dmrC_token_type(next) == TOKEN_IDENT) {
- if (dmrC_lookup_type(next))
- return Proto;
- /* identifier list not in definition; complain */
- if (prefer_abstract)
- dmrC_warning(C, token->pos,
- "identifier list not in definition");
- return K_R;
- }
-
- if (dmrC_token_type(next) != TOKEN_SPECIAL)
- return Bad_Func;
-
- if (next->special == ')') {
- /* don't complain about those */
- if (!n || dmrC_match_op(next->next, ';'))
- return Empty;
- dmrC_warning(C, next->pos,
- "non-ANSI function declaration of function '%s'",
- dmrC_show_ident(C, *n));
- return Empty;
- }
-
- if (next->special == SPECIAL_ELLIPSIS) {
- dmrC_warning(C, next->pos,
- "variadic functions must have one named argument");
- return Proto;
- }
-
- return Bad_Func;
-}
-
-static struct token *direct_declarator(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- struct ctype *ctype = &ctx->ctype;
- struct token *next;
- struct ident **p = ctx->ident;
-
- if (ctx->ident && dmrC_token_type(token) == TOKEN_IDENT) {
- *ctx->ident = token->ident;
- token = token->next;
- } else if (dmrC_match_op(token, '(') &&
- is_nested(C, token, &next, ctx->prefer_abstract)) {
- struct symbol *base_type = ctype->base_type;
- if (token->next != next)
- next = handle_attributes(C, token->next, ctx,
- KW_ATTRIBUTE);
- token = declarator(C, next, ctx);
- token = dmrC_expect_token(C, token, ')', "in nested declarator");
- while (ctype->base_type != base_type)
- ctype = &ctype->base_type->ctype;
- p = NULL;
- }
-
- if (dmrC_match_op(token, '(')) {
- enum kind kind = which_func(C, token, p, ctx->prefer_abstract);
- struct symbol *fn;
- fn = alloc_indirect_symbol(C, token->pos, ctype, SYM_FN);
- token = token->next;
- if (kind == K_R)
- token = identifier_list(C, token, fn);
- else if (kind == Proto)
- token = parameter_type_list(C, token, fn);
- token = dmrC_expect_token(C, token, ')', "in function declarator");
- fn->endpos = token->pos;
- return token;
- }
-
- while (dmrC_match_op(token, '[')) {
- struct symbol *array;
- array = alloc_indirect_symbol(C, token->pos, ctype, SYM_ARRAY);
- token = abstract_array_declarator(C, token->next, array);
- token = dmrC_expect_token(C, token, ']', "in abstract_array_declarator");
- array->endpos = token->pos;
- ctype = &array->ctype;
- }
- return token;
-}
-
-static struct token *pointer(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- while (dmrC_match_op(token,'*')) {
- struct symbol *ptr = dmrC_alloc_symbol(C->S, token->pos, SYM_PTR);
- ptr->ctype.modifiers = ctx->ctype.modifiers;
- ptr->ctype.base_type = ctx->ctype.base_type;
- ptr->ctype.as = ctx->ctype.as;
- ptr->ctype.contexts = ctx->ctype.contexts;
- ctx->ctype.modifiers = 0;
- ctx->ctype.base_type = ptr;
- ctx->ctype.as = 0;
- ctx->ctype.contexts = NULL;
- ctx->ctype.alignment = 0;
-
- token = handle_qualifiers(C, token->next, ctx);
- ctx->ctype.base_type->endpos = token->pos;
- }
- return token;
-}
-
-static struct token *declarator(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- token = pointer(C, token, ctx);
- return direct_declarator(C, token, ctx);
-}
-
-static struct token *handle_bitfield(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- struct ctype *ctype = &ctx->ctype;
- struct expression *expr;
- struct symbol *bitfield;
- long long width;
-
- if (ctype->base_type != &C->S->int_type && !dmrC_is_int_type(C->S, ctype->base_type)) {
- dmrC_sparse_error(C, token->pos, "invalid bitfield specifier for type %s.",
- dmrC_show_typename(C, ctype->base_type));
- // Parse this to recover gracefully.
- return dmrC_conditional_expression(C, token->next, &expr);
- }
-
- bitfield = alloc_indirect_symbol(C, token->pos, ctype, SYM_BITFIELD);
- token = dmrC_conditional_expression(C, token->next, &expr);
- width = dmrC_const_expression_value(C, expr);
- bitfield->bit_size = (int) width;
-
- if (width < 0 || width > INT_MAX) {
- dmrC_sparse_error(C, token->pos, "invalid bitfield width, %lld.", width);
- width = -1;
- } else if (*ctx->ident && width == 0) {
- dmrC_sparse_error(C, token->pos, "invalid named zero-width bitfield `%s'",
- dmrC_show_ident(C, *ctx->ident));
- width = -1;
- } else if (*ctx->ident) {
- struct symbol *base_type = bitfield->ctype.base_type;
- struct symbol *bitfield_type = base_type == &C->S->int_type ? bitfield : base_type;
- int is_signed = !(bitfield_type->ctype.modifiers & MOD_UNSIGNED);
- if (C->Wone_bit_signed_bitfield && width == 1 && is_signed) {
- // Valid values are either {-1;0} or {0}, depending on integer
- // representation. The latter makes for very efficient code...
- dmrC_sparse_error(C, token->pos, "dubious one-bit signed bitfield");
- }
- if (C->Wdefault_bitfield_sign &&
- bitfield_type->type != SYM_ENUM &&
- !(bitfield_type->ctype.modifiers & MOD_EXPLICITLY_SIGNED) &&
- is_signed) {
- // The sign of bitfields is unspecified by default.
- dmrC_warning(C, token->pos, "dubious bitfield without explicit `signed' or `unsigned'");
- }
- }
- bitfield->bit_size = (int) width;
- bitfield->endpos = token->pos;
- return token;
-}
-
-static struct token *declaration_list(struct dmr_C *C, struct token *token, struct symbol_list **list)
-{
- struct decl_state ctx = {.prefer_abstract = 0};
- struct ctype saved;
- unsigned long mod;
-
- token = declaration_specifiers(C, token, &ctx);
- mod = storage_modifiers(C, &ctx);
- saved = ctx.ctype;
- for (;;) {
- struct symbol *decl = dmrC_alloc_symbol(C->S, token->pos, SYM_NODE);
- ctx.ident = &decl->ident;
-
- token = declarator(C, token, &ctx);
- if (dmrC_match_op(token, ':'))
- token = handle_bitfield(C, token, &ctx);
-
- token = handle_attributes(C, token, &ctx, KW_ATTRIBUTE);
- apply_modifiers(C, token->pos, &ctx);
-
- decl->ctype = ctx.ctype;
- decl->ctype.modifiers |= mod;
- decl->endpos = token->pos;
- dmrC_add_symbol(C, list, decl);
- if (!dmrC_match_op(token, ','))
- break;
- token = token->next;
- ctx.ctype = saved;
- }
- return token;
-}
-
-static struct token *struct_declaration_list(struct dmr_C *C, struct token *token, struct symbol_list **list)
-{
- while (!dmrC_match_op(token, '}')) {
- if (dmrC_match_ident(token, C->S->_Static_assert_ident)) {
- token = parse_static_assert(C, token, NULL);
- continue;
- }
- if (!dmrC_match_op(token, ';'))
- token = declaration_list(C, token, list);
- if (!dmrC_match_op(token, ';')) {
- dmrC_sparse_error(C, token->pos, "expected ; at end of declaration");
- break;
- }
- token = token->next;
- }
- return token;
-}
-
-static struct token *parameter_declaration(struct dmr_C *C, struct token *token, struct symbol *sym)
-{
- struct decl_state ctx = {.prefer_abstract = 1};
-
- token = declaration_specifiers(C, token, &ctx);
- ctx.ident = &sym->ident;
- token = declarator(C, token, &ctx);
- token = handle_attributes(C, token, &ctx, KW_ATTRIBUTE);
- apply_modifiers(C, token->pos, &ctx);
- sym->ctype = ctx.ctype;
- sym->ctype.modifiers |= storage_modifiers(C, &ctx);
- sym->endpos = token->pos;
- sym->forced_arg = ctx.storage_class == SForced;
- return token;
-}
-
-struct token *dmrC_typename(struct dmr_C *C, struct token *token, struct symbol **p, int *forced)
-{
- struct decl_state ctx = {.prefer_abstract = 1};
- int klass;
- struct symbol *sym = dmrC_alloc_symbol(C->S, token->pos, SYM_NODE);
- *p = sym;
- token = declaration_specifiers(C, token, &ctx);
- token = declarator(C, token, &ctx);
- apply_modifiers(C, token->pos, &ctx);
- sym->ctype = ctx.ctype;
- sym->endpos = token->pos;
- klass = ctx.storage_class;
- if (forced) {
- *forced = 0;
- if (klass == SForced) {
- *forced = 1;
- klass = 0;
- }
- }
- if (klass)
- dmrC_warning(C, sym->pos, "storage class in typename (%s %s)",
- storage_class[klass], dmrC_show_typename(C, sym));
- return token;
-}
-
-static struct token *expression_statement(struct dmr_C *C, struct token *token, struct expression **tree)
-{
- token = dmrC_parse_expression(C, token, tree);
- return dmrC_expect_token(C, token, ';', "at end of statement");
-}
-
-static struct token *parse_asm_operands(struct dmr_C *C, struct token *token, struct statement *stmt,
- struct expression_list **inout)
-{
- (void) stmt;
- struct expression *expr;
-
- /* Allow empty operands */
- if (dmrC_match_op(token->next, ':') || dmrC_match_op(token->next, ')'))
- return token->next;
- do {
- struct ident *ident = NULL;
- if (dmrC_match_op(token->next, '[') &&
- dmrC_token_type(token->next->next) == TOKEN_IDENT &&
- dmrC_match_op(token->next->next->next, ']')) {
- ident = token->next->next->ident;
- token = token->next->next->next;
- }
- dmrC_add_expression(C, inout, (struct expression *)ident); /* UGGLEE!!! */
- token = dmrC_primary_expression(C, token->next, &expr);
- dmrC_add_expression(C, inout, expr);
- token = dmrC_parens_expression(C, token, &expr, "in asm parameter");
- dmrC_add_expression(C, inout, expr);
- } while (dmrC_match_op(token, ','));
- return token;
-}
-
-static struct token *parse_asm_clobbers(struct dmr_C *C, struct token *token, struct statement *stmt,
- struct expression_list **clobbers)
-{
- (void) stmt;
- struct expression *expr;
-
- do {
- token = dmrC_primary_expression(C, token->next, &expr);
- if (expr)
- dmrC_add_expression(C, clobbers, expr);
- } while (dmrC_match_op(token, ','));
- return token;
-}
-
-static struct token *parse_asm_labels(struct dmr_C *C, struct token *token, struct statement *stmt,
- struct symbol_list **labels)
-{
- struct symbol *label;
- (void) stmt;
- do {
- token = token->next; /* skip ':' and ',' */
- if (dmrC_token_type(token) != TOKEN_IDENT)
- return token;
- label = dmrC_label_symbol(C, token);
- dmrC_add_symbol(C, labels, label);
- token = token->next;
- } while (dmrC_match_op(token, ','));
- return token;
-}
-
-static struct token *parse_asm_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- int is_goto = 0;
-
- token = token->next;
- stmt->type = STMT_ASM;
- if (match_idents(C, token, C->S->__volatile___ident, C->S->__volatile_ident, C->S->volatile_ident, NULL)) {
- token = token->next;
- }
- if (dmrC_token_type(token) == TOKEN_IDENT && token->ident == C->S->goto_ident) {
- is_goto = 1;
- token = token->next;
- }
- token = dmrC_expect_token(C, token, '(', "after asm");
- token = dmrC_parse_expression(C, token, &stmt->asm_string);
- if (dmrC_match_op(token, ':'))
- token = parse_asm_operands(C, token, stmt, &stmt->asm_outputs);
- if (dmrC_match_op(token, ':'))
- token = parse_asm_operands(C, token, stmt, &stmt->asm_inputs);
- if (dmrC_match_op(token, ':'))
- token = parse_asm_clobbers(C, token, stmt, &stmt->asm_clobbers);
- if (is_goto && dmrC_match_op(token, ':'))
- token = parse_asm_labels(C, token, stmt, &stmt->asm_labels);
- token = dmrC_expect_token(C, token, ')', "after asm");
- return dmrC_expect_token(C, token, ';', "at end of asm-statement");
-}
-
-static struct token *parse_asm_declarator(struct dmr_C *C, struct token *token, struct decl_state *ctx)
-{
- (void) ctx;
- struct expression *expr;
- token = dmrC_expect_token(C, token, '(', "after asm");
- token = dmrC_parse_expression(C, token->next, &expr);
- token = dmrC_expect_token(C, token, ')', "after asm");
- return token;
-}
-
-static struct token *parse_static_assert(struct dmr_C *C, struct token *token, struct symbol_list **unused)
-{
- (void) unused;
- struct expression *cond = NULL, *message = NULL;
-
- token = dmrC_expect_token(C, token->next, '(', "after _Static_assert");
- token = dmrC_constant_expression(C, token, &cond);
- if (!cond)
- dmrC_sparse_error(C, token->pos, "Expected constant expression");
- token = dmrC_expect_token(C, token, ',', "after conditional expression in _Static_assert");
- token = dmrC_parse_expression(C, token, &message);
- if (!message || message->type != EXPR_STRING) {
- struct position pos;
-
- pos = message ? message->pos : token->pos;
- dmrC_sparse_error(C, pos, "bad or missing string literal");
- cond = NULL;
- }
- token = dmrC_expect_token(C, token, ')', "after diagnostic message in _Static_assert");
-
- token = dmrC_expect_token(C, token, ';', "after _Static_assert()");
-
- if (cond && !dmrC_const_expression_value(C, cond) && cond->type == EXPR_VALUE)
- dmrC_sparse_error(C, cond->pos, "static assertion failed: %s",
- dmrC_show_string(C, message->string));
- return token;
-}
-
-/* Make a statement out of an expression */
-static struct statement *make_statement(struct dmr_C *C, struct expression *expr)
-{
- struct statement *stmt;
-
- if (!expr)
- return NULL;
- stmt = dmrC_alloc_statement(C, expr->pos, STMT_EXPRESSION);
- stmt->expression = expr;
- return stmt;
-}
-
-/*
- * All iterators have two symbols associated with them:
- * the "continue" and "break" symbols, which are targets
- * for continue and break statements respectively.
- *
- * They are in a special name-space, but they follow
- * all the normal visibility rules, so nested iterators
- * automatically work right.
- */
-static void start_iterator(struct dmr_C *C, struct statement *stmt)
-{
- struct symbol *cont, *brk;
-
- dmrC_start_symbol_scope(C);
- cont = dmrC_alloc_symbol(C->S, stmt->pos, SYM_NODE);
- dmrC_bind_symbol(C->S, cont, C->S->continue_ident, NS_ITERATOR);
- brk = dmrC_alloc_symbol(C->S, stmt->pos, SYM_NODE);
- dmrC_bind_symbol(C->S, brk, C->S->break_ident, NS_ITERATOR);
-
- stmt->type = STMT_ITERATOR;
- stmt->iterator_break = brk;
- stmt->iterator_continue = cont;
- fn_local_symbol(C, brk);
- fn_local_symbol(C, cont);
-}
-
-static void end_iterator(struct dmr_C *C, struct statement *stmt)
-{
- (void) stmt;
- dmrC_end_symbol_scope(C);
-}
-
-static struct statement *start_function(struct dmr_C *C, struct symbol *sym)
-{
- struct symbol *ret;
- struct statement *stmt = dmrC_alloc_statement(C, sym->pos, STMT_COMPOUND);
-
- dmrC_start_function_scope(C);
- ret = dmrC_alloc_symbol(C->S, sym->pos, SYM_NODE);
- ret->ctype = sym->ctype.base_type->ctype;
- ret->ctype.modifiers &= ~(MOD_STORAGE | MOD_CONST | MOD_VOLATILE | MOD_TLS | MOD_INLINE | MOD_ADDRESSABLE | MOD_NOCAST | MOD_NODEREF | MOD_ACCESSED | MOD_TOPLEVEL);
- ret->ctype.modifiers |= (MOD_AUTO | MOD_REGISTER);
- dmrC_bind_symbol(C->S, ret, C->S->return_ident, NS_ITERATOR);
- stmt->ret = ret;
- fn_local_symbol(C, ret);
-
- // Currently parsed symbol for __func__/__FUNCTION__/__PRETTY_FUNCTION__
- C->current_fn = sym;
-
- return stmt;
-}
-
-static void end_function(struct dmr_C *C, struct symbol *sym)
-{
- (void) sym;
- C->current_fn = NULL;
- dmrC_end_function_scope(C);
-}
-
-/*
- * A "switch()" statement, like an iterator, has a
- * the "break" symbol associated with it. It works
- * exactly like the iterator break - it's the target
- * for any break-statements in scope, and means that
- * "break" handling doesn't even need to know whether
- * it's breaking out of an iterator or a switch.
- *
- * In addition, the "case" symbol is a marker for the
- * case/default statements to find the switch statement
- * that they are associated with.
- */
-static void start_switch(struct dmr_C *C, struct statement *stmt)
-{
- struct symbol *brk, *switch_case;
-
- dmrC_start_symbol_scope(C);
- brk = dmrC_alloc_symbol(C->S, stmt->pos, SYM_NODE);
- dmrC_bind_symbol(C->S, brk, C->S->break_ident, NS_ITERATOR);
-
- switch_case = dmrC_alloc_symbol(C->S, stmt->pos, SYM_NODE);
- dmrC_bind_symbol(C->S, switch_case, C->S->case_ident, NS_ITERATOR);
- switch_case->stmt = stmt;
-
- stmt->type = STMT_SWITCH;
- stmt->switch_break = brk;
- stmt->switch_case = switch_case;
-
- fn_local_symbol(C, brk);
- fn_local_symbol(C, switch_case);
-}
-
-static void end_switch(struct dmr_C *C, struct statement *stmt)
-{
- if (!stmt->switch_case->symbol_list)
- dmrC_warning(C, stmt->pos, "switch with no cases");
- dmrC_end_symbol_scope(C);
-}
-
-static void add_case_statement(struct dmr_C *C, struct statement *stmt)
-{
- struct symbol *target = dmrC_lookup_symbol(C->S->case_ident, NS_ITERATOR);
- struct symbol *sym;
-
- if (!target) {
- dmrC_sparse_error(C, stmt->pos, "not in switch scope");
- stmt->type = STMT_NONE;
- return;
- }
- sym = dmrC_alloc_symbol(C->S, stmt->pos, SYM_NODE);
- dmrC_add_symbol(C, &target->symbol_list, sym);
- sym->stmt = stmt;
- stmt->case_label = sym;
- fn_local_symbol(C, sym);
-}
-
-static struct token *parse_return_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- struct symbol *target = dmrC_lookup_symbol(C->S->return_ident, NS_ITERATOR);
-
- if (!target)
- dmrC_error_die(C, token->pos, "internal error: return without a function target");
- stmt->type = STMT_RETURN;
- stmt->ret_target = target;
- return expression_statement(C, token->next, &stmt->ret_value);
-}
-
-static void validate_for_loop_decl(struct dmr_C *C, struct symbol *sym)
-{
- unsigned long storage = sym->ctype.modifiers & MOD_STORAGE;
-
- if (storage & ~(MOD_AUTO | MOD_REGISTER)) {
- const char *name = dmrC_show_ident(C, sym->ident);
- dmrC_sparse_error(C, sym->pos, "non-local var '%s' in for-loop initializer", name);
- sym->ctype.modifiers &= ~MOD_STORAGE;
- }
-}
-static struct token *parse_for_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- struct symbol_list *syms;
- struct expression *e1, *e2, *e3;
- struct statement *iterator;
-
- start_iterator(C, stmt);
- token = dmrC_expect_token(C, token->next, '(', "after 'for'");
-
- syms = NULL;
- e1 = NULL;
- /* C99 variable declaration? */
- if (dmrC_lookup_type(token)) {
- token = dmrC_external_declaration(C, token, &syms, validate_for_loop_decl);
- } else {
- token = dmrC_parse_expression(C, token, &e1);
- token = dmrC_expect_token(C, token, ';', "in 'for'");
- }
- token = dmrC_parse_expression(C, token, &e2);
- token = dmrC_expect_token(C, token, ';', "in 'for'");
- token = dmrC_parse_expression(C, token, &e3);
- token = dmrC_expect_token(C, token, ')', "in 'for'");
- token = statement(C, token, &iterator);
-
- stmt->iterator_syms = syms;
- stmt->iterator_pre_statement = make_statement(C, e1);
- stmt->iterator_pre_condition = e2;
- stmt->iterator_post_statement = make_statement(C, e3);
- stmt->iterator_post_condition = NULL;
- stmt->iterator_statement = iterator;
- end_iterator(C, stmt);
-
- return token;
-}
-
-static struct token *parse_while_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- struct expression *expr;
- struct statement *iterator;
-
- start_iterator(C, stmt);
- token = dmrC_parens_expression(C, token->next, &expr, "after 'while'");
- token = statement(C, token, &iterator);
-
- stmt->iterator_pre_condition = expr;
- stmt->iterator_post_condition = NULL;
- stmt->iterator_statement = iterator;
- end_iterator(C, stmt);
-
- return token;
-}
-
-static struct token *parse_do_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- struct expression *expr;
- struct statement *iterator;
-
- start_iterator(C, stmt);
- token = statement(C, token->next, &iterator);
- if (dmrC_token_type(token) == TOKEN_IDENT && token->ident == C->S->while_ident)
- token = token->next;
- else
- dmrC_sparse_error(C, token->pos, "expected 'while' after 'do'");
- token = dmrC_parens_expression(C, token, &expr, "after 'do-while'");
-
- stmt->iterator_post_condition = expr;
- stmt->iterator_statement = iterator;
- end_iterator(C, stmt);
-
- if (iterator && iterator->type != STMT_COMPOUND && C->Wdo_while)
- dmrC_warning(C, iterator->pos, "do-while statement is not a compound statement");
-
- return dmrC_expect_token(C, token, ';', "after statement");
-}
-
-static struct token *parse_if_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- stmt->type = STMT_IF;
- token = dmrC_parens_expression(C, token->next, &stmt->if_conditional, "after if");
- token = statement(C, token, &stmt->if_true);
- if (dmrC_token_type(token) != TOKEN_IDENT)
- return token;
- if (token->ident != C->S->else_ident)
- return token;
- return statement(C, token->next, &stmt->if_false);
-}
-
-static inline struct token *case_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- stmt->type = STMT_CASE;
- token = dmrC_expect_token(C, token, ':', "after default/case");
- add_case_statement(C, stmt);
- return statement(C, token, &stmt->case_statement);
-}
-
-static struct token *parse_case_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- token = dmrC_parse_expression(C, token->next, &stmt->case_expression);
- if (dmrC_match_op(token, SPECIAL_ELLIPSIS))
- token = dmrC_parse_expression(C, token->next, &stmt->case_to);
- return case_statement(C, token, stmt);
-}
-
-static struct token *parse_default_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- return case_statement(C, token->next, stmt);
-}
-
-static struct token *parse_loop_iterator(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- struct symbol *target = dmrC_lookup_symbol(token->ident, NS_ITERATOR);
- stmt->type = STMT_GOTO;
- stmt->goto_label = target;
- if (!target)
- dmrC_sparse_error(C, stmt->pos, "break/continue not in iterator scope");
- return dmrC_expect_token(C, token->next, ';', "at end of statement");
-}
-
-static struct token *parse_switch_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- stmt->type = STMT_SWITCH;
- start_switch(C, stmt);
- token = dmrC_parens_expression(C, token->next, &stmt->switch_expression, "after 'switch'");
- token = statement(C, token, &stmt->switch_statement);
- end_switch(C, stmt);
- return token;
-}
-
-static struct token *parse_goto_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- stmt->type = STMT_GOTO;
- token = token->next;
- if (dmrC_match_op(token, '*')) {
- token = dmrC_parse_expression(C, token->next, &stmt->goto_expression);
- dmrC_add_statement(C, &C->P->function_computed_goto_list, stmt);
- } else if (dmrC_token_type(token) == TOKEN_IDENT) {
- stmt->goto_label = dmrC_label_symbol(C, token);
- token = token->next;
- } else {
- dmrC_sparse_error(C, token->pos, "Expected identifier or goto expression");
- }
- return dmrC_expect_token(C, token, ';', "at end of statement");
-}
-
-static struct token *parse_context_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- stmt->type = STMT_CONTEXT;
- token = dmrC_parse_expression(C, token->next, &stmt->expression);
- if (stmt->expression->type == EXPR_PREOP
- && stmt->expression->op == '('
- && stmt->expression->unop->type == EXPR_COMMA) {
- struct expression *expr;
- expr = stmt->expression->unop;
- stmt->context = expr->left;
- stmt->expression = expr->right;
- }
- return dmrC_expect_token(C, token, ';', "at end of statement");
-}
-
-static struct token *parse_range_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- stmt->type = STMT_RANGE;
- token = dmrC_assignment_expression(C, token->next, &stmt->range_expression);
- token = dmrC_expect_token(C, token, ',', "after range expression");
- token = dmrC_assignment_expression(C, token, &stmt->range_low);
- token = dmrC_expect_token(C, token, ',', "after low range");
- token = dmrC_assignment_expression(C, token, &stmt->range_high);
- return dmrC_expect_token(C, token, ';', "after range statement");
-}
-
-static struct token *statement(struct dmr_C *C, struct token *token, struct statement **tree)
-{
- struct statement *stmt = dmrC_alloc_statement(C, token->pos, STMT_NONE);
-
- *tree = stmt;
- if (dmrC_token_type(token) == TOKEN_IDENT) {
- struct symbol *s = dmrC_lookup_keyword(token->ident, NS_KEYWORD);
- if (s && s->op->statement)
- return s->op->statement(C, token, stmt);
-
- if (dmrC_match_op(token->next, ':')) {
- struct symbol *s = dmrC_label_symbol(C, token);
- stmt->type = STMT_LABEL;
- stmt->label_identifier = s;
- if (s->stmt)
- dmrC_sparse_error(C, stmt->pos, "label '%s' redefined", dmrC_show_ident(C, token->ident));
- s->stmt = stmt;
- token = skip_attributes(C, token->next->next);
- return statement(C, token, &stmt->label_statement);
- }
- }
-
- if (dmrC_match_op(token, '{')) {
- stmt->type = STMT_COMPOUND;
- dmrC_start_symbol_scope(C);
- token = dmrC_compound_statement(C, token->next, stmt);
- dmrC_end_symbol_scope(C);
-
- return dmrC_expect_token(C, token, '}', "at end of compound statement");
- }
-
- stmt->type = STMT_EXPRESSION;
- return expression_statement(C, token, &stmt->expression);
-}
-
-/* gcc extension - __label__ ident-list; in the beginning of compound stmt */
-static struct token *label_statement(struct dmr_C *C, struct token *token)
-{
- while (dmrC_token_type(token) == TOKEN_IDENT) {
- struct symbol *sym = dmrC_alloc_symbol(C->S, token->pos, SYM_LABEL);
- /* it's block-scope, but we want label namespace */
- dmrC_bind_symbol(C->S, sym, token->ident, NS_SYMBOL);
- sym->ns = NS_LABEL;
- fn_local_symbol(C, sym);
- token = token->next;
- if (!dmrC_match_op(token, ','))
- break;
- token = token->next;
- }
- return dmrC_expect_token(C, token, ';', "at end of label declaration");
-}
-
-static struct token * statement_list(struct dmr_C *C, struct token *token, struct statement_list **list)
-{
- int seen_statement = 0;
- while (dmrC_token_type(token) == TOKEN_IDENT &&
- token->ident == C->S->__label___ident)
- token = label_statement(C, token->next);
- for (;;) {
- struct statement * stmt;
- if (dmrC_eof_token(token))
- break;
- if (dmrC_match_op(token, '}'))
- break;
- if (dmrC_match_ident(token, C->S->_Static_assert_ident)) {
- token = parse_static_assert(C, token, NULL);
- continue;
- }
- if (dmrC_lookup_type(token)) {
- if (seen_statement) {
- dmrC_warning(C, token->pos, "mixing declarations and code");
- seen_statement = 0;
- }
- stmt = dmrC_alloc_statement(C, token->pos, STMT_DECLARATION);
- token = dmrC_external_declaration(C, token, &stmt->declaration, NULL);
- } else {
- seen_statement = C->Wdeclarationafterstatement;
- token = statement(C, token, &stmt);
- }
- dmrC_add_statement(C, list, stmt);
- }
- return token;
-}
-
-static struct token *identifier_list(struct dmr_C *C, struct token *token, struct symbol *fn)
-{
- struct symbol_list **list = &fn->arguments;
- for (;;) {
- struct symbol *sym = dmrC_alloc_symbol(C->S, token->pos, SYM_NODE);
- sym->ident = token->ident;
- token = token->next;
- sym->endpos = token->pos;
- sym->ctype.base_type = &C->S->incomplete_ctype;
- dmrC_add_symbol(C, list, sym);
- if (!dmrC_match_op(token, ',') ||
- dmrC_token_type(token->next) != TOKEN_IDENT ||
- dmrC_lookup_type(token->next))
- break;
- token = token->next;
- }
- return token;
-}
-
-static struct token *parameter_type_list(struct dmr_C *C, struct token *token, struct symbol *fn)
-{
- struct symbol_list **list = &fn->arguments;
-
- for (;;) {
- struct symbol *sym;
-
- if (dmrC_match_op(token, SPECIAL_ELLIPSIS)) {
- fn->variadic = 1;
- token = token->next;
- break;
- }
-
- sym = dmrC_alloc_symbol(C->S, token->pos, SYM_NODE);
- token = parameter_declaration(C, token, sym);
- if (sym->ctype.base_type == &C->S->void_ctype) {
- /* Special case: (void) */
- if (!*list && !sym->ident)
- break;
- dmrC_warning(C, token->pos, "void parameter");
- }
- dmrC_add_symbol(C, list, sym);
- if (!dmrC_match_op(token, ','))
- break;
- token = token->next;
- }
- return token;
-}
-
-struct token *dmrC_compound_statement(struct dmr_C *C, struct token *token, struct statement *stmt)
-{
- token = statement_list(C, token, &stmt->stmts);
- return token;
-}
-
-static struct expression *identifier_expression(struct dmr_C *C, struct token *token)
-{
- struct expression *expr = dmrC_alloc_expression(C, token->pos, EXPR_IDENTIFIER);
- expr->expr_ident = token->ident;
- return expr;
-}
-
-static struct expression *index_expression(struct dmr_C *C, struct expression *from, struct expression *to)
-{
- int idx_from, idx_to;
- struct expression *expr = dmrC_alloc_expression(C, from->pos, EXPR_INDEX);
-
- idx_from = (int) dmrC_const_expression_value(C, from);
- idx_to = idx_from;
- if (to) {
- idx_to = (int) dmrC_const_expression_value(C, to);
- if (idx_to < idx_from || idx_from < 0)
- dmrC_warning(C, from->pos, "nonsense array initializer index range");
- }
- expr->idx_from = idx_from;
- expr->idx_to = idx_to;
- return expr;
-}
-
-static struct token *single_initializer(struct dmr_C *C, struct expression **ep, struct token *token)
-{
- int expect_equal = 0;
- struct token *next = token->next;
- struct expression **tail = ep;
- int nested;
-
- *ep = NULL;
-
- if ((dmrC_token_type(token) == TOKEN_IDENT) && dmrC_match_op(next, ':')) {
- struct expression *expr = identifier_expression(C, token);
- if (C->Wold_initializer)
- dmrC_warning(C, token->pos, "obsolete struct initializer, use C99 syntax");
- token = dmrC_initializer(C, &expr->ident_expression, next->next);
- if (expr->ident_expression)
- *ep = expr;
- return token;
- }
-
- for (tail = ep, nested = 0; ; nested++, next = token->next) {
- if (dmrC_match_op(token, '.') && (dmrC_token_type(next) == TOKEN_IDENT)) {
- struct expression *expr = identifier_expression(C, next);
- *tail = expr;
- tail = &expr->ident_expression;
- expect_equal = 1;
- token = next->next;
- } else if (dmrC_match_op(token, '[')) {
- struct expression *from = NULL, *to = NULL, *expr;
- token = dmrC_constant_expression(C, token->next, &from);
- if (!from) {
- dmrC_sparse_error(C, token->pos, "Expected constant expression");
- break;
- }
- if (dmrC_match_op(token, SPECIAL_ELLIPSIS))
- token = dmrC_constant_expression(C, token->next, &to);
- expr = index_expression(C, from, to);
- *tail = expr;
- tail = &expr->idx_expression;
- token = dmrC_expect_token(C, token, ']', "at end of initializer index");
- if (nested)
- expect_equal = 1;
- } else {
- break;
- }
- }
- if (nested && !expect_equal) {
- if (!dmrC_match_op(token, '='))
- dmrC_warning(C, token->pos, "obsolete array initializer, use C99 syntax");
- else
- expect_equal = 1;
- }
- if (expect_equal)
- token = dmrC_expect_token(C, token, '=', "at end of initializer index");
-
- token = dmrC_initializer(C, tail, token);
- if (!*tail)
- *ep = NULL;
- return token;
-}
-
-static struct token *initializer_list(struct dmr_C *C, struct expression_list **list, struct token *token)
-{
- struct expression *expr;
-
- for (;;) {
- token = single_initializer(C, &expr, token);
- if (!expr)
- break;
- dmrC_add_expression(C, list, expr);
- if (!dmrC_match_op(token, ','))
- break;
- token = token->next;
- }
- return token;
-}
-
-struct token *dmrC_initializer(struct dmr_C *C, struct expression **tree, struct token *token)
-{
- if (dmrC_match_op(token, '{')) {
- struct expression *expr = dmrC_alloc_expression(C, token->pos, EXPR_INITIALIZER);
- *tree = expr;
- token = initializer_list(C, &expr->expr_list, token->next);
- return dmrC_expect_token(C, token, '}', "at end of initializer");
- }
- return dmrC_assignment_expression(C, token, tree);
-}
-
-static void declare_argument(struct dmr_C *C, struct symbol *sym, struct symbol *fn)
-{
- (void) fn;
- if (!sym->ident) {
- dmrC_sparse_error(C, sym->pos, "no identifier for function argument");
- return;
- }
- dmrC_bind_symbol(C->S, sym, sym->ident, NS_SYMBOL);
-}
-
-static struct token *parse_function_body(struct dmr_C *C, struct token *token, struct symbol *decl,
- struct symbol_list **list)
-{
- struct symbol_list **old_symbol_list;
- struct symbol *base_type = decl->ctype.base_type;
- struct statement *stmt, **p;
- struct symbol *prev;
- struct symbol *arg;
-
- old_symbol_list = C->P->function_symbol_list;
- if (decl->ctype.modifiers & MOD_INLINE) {
- C->P->function_symbol_list = &decl->inline_symbol_list;
- p = &base_type->inline_stmt;
- } else {
- C->P->function_symbol_list = &decl->symbol_list;
- p = &base_type->stmt;
- }
- C->P->function_computed_target_list = NULL;
- C->P->function_computed_goto_list = NULL;
-
- if (decl->ctype.modifiers & MOD_EXTERN) {
- if (!(decl->ctype.modifiers & MOD_INLINE))
- dmrC_warning(C, decl->pos, "function '%s' with external linkage has definition", dmrC_show_ident(C, decl->ident));
- }
- if (!(decl->ctype.modifiers & MOD_STATIC))
- decl->ctype.modifiers |= MOD_EXTERN;
-
- stmt = start_function(C, decl);
-
- *p = stmt;
- FOR_EACH_PTR (base_type->arguments, arg) {
- declare_argument(C, arg, base_type);
- } END_FOR_EACH_PTR(arg);
-
- token = dmrC_compound_statement(C, token->next, stmt);
-
- end_function(C, decl);
- if (!(decl->ctype.modifiers & MOD_INLINE))
- dmrC_add_symbol(C, list, decl);
- dmrC_check_declaration(C->S, decl);
- decl->definition = decl;
- prev = decl->same_symbol;
- if (prev && prev->definition) {
- dmrC_warning(C, decl->pos, "multiple definitions for function '%s'",
- dmrC_show_ident(C, decl->ident));
- dmrC_info(C, prev->definition->pos, " the previous one is here");
- } else {
- while (prev) {
- dmrC_rebind_scope(C, prev, decl->scope);
- prev->definition = decl;
- prev = prev->same_symbol;
- }
- }
- C->P->function_symbol_list = old_symbol_list;
- if (C->P->function_computed_goto_list) {
- if (!C->P->function_computed_target_list)
- dmrC_warning(C, decl->pos, "function '%s' has computed goto but no targets?", dmrC_show_ident(C, decl->ident));
- else {
- FOR_EACH_PTR(C->P->function_computed_goto_list, stmt) {
- stmt->target_list = C->P->function_computed_target_list;
- } END_FOR_EACH_PTR(stmt);
- }
- }
- return dmrC_expect_token(C, token, '}', "at end of function");
-}
-
-static void promote_k_r_types(struct dmr_C *C, struct symbol *arg)
-{
- struct symbol *base = arg->ctype.base_type;
- if (base && base->ctype.base_type == &C->S->int_type && (base->ctype.modifiers & (MOD_CHAR | MOD_SHORT))) {
- arg->ctype.base_type = &C->S->int_ctype;
- }
-}
-
-static void apply_k_r_types(struct dmr_C *C, struct symbol_list *argtypes, struct symbol *fn)
-{
- struct symbol_list *real_args = fn->ctype.base_type->arguments;
- struct symbol *arg;
-
- FOR_EACH_PTR(real_args, arg) {
- struct symbol *type;
-
- /* This is quadratic in the number of arguments. We _really_ don't care */
- FOR_EACH_PTR(argtypes, type) {
- if (type->ident == arg->ident)
- goto match;
- } END_FOR_EACH_PTR(type);
- dmrC_sparse_error(C, arg->pos, "missing type declaration for parameter '%s'", dmrC_show_ident(C, arg->ident));
- continue;
-match:
- type->used = 1;
- /* "char" and "short" promote to "int" */
- promote_k_r_types(C, type);
-
- arg->ctype = type->ctype;
- } END_FOR_EACH_PTR(arg);
-
- FOR_EACH_PTR(argtypes, arg) {
- if (!arg->used)
- dmrC_warning(C, arg->pos, "nonsensical parameter declaration '%s'", dmrC_show_ident(C, arg->ident));
- } END_FOR_EACH_PTR(arg);
-}
-
-static struct token *parse_k_r_arguments(struct dmr_C *C, struct token *token, struct symbol *decl,
- struct symbol_list **list)
-{
- struct symbol_list *args = NULL;
-
- dmrC_warning(C, token->pos, "non-ANSI definition of function '%s'", dmrC_show_ident(C, decl->ident));
- do {
- token = declaration_list(C, token, &args);
- if (!dmrC_match_op(token, ';')) {
- dmrC_sparse_error(C, token->pos, "expected ';' at end of parameter declaration");
- break;
- }
- token = token->next;
- } while (dmrC_lookup_type(token));
-
- apply_k_r_types(C, args, decl);
-
- if (!dmrC_match_op(token, '{')) {
- dmrC_sparse_error(C, token->pos, "expected function body");
- return token;
- }
- return parse_function_body(C, token, decl, list);
-}
-
-static struct token *toplevel_asm_declaration(struct dmr_C *C, struct token *token, struct symbol_list **list)
-{
- struct symbol *anon = dmrC_alloc_symbol(C->S, token->pos, SYM_NODE);
- struct symbol *fn = dmrC_alloc_symbol(C->S, token->pos, SYM_FN);
- struct statement *stmt;
-
- anon->ctype.base_type = fn;
- stmt = dmrC_alloc_statement(C, token->pos, STMT_NONE);
- fn->stmt = stmt;
-
- token = parse_asm_statement(C, token, stmt);
-
- dmrC_add_symbol(C, list, anon);
- return token;
-}
-
-struct token *dmrC_external_declaration(struct dmr_C *C, struct token *token, struct symbol_list **list, validate_decl_t validate_decl)
-{
- struct ident *ident = NULL;
- struct symbol *decl;
- struct decl_state ctx = { .ident = &ident };
- struct ctype saved;
- struct symbol *base_type;
- unsigned long mod;
- int is_typedef;
-
- /* Top-level inline asm? or static assertion? */
- if (dmrC_token_type(token) == TOKEN_IDENT) {
- struct symbol *s = dmrC_lookup_keyword(token->ident, NS_KEYWORD);
- if (s && s->op->toplevel)
- return s->op->toplevel(C, token, list);
- }
-
- /* Parse declaration-specifiers, if any */
- token = declaration_specifiers(C, token, &ctx);
- mod = storage_modifiers(C, &ctx);
- decl = dmrC_alloc_symbol(C->S, token->pos, SYM_NODE);
- /* Just a type declaration? */
- if (dmrC_match_op(token, ';')) {
- apply_modifiers(C, token->pos, &ctx);
- return token->next;
- }
-
- saved = ctx.ctype;
- token = declarator(C, token, &ctx);
- token = handle_attributes(C, token, &ctx, KW_ATTRIBUTE | KW_ASM);
- apply_modifiers(C, token->pos, &ctx);
-
- decl->ctype = ctx.ctype;
- decl->ctype.modifiers |= mod;
- decl->endpos = token->pos;
-
- /* Just a type declaration? */
- if (!ident) {
- dmrC_warning(C, token->pos, "missing identifier in declaration");
- return dmrC_expect_token(C, token, ';', "at the end of type declaration");
- }
-
- /* type define declaration? */
- is_typedef = ctx.storage_class == STypedef;
-
- /* Typedefs don't have meaningful storage */
- if (is_typedef)
- decl->ctype.modifiers |= MOD_USERTYPE;
-
- dmrC_bind_symbol(C->S, decl, ident, is_typedef ? NS_TYPEDEF: NS_SYMBOL);
-
- base_type = decl->ctype.base_type;
-
- if (is_typedef) {
- if (base_type && !base_type->ident) {
- switch (base_type->type) {
- case SYM_STRUCT:
- case SYM_UNION:
- case SYM_ENUM:
- case SYM_RESTRICT:
- base_type->ident = ident;
- break;
- default:
- break;
- }
- }
- } else if (base_type && base_type->type == SYM_FN) {
- if (base_type->ctype.base_type == &C->S->incomplete_ctype) {
- dmrC_warning(C, decl->pos, "'%s()' has implicit return type",
- dmrC_show_ident(C, decl->ident));
- base_type->ctype.base_type = &C->S->int_ctype;
- }
- /* K&R argument declaration? */
- if (dmrC_lookup_type(token))
- return parse_k_r_arguments(C, token, decl, list);
- if (dmrC_match_op(token, '{'))
- return parse_function_body(C, token, decl, list);
-
- if (!(decl->ctype.modifiers & MOD_STATIC))
- decl->ctype.modifiers |= MOD_EXTERN;
- } else if (base_type == &C->S->void_ctype && !(decl->ctype.modifiers & MOD_EXTERN)) {
- dmrC_sparse_error(C, token->pos, "void declaration");
- }
- if (base_type == &C->S->incomplete_ctype) {
- dmrC_warning(C, decl->pos, "'%s' has implicit type", dmrC_show_ident(C, decl->ident));
- decl->ctype.base_type = &C->S->int_ctype;
- }
-
- for (;;) {
- if (!is_typedef && dmrC_match_op(token, '=')) {
- token = dmrC_initializer(C, &decl->initializer, token->next);
- }
- if (!is_typedef) {
- if (validate_decl)
- validate_decl(C, decl);
- if (decl->initializer && decl->ctype.modifiers & MOD_EXTERN) {
- dmrC_warning(C, decl->pos, "symbol with external linkage has initializer");
- decl->ctype.modifiers &= ~MOD_EXTERN;
- }
- if (!(decl->ctype.modifiers & (MOD_EXTERN | MOD_INLINE))) {
- dmrC_add_symbol(C, list, decl);
- fn_local_symbol(C, decl);
- }
- }
- dmrC_check_declaration(C->S, decl);
- if (decl->same_symbol) {
- decl->definition = decl->same_symbol->definition;
- decl->op = decl->same_symbol->op;
- }
-
- if (!dmrC_match_op(token, ','))
- break;
-
- token = token->next;
- ident = NULL;
- decl = dmrC_alloc_symbol(C->S, token->pos, SYM_NODE);
- ctx.ctype = saved;
- token = handle_attributes(C, token, &ctx, KW_ATTRIBUTE);
- token = declarator(C, token, &ctx);
- token = handle_attributes(C, token, &ctx, KW_ATTRIBUTE | KW_ASM);
- apply_modifiers(C, token->pos, &ctx);
- decl->ctype = ctx.ctype;
- decl->ctype.modifiers |= mod;
- decl->endpos = token->pos;
- if (!ident) {
- dmrC_sparse_error(C, token->pos, "expected identifier name in type definition");
- return token;
- }
-
- if (is_typedef)
- decl->ctype.modifiers |= MOD_USERTYPE;
-
- dmrC_bind_symbol(C->S, decl, ident, is_typedef ? NS_TYPEDEF: NS_SYMBOL);
-
- /* Function declarations are automatically extern unless specifically static */
- base_type = decl->ctype.base_type;
- if (!is_typedef && base_type && base_type->type == SYM_FN) {
- if (!(decl->ctype.modifiers & MOD_STATIC))
- decl->ctype.modifiers |= MOD_EXTERN;
- }
- }
- return dmrC_expect_token(C, token, ';', "at end of declaration");
-}
-
-int dmrC_test_parse() {
- struct dmr_C *C = new_dmr_C();
- char test1[100] = "extern int printf(const char *, ...); int main() { printf(\"hello world!\\n\"); return 0; }";
- struct token *start;
- struct token *end;
- start = dmrC_tokenize_buffer(C, (unsigned char *)test1,
- (unsigned long)strlen(test1), &end);
- for (struct token *p = start; !dmrC_eof_token(p); p = p->next) {
- printf("%s\n", dmrC_show_token(C, p));
- }
- printf("\n");
- start = dmrC_preprocess(C, start);
- for (struct token *p = start; !dmrC_eof_token(p); p = p->next) {
- printf("%s\n", dmrC_show_token(C, p));
- }
- while (!dmrC_eof_token(start))
- start = dmrC_external_declaration(C, start, &C->S->translation_unit_used_list, NULL);
- dmrC_show_symbol_list(C, C->S->translation_unit_used_list, "\n\n");
- destroy_dmr_C(C);
- return 0;
-}
diff --git a/dmr_c/src/parse.h b/dmr_c/src/parse.h
deleted file mode 100644
index 4d27b94..0000000
--- a/dmr_c/src/parse.h
+++ /dev/null
@@ -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
-#include
-
-#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 */
diff --git a/dmr_c/src/port.h b/dmr_c/src/port.h
deleted file mode 100644
index 1e6f042..0000000
--- a/dmr_c/src/port.h
+++ /dev/null
@@ -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
-#include
-#else
-#include
-#include
-#endif
-
-#if defined(_WIN32) && defined(_MSC_VER)
-#include
-#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
-
-#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
diff --git a/dmr_c/src/pre-process.c b/dmr_c/src/pre-process.c
deleted file mode 100644
index 4817939..0000000
--- a/dmr_c/src/pre-process.c
+++ /dev/null
@@ -1,2130 +0,0 @@
-/*
- * Do C preprocessing, based on a token list gathered by
- * the tokenizer.
- *
- * This may not be the smartest preprocessor on the planet.
- *
- * 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