Compare commits
93 Commits
loader_sep
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3905c4e281 | ||
|
|
171abc0415 | ||
|
|
126e206b08 | ||
|
|
7f1a4e26bd | ||
|
|
8875371cee | ||
|
|
3af6f8f5c3 | ||
|
|
e1f0c084f8 | ||
|
|
e2a6b25345 | ||
|
|
f210ed78c2 | ||
|
|
ccc8cc526b | ||
|
|
cd6797499f | ||
|
|
d5985b4b97 | ||
|
|
b60903306f | ||
|
|
5f68987001 | ||
|
|
1df7cb3be4 | ||
|
|
a7265f06b0 | ||
|
|
58532f4402 | ||
|
|
7d986ef661 | ||
|
|
7f4197acc1 | ||
|
|
e71c8051c3 | ||
|
|
73cf949e25 | ||
|
|
14ceb301c1 | ||
|
|
bc654cbf76 | ||
|
|
9c6dfd676e | ||
|
|
ae27258e3c | ||
|
|
41e9faec0e | ||
|
|
6f7bfbddf8 | ||
|
|
db39014e1b | ||
|
|
3376818a17 | ||
|
|
72ca6bbb70 | ||
|
|
888de8d35e | ||
|
|
59c199837c | ||
|
|
152625d67d | ||
|
|
292e4041e1 | ||
|
|
36d95946b3 | ||
|
|
4cc3b41e64 | ||
|
|
6ade935e37 | ||
|
|
c8fd3a01df | ||
|
|
29353111ac | ||
|
|
4dc321650f | ||
|
|
0521206de5 | ||
|
|
60a4fefe95 | ||
|
|
0391f67109 | ||
|
|
d22624a99b | ||
|
|
95acbaa7fa | ||
|
|
2452984864 | ||
|
|
4682bda8d8 | ||
|
|
4a6d97c1b1 | ||
|
|
3d5a907b30 | ||
|
|
0684062130 | ||
|
|
62d8633113 | ||
|
|
b2be1cf2da | ||
|
|
94e3016a5b | ||
|
|
145a50369e | ||
|
|
d77927c608 | ||
|
|
3bb72987a6 | ||
|
|
c782892db4 | ||
|
|
a944ea5da8 | ||
|
|
d1738ea630 | ||
|
|
5f39236ba2 | ||
|
|
ede09ddae3 | ||
|
|
34b1f4f4fe | ||
|
|
d6249916e1 | ||
|
|
9cd3226536 | ||
|
|
3f217e83da | ||
|
|
652cfb67c3 | ||
|
|
c0e9ba2fb3 | ||
|
|
5963f5fd4d | ||
|
|
12ee08f87e | ||
|
|
5c85c92d1a | ||
|
|
b509d0fcf0 | ||
|
|
bb007ddefc | ||
|
|
9129d48429 | ||
|
|
d105182051 | ||
|
|
157a968372 | ||
|
|
bae2a582f1 | ||
|
|
19191876e2 | ||
|
|
fcfe3c1f4b | ||
|
|
97f093feaa | ||
|
|
3561de6e12 | ||
|
|
e84d09b97c | ||
|
|
d8a4fe1c04 | ||
|
|
e4e6ad6415 | ||
|
|
2543617930 | ||
|
|
bc5784a8f2 | ||
|
|
842687726f | ||
|
|
c5c9196561 | ||
|
|
a697ad05c0 | ||
|
|
d8c66e7791 | ||
|
|
337a6c44aa | ||
|
|
cde4484821 | ||
|
|
36b063c183 | ||
|
|
3603877f42 |
6
.gitattributes
vendored
Normal file
6
.gitattributes
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
* text=auto
|
||||
*.c text
|
||||
*.cpp text
|
||||
*.ui text
|
||||
*.qrc text
|
||||
*.h text
|
||||
68
3rd_party/libdisasm/INTEL_BUGS
vendored
Normal file
68
3rd_party/libdisasm/INTEL_BUGS
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
PMOVMSKB
|
||||
Gd, Pq1H
|
||||
PMOVMSKB
|
||||
(66)
|
||||
Gd, Vdq1H
|
||||
|
||||
should be
|
||||
|
||||
PMOVMSKB
|
||||
Gd, Qq1H
|
||||
PMOVMSKB
|
||||
(66)
|
||||
Gd, Wdq1H
|
||||
|
||||
The instruction represented by this opcode expression does not support any
|
||||
operand to be a memory location.
|
||||
|
||||
MASKMOVQ
|
||||
Pq, Pq1H
|
||||
MASKMOVDQU
|
||||
(66)
|
||||
Vdq, Vdq1H
|
||||
|
||||
should be
|
||||
|
||||
MASKMOVQ
|
||||
Pq, Pq1H
|
||||
MASKMOVDQU
|
||||
(66)
|
||||
Vdq, Wdq1H
|
||||
|
||||
MOVMSKPS
|
||||
Gd, Vps1H
|
||||
MOVMSKPD
|
||||
(66)
|
||||
Gd, Vpd1H
|
||||
|
||||
should be
|
||||
|
||||
MOVMSKPS
|
||||
Gd, Wps1H
|
||||
MOVMSKPD
|
||||
(66)
|
||||
Gd, Wpd1H
|
||||
|
||||
The opcode table entries for LFS, LGS, and LSS
|
||||
|
||||
L[FGS]S
|
||||
Mp
|
||||
|
||||
should be
|
||||
|
||||
L[FGS]S
|
||||
Gv,Mp
|
||||
|
||||
MOVHLPS
|
||||
Vps, Vps
|
||||
|
||||
MOVLHPS
|
||||
Vps, Vps
|
||||
|
||||
should be
|
||||
|
||||
MOVHLPS
|
||||
Vps, Wps
|
||||
|
||||
MOVLHPS
|
||||
Vps, Wps
|
||||
137
3rd_party/libdisasm/LICENSE
vendored
Normal file
137
3rd_party/libdisasm/LICENSE
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
|
||||
|
||||
|
||||
|
||||
The "Clarified Artistic License"
|
||||
|
||||
Preamble
|
||||
|
||||
The intent of this document is to state the conditions under which a
|
||||
Package may be copied, such that the Copyright Holder maintains some
|
||||
semblance of artistic control over the development of the package,
|
||||
while giving the users of the package the right to use and distribute
|
||||
the Package in a more-or-less customary fashion, plus the right to make
|
||||
reasonable modifications.
|
||||
|
||||
Definitions:
|
||||
|
||||
"Package" refers to the collection of files distributed by the
|
||||
Copyright Holder, and derivatives of that collection of files
|
||||
created through textual modification.
|
||||
|
||||
"Standard Version" refers to such a Package if it has not been
|
||||
modified, or has been modified in accordance with the wishes
|
||||
of the Copyright Holder as specified below.
|
||||
|
||||
"Copyright Holder" is whoever is named in the copyright or
|
||||
copyrights for the package.
|
||||
|
||||
"You" is you, if you're thinking about copying or distributing
|
||||
this Package.
|
||||
|
||||
"Distribution fee" is a fee you charge for providing a copy of this
|
||||
Package to another party.
|
||||
|
||||
"Freely Available" means that no fee is charged for the right to use
|
||||
the item, though there may be fees involved in handling the item.
|
||||
|
||||
1. You may make and give away verbatim copies of the source form of the
|
||||
Standard Version of this Package without restriction, provided that you
|
||||
duplicate all of the original copyright notices and associated disclaimers.
|
||||
|
||||
2. You may apply bug fixes, portability fixes and other modifications
|
||||
derived from the Public Domain, or those made Freely Available, or from
|
||||
the Copyright Holder. A Package modified in such a way shall still be
|
||||
considered the Standard Version.
|
||||
|
||||
3. You may otherwise modify your copy of this Package in any way, provided
|
||||
that you insert a prominent notice in each changed file stating how and
|
||||
when you changed that file, and provided that you do at least ONE of the
|
||||
following:
|
||||
|
||||
a) place your modifications in the Public Domain or otherwise make them
|
||||
Freely Available, such as by posting said modifications to Usenet or
|
||||
an equivalent medium, or placing the modifications on a major archive
|
||||
site allowing unrestricted access to them, or by allowing the Copyright
|
||||
Holder to include your modifications in the Standard Version of the
|
||||
Package.
|
||||
|
||||
b) use the modified Package only within your corporation or organization.
|
||||
|
||||
c) rename any non-standard executables so the names do not conflict
|
||||
with standard executables, which must also be provided, and provide
|
||||
a separate manual page for each non-standard executable that clearly
|
||||
documents how it differs from the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright Holder.
|
||||
|
||||
e) permit and encourge anyone who receives a copy of the modified Package
|
||||
permission to make your modifications Freely Available in some specific
|
||||
way.
|
||||
|
||||
4. You may distribute the programs of this Package in object code or
|
||||
executable form, provided that you do at least ONE of the following:
|
||||
|
||||
a) distribute a Standard Version of the executables and library files,
|
||||
together with instructions (in the manual page or equivalent) on where
|
||||
to get the Standard Version.
|
||||
|
||||
b) accompany the distribution with the machine-readable source of
|
||||
the Package with your modifications.
|
||||
|
||||
c) give non-standard executables non-standard names, and clearly
|
||||
document the differences in manual pages (or equivalent), together
|
||||
with instructions on where to get the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright Holder.
|
||||
|
||||
e) offer the machine-readable source of the Package, with your
|
||||
modifications, by mail order.
|
||||
|
||||
5. You may charge a distribution fee for any distribution of this Package.
|
||||
If you offer support for this Package, you may charge any fee you choose
|
||||
for that support. You may not charge a license fee for the right to use
|
||||
this Package itself. You may distribute this Package in aggregate with
|
||||
other (possibly commercial and possibly nonfree) programs as part of a
|
||||
larger (possibly commercial and possibly nonfree) software distribution,
|
||||
and charge license fees for other parts of that software distribution,
|
||||
provided that you do not advertise this Package as a product of your own.
|
||||
If the Package includes an interpreter, You may embed this Package's
|
||||
interpreter within an executable of yours (by linking); this shall be
|
||||
construed as a mere form of aggregation, provided that the complete
|
||||
Standard Version of the interpreter is so embedded.
|
||||
|
||||
6. The scripts and library files supplied as input to or produced as
|
||||
output from the programs of this Package do not automatically fall
|
||||
under the copyright of this Package, but belong to whoever generated
|
||||
them, and may be sold commercially, and may be aggregated with this
|
||||
Package. If such scripts or library files are aggregated with this
|
||||
Package via the so-called "undump" or "unexec" methods of producing a
|
||||
binary executable image, then distribution of such an image shall
|
||||
neither be construed as a distribution of this Package nor shall it
|
||||
fall under the restrictions of Paragraphs 3 and 4, provided that you do
|
||||
not represent such an executable image as a Standard Version of this
|
||||
Package.
|
||||
|
||||
7. C subroutines (or comparably compiled subroutines in other
|
||||
languages) supplied by you and linked into this Package in order to
|
||||
emulate subroutines and variables of the language defined by this
|
||||
Package shall not be considered part of this Package, but are the
|
||||
equivalent of input as in Paragraph 6, provided these subroutines do
|
||||
not change the language in any way that would cause it to fail the
|
||||
regression tests for the language.
|
||||
|
||||
8. Aggregation of the Standard Version of the Package with a commercial
|
||||
distribution is always permitted provided that the use of this Package is
|
||||
embedded; that is, when no overt attempt is made to make this Package's
|
||||
interfaces visible to the end user of the commercial distribution.
|
||||
Such use shall not be construed as a distribution of this Package.
|
||||
|
||||
9. The name of the Copyright Holder may not be used to endorse or promote
|
||||
products derived from this software without specific prior written permission.
|
||||
|
||||
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
The End
|
||||
12
3rd_party/libdisasm/NAMESPACE.TXT
vendored
Normal file
12
3rd_party/libdisasm/NAMESPACE.TXT
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
The rewritten libdisasm code uses the following namespaces:
|
||||
|
||||
|
||||
Prefix Namespace
|
||||
----------------------------------------------------
|
||||
x86_ Global 'libdisasm' namespace
|
||||
ia32_ Internal IA32 ISA namespace
|
||||
ia64_ Internal IA64 ISA namespace
|
||||
ix64_ Internal X86-64 ISA namespace
|
||||
|
||||
Note that the 64-bit ISAs are not yet supported/written.
|
||||
2
3rd_party/libdisasm/README
vendored
Normal file
2
3rd_party/libdisasm/README
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
This is a cut-up version of libdisasm originally from the bastard project http://bastard.sourceforge.net/
|
||||
|
||||
43
3rd_party/libdisasm/TODO
vendored
Normal file
43
3rd_party/libdisasm/TODO
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
x86_format.c
|
||||
------------
|
||||
intel: jmpf -> jmp, callf -> call
|
||||
att: jmpf -> ljmp, callf -> lcall
|
||||
|
||||
opcode table
|
||||
------------
|
||||
finish typing instructions
|
||||
fix flag clear/set/toggle types
|
||||
|
||||
ix64 stuff
|
||||
----------
|
||||
document output file formats in web page
|
||||
features doc: register aliases, implicit operands, stack mods,
|
||||
ring0 flags, eflags, cpu model/isa
|
||||
|
||||
ia32_handle_* implementation
|
||||
|
||||
fix operand 0F C2
|
||||
CMPPS
|
||||
|
||||
* sysenter, sysexit as CALL types -- preceded by MSR writes
|
||||
* SYSENTER/SYSEXIT stack : overwrites SS, ESP
|
||||
* stos, cmps, scas, movs, ins, outs, lods -> OP_PTR
|
||||
* OP_SIZE in implicit operands
|
||||
* use OP_SIZE to choose reg sizes!
|
||||
|
||||
DONE?? :
|
||||
implicit operands: provide action ?
|
||||
e.g. add/inc for stach, write, etc
|
||||
replace table numbers in opcodes.dat with
|
||||
#defines for table names
|
||||
|
||||
replace 0 with INSN_INVALID [or maybe FF for imnvalid and 00 for Not Applicable */
|
||||
no wait that is only for prefix tables -- n/p
|
||||
|
||||
if ( prefx) only use if insn != invalid
|
||||
|
||||
these should cover all the wacky disasm exceptions
|
||||
|
||||
for the rep one we can chet, match only a 0x90
|
||||
|
||||
todo: privilege | ring
|
||||
36
3rd_party/libdisasm/ia32_fixup.cpp
vendored
Normal file
36
3rd_party/libdisasm/ia32_fixup.cpp
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
|
||||
static const char * mem_fixup[256] = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 00 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 08 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 10 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 18 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 20 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 28 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 30 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 38 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 40 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 48 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 50 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 58 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 60 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 68 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 70 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 78 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 80 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 88 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 90 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 98 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* F0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* F8 */
|
||||
};
|
||||
3206
3rd_party/libdisasm/ia32_opcode.dat
vendored
Normal file
3206
3rd_party/libdisasm/ia32_opcode.dat
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
3rd_party/libdisasm/libdis.h
vendored
7
3rd_party/libdisasm/libdis.h
vendored
@@ -317,7 +317,10 @@ struct x86_op_t{
|
||||
case op_offset:
|
||||
return data.offset;
|
||||
case op_relative_far:
|
||||
return (int32_t) data.relative_far;
|
||||
if (data.relative_far & 0x8000)
|
||||
return (data.relative_far & 0xFFFF) | 0xFFFF0000;
|
||||
else
|
||||
return (int32_t)data.relative_far;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
@@ -623,7 +626,7 @@ public:
|
||||
/* the instruction proper */
|
||||
enum x86_insn_prefix prefix; /* prefixes ORed together */
|
||||
char prefix_string[MAX_PREFIX_STR]; /* prefixes [might be truncated] */
|
||||
char mnemonic[MAX_MNEM_STR];
|
||||
char mnemonic[MAX_MNEM_STR+1];
|
||||
x86_oplist_t *operands; /* list of explicit/implicit operands */
|
||||
size_t operand_count; /* total number of operands */
|
||||
size_t explicit_count; /* number of explicit operands */
|
||||
|
||||
49
3rd_party/libdisasm/libdisasm.def
vendored
Normal file
49
3rd_party/libdisasm/libdisasm.def
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
;libdisasm.def : Declares the module parameters
|
||||
|
||||
LIBRARY "libdisasm.dll"
|
||||
DESCRIPTION "libdisasm exported functions"
|
||||
EXPORTS
|
||||
x86_addr_size @1
|
||||
x86_cleanup @2
|
||||
x86_disasm @3
|
||||
x86_disasm_forward @4
|
||||
x86_disasm_range @5
|
||||
x86_endian @6
|
||||
x86_format_header @7
|
||||
x86_format_insn @8
|
||||
x86_format_mnemonic @9
|
||||
x86_format_operand @10
|
||||
x86_fp_reg @11
|
||||
x86_get_branch_target @12
|
||||
x86_get_imm @13
|
||||
x86_get_options @14
|
||||
x86_get_raw_imm @15
|
||||
x86_get_rel_offset @16
|
||||
x86_imm_signsized @17
|
||||
x86_imm_sized @18
|
||||
x86_init @19
|
||||
x86_insn_is_tagged @20
|
||||
x86_insn_is_valid @21
|
||||
x86_invariant_disasm @22
|
||||
x86_ip_reg @23
|
||||
x86_max_insn_size @24
|
||||
x86_op_size @25
|
||||
x86_operand_1st @26
|
||||
x86_operand_2nd @27
|
||||
x86_operand_3rd @28
|
||||
x86_operand_count @29
|
||||
x86_operand_foreach @30
|
||||
x86_operand_new @31
|
||||
x86_operand_size @32
|
||||
x86_oplist_free @33
|
||||
x86_reg_from_id @34
|
||||
x86_report_error @35
|
||||
x86_set_insn_addr @36
|
||||
x86_set_insn_block @37
|
||||
x86_set_insn_function @38
|
||||
x86_set_insn_offset @39
|
||||
x86_set_options @40
|
||||
x86_set_reporter @41
|
||||
x86_size_disasm @42
|
||||
x86_sp_reg @43
|
||||
x86_tag_insn @44
|
||||
128
CMakeLists.txt
128
CMakeLists.txt
@@ -1,128 +1,46 @@
|
||||
PROJECT(dcc_original)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
OPTION(dcc_build_tests "Enable unit tests." OFF)
|
||||
#SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS)
|
||||
IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX)
|
||||
ADD_DEFINITIONS(/W4)
|
||||
ELSE()
|
||||
#-D_GLIBCXX_DEBUG
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++0x")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} " ) #--coverage
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
|
||||
include(cotire)
|
||||
FIND_PACKAGE(LLVM)
|
||||
FIND_PACKAGE(Boost)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
find_package(Qt5Core)
|
||||
find_package(Qt5Widgets)
|
||||
find_package(Boost)
|
||||
|
||||
OPTION(dcc_build_tests "Enable unit tests." OFF)
|
||||
IF(dcc_build_tests)
|
||||
enable_testing()
|
||||
FIND_PACKAGE(GMock)
|
||||
enable_testing()
|
||||
find_package(Qt5Test)
|
||||
#FIND_PACKAGE(GMock)
|
||||
ENDIF()
|
||||
|
||||
ADD_SUBDIRECTORY(3rd_party)
|
||||
|
||||
llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support tablegen)
|
||||
INCLUDE_DIRECTORIES(
|
||||
${PROJECT_SOURCE_DIR}
|
||||
3rd_party/libdisasm
|
||||
include
|
||||
include/idioms
|
||||
common
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${LLVM_INCLUDE_DIRS}
|
||||
)
|
||||
set(dcc_LIB_SOURCES
|
||||
src/ast.cpp
|
||||
src/backend.cpp
|
||||
src/bundle.cpp
|
||||
src/chklib.cpp
|
||||
src/comwrite.cpp
|
||||
src/control.cpp
|
||||
src/dataflow.cpp
|
||||
src/disassem.cpp
|
||||
src/error.cpp
|
||||
src/fixwild.cpp
|
||||
src/frontend.cpp
|
||||
src/graph.cpp
|
||||
src/hlicode.cpp
|
||||
src/hltype.cpp
|
||||
src/machine_x86.cpp
|
||||
src/icode.cpp
|
||||
src/RegisterNode
|
||||
src/idioms.cpp
|
||||
src/idioms/idiom1.cpp
|
||||
src/idioms/arith_idioms.cpp
|
||||
src/idioms/call_idioms.cpp
|
||||
src/idioms/epilogue_idioms.cpp
|
||||
src/idioms/mov_idioms.cpp
|
||||
src/idioms/neg_idioms.cpp
|
||||
src/idioms/shift_idioms.cpp
|
||||
src/idioms/xor_idioms.cpp
|
||||
src/locident.cpp
|
||||
src/liveness_set.cpp
|
||||
src/parser.cpp
|
||||
src/perfhlib.cpp
|
||||
src/procs.cpp
|
||||
src/project.cpp
|
||||
src/Procedure.cpp
|
||||
src/proplong.cpp
|
||||
src/reducible.cpp
|
||||
src/scanner.cpp
|
||||
src/symtab.cpp
|
||||
src/udm.cpp
|
||||
src/BasicBlock.cpp
|
||||
src/CallConvention.cpp
|
||||
)
|
||||
set(dcc_SOURCES
|
||||
src/dcc.cpp
|
||||
)
|
||||
set(dcc_HEADERS
|
||||
include/ast.h
|
||||
include/bundle.h
|
||||
include/BinaryImage.h
|
||||
include/dcc.h
|
||||
include/disassem.h
|
||||
include/dosdcc.h
|
||||
include/error.h
|
||||
include/graph.h
|
||||
include/hlicode.h
|
||||
include/machine_x86.h
|
||||
include/icode.h
|
||||
include/idioms/idiom.h
|
||||
include/idioms/idiom1.h
|
||||
include/idioms/arith_idioms.h
|
||||
include/idioms/call_idioms.h
|
||||
include/idioms/epilogue_idioms.h
|
||||
include/idioms/mov_idioms.h
|
||||
include/idioms/neg_idioms.h
|
||||
include/idioms/shift_idioms.h
|
||||
include/idioms/xor_idioms.h
|
||||
include/locident.h
|
||||
include/perfhlib.h
|
||||
include/project.h
|
||||
include/scanner.h
|
||||
include/state.h
|
||||
include/symtab.h
|
||||
include/types.h
|
||||
include/Procedure.h
|
||||
include/StackFrame.h
|
||||
include/BasicBlock.h
|
||||
include/CallConvention.h
|
||||
|
||||
)
|
||||
SOURCE_GROUP(Source FILES ${dcc_SOURCES})
|
||||
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
|
||||
|
||||
ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
|
||||
#cotire(dcc_lib)
|
||||
|
||||
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
|
||||
ADD_DEPENDENCIES(dcc_original dcc_lib)
|
||||
TARGET_LINK_LIBRARIES(dcc_original LLVMSupport dcc_lib disasm_s ${REQ_LLVM_LIBRARIES} LLVMSupport)
|
||||
if(dcc_build_tests)
|
||||
ADD_SUBDIRECTORY(3rd_party)
|
||||
ADD_SUBDIRECTORY(common)
|
||||
ADD_SUBDIRECTORY(tools)
|
||||
ADD_SUBDIRECTORY(src)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
21
CMakeScripts/DCC_Macros.cmake
Normal file
21
CMakeScripts/DCC_Macros.cmake
Normal file
@@ -0,0 +1,21 @@
|
||||
MACRO(ADD_UNIT_TEST name)
|
||||
IF(NOT ${name}_TEST_VISITED)
|
||||
# add the loader as a dll
|
||||
ADD_EXECUTABLE(${name} ${ARGN})
|
||||
qt5_use_modules(${name} Core)
|
||||
MESSAGE(WARNING "Adding test " ${name} " " ${ARGN})
|
||||
TARGET_LINK_LIBRARIES(${name} ${UNIT_TEST_LIBS})
|
||||
ADD_TEST(NAME ${name} COMMAND ${name})
|
||||
set_property(TEST ${name} APPEND PROPERTY ENVIRONMENT DCC_TEST_BASE=${PROJECT_SOURCE_DIR})
|
||||
SET(${name}_TEST_VISITED true)
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
||||
function(ADD_QTEST NAME)
|
||||
add_executable(${NAME} ${NAME}.cpp ${NAME}.h) #${PROTO_SRCS} ${PROTO_HDRS}
|
||||
target_link_libraries(${NAME} ${test_LIBRARIES})
|
||||
qt5_use_modules(${NAME} Core Test)
|
||||
|
||||
add_test( NAME ${NAME} COMMAND $<TARGET_FILE:${NAME}>)
|
||||
set_property(TEST ${NAME} APPEND PROPERTY ENVIRONMENT DCC_TEST_BASE=${PROJECT_SOURCE_DIR})
|
||||
endfunction()
|
||||
File diff suppressed because it is too large
Load Diff
127
Readme.md
Normal file
127
Readme.md
Normal file
@@ -0,0 +1,127 @@
|
||||
I've fixed many issues in this codebase, among other things - memory reallocation during decompilation.
|
||||
|
||||
To reflect those fixes, I've edited the original readme a bit.
|
||||
|
||||
* * *
|
||||
dcc Distribution
|
||||
================
|
||||
|
||||
The code provided in this distribution is (C) by their authors:
|
||||
- Cristina Cifuentes (most of dcc code)
|
||||
- Mike van Emmerik (signatures and prototype code)
|
||||
- Jeff Ledermann (some disassembly code)
|
||||
|
||||
and is provided "as is". Additional contributor list is available
|
||||
[on GitHub](https://github.com/nemerle/dcc/graphs/contributors).
|
||||
|
||||
The following files are included in the dccoo.tar.gz distribution:
|
||||
- dcc.zip (dcc.exe DOS program, 1995)
|
||||
- dccsrc.zip (source code *.c, *.h for dcc, 1993-1994)
|
||||
- dcc32.zip (dcc_oo.exe 32 bit console (Win95/Win-NT) program, 1997)
|
||||
- dccsrcoo.zip (source code *.cpp, *.h for "oo" dcc, 1993-1997)
|
||||
- dccbsig.zip (library signatures for Borland C compilers, 1994)
|
||||
- dccmsig.zip (library signatures for Microsoft C compilers, 1994)
|
||||
- dcctpsig.zip (library signatures for Turbo Pascal compilers, 1994)
|
||||
- dcclibs.dat (prototype file for C headers, 1994)
|
||||
- test.zip (sample test files: *.c *.exe *.b, 1993-1996)
|
||||
- makedsig.zip (creates a .sig file from a .lib C file, 1994)
|
||||
- makedstp.zip (creates a .sig file from a Pascal library file, 1994)
|
||||
- readsig.zip (reads signatures in a .sig file, 1994)
|
||||
- dispsrch.zip (displays the name of a function given a signature, 1994)
|
||||
- parsehdr.zip (generates a prototype file (dcclibs.dat) from C *.h files, 1994)
|
||||
|
||||
Note that the dcc_oo.exe program (in dcc32.zip) is a 32 bit program,
|
||||
so it won't work under Windows 3.1. Also, it is a console mode program,
|
||||
meaning that it has to be run in the "Command Prompt" window (sometimes
|
||||
known as the "Dos Box"). It is not a GUI program.
|
||||
|
||||
The following files are included in the test.zip file: fibo,
|
||||
benchsho, benchlng, benchfn, benchmul, byteops, intops, longops,
|
||||
max, testlong, matrixmu, strlen, dhamp.
|
||||
The version of dcc included in this distribution (dccsrcoo.zip and
|
||||
dcc32.exe) is a bit better than the first release, but it is still
|
||||
broken in some cases, and we do not have the time to work in this
|
||||
project at present so we cannot provide any changes.
|
||||
Comments on individual files:
|
||||
- fibo (fibonacci): the small model (fibos.exe) decompiles correctly,
|
||||
the large model (fibol.exe) expects an extra argument for
|
||||
`scanf()`. This argument is the segment and is not displayed.
|
||||
- benchsho: the first `scanf()` takes loc0 as an argument. This is
|
||||
part of a long variable, but dcc does not have any clue at that
|
||||
stage that the stack offset pushed on the stack is to be used
|
||||
as a long variable rather than an integer variable.
|
||||
- benchlng: as part of the `main()` code, `LO(loc1) | HI(loc1)` should
|
||||
be displayed instead of `loc3 | loc9`. These two integer variables
|
||||
are equivalent to the one long loc1 variable.
|
||||
- benchfn: see benchsho.
|
||||
- benchmul: see benchsho.
|
||||
- byteops: decompiles correctly.
|
||||
- intops: the du analysis for `DIV` and `MOD` is broken. dcc currently
|
||||
generates code for a long and an integer temporary register that
|
||||
were used as part of the analysis.
|
||||
- longops: decompiles correctly.
|
||||
- max: decompiles correctly.
|
||||
- testlong: this example decompiles correctly given the algorithms
|
||||
implemented in dcc. However, it shows that when long variables
|
||||
are defined and used as integers (or long) without giving dcc
|
||||
any hint that this is happening, the variable will be treated as
|
||||
two integer variables. This is due to the fact that the assembly
|
||||
code is in terms of integer registers, and long registers are not
|
||||
available in 80286, so a long variable is equivalent to two integer
|
||||
registers. dcc only knows of this through idioms such as add two
|
||||
long variables.
|
||||
- matrixmu: decompiles correctly. Shows that arrays are not supported
|
||||
in dcc.
|
||||
- strlen: decompiles correctly. Shows that pointers are partially
|
||||
supported by dcc.
|
||||
- dhamp: this program has far more data types than what dcc recognizes
|
||||
at present.
|
||||
|
||||
Our thanks to Gary Shaffstall for some debugging work. Current bugs
|
||||
are:
|
||||
- [ ] if the code generated in the one line is too long, the (static)
|
||||
buffer used for that line is clobbered. Solution: make the buffer
|
||||
larger (currently 200 chars).
|
||||
- [ ] the large memory model problem & `scanf()`
|
||||
- [ ] dcc's error message shows a p option available which doesn't
|
||||
exist, and doesn't show an i option which exists.
|
||||
- [x] there is a nasty problem whereby some arrays can get reallocated
|
||||
to a new address, and some pointers can become invalid. This mainly
|
||||
tends to happen to larger executable files. A major rewrite will
|
||||
probably be required to fix this.
|
||||
|
||||
For more information refer to the thesis "Reverse Compilation
|
||||
Techniques" by Cristina Cifuentes, Queensland University of
|
||||
Technology, 1994, and the dcc home page:
|
||||
http://www.it.uq.edu.au/groups/csm/dcc_readme.html
|
||||
|
||||
Please note that the executable version of dcc provided in this
|
||||
distribution does not necessarily match the source code provided,
|
||||
some changes were done without us keeping track of every change.
|
||||
|
||||
Using dcc
|
||||
---------
|
||||
|
||||
Here is a very brief summary of switches for dcc:
|
||||
|
||||
* `a1`, `a2`: assembler output, before and after re-ordering of input code
|
||||
* `c`: Attempt to follow control through indirect call instructions
|
||||
* `i`: Enter interactive disassembler
|
||||
* `m`: Memory map
|
||||
* `s`: Statistics summary
|
||||
* `v`, `V`: verbose (and Very verbose)
|
||||
* `o` filename: Use filename as assembler output file
|
||||
|
||||
If dcc encounters illegal instructions, it will attempt to enter the so called
|
||||
interactive disassembler. The idea of this was to allow commands to fix the
|
||||
problem so that dcc could continue, but no such changes are implemented
|
||||
as yet. (Note: the Unix versions do not have the interactive disassembler). If
|
||||
you get into this, you can get out of it by pressing `^X` (control-X). Once dcc
|
||||
has entered the interactive disassembler, however, there is little chance that
|
||||
it will recover and produce useful output.
|
||||
|
||||
If dcc loads the signature file `dccxxx.sig`, this means that it has not
|
||||
recognised the compiler library used. You can place the signatures in a
|
||||
different direcory to where you are working if you set the DCC environment
|
||||
variable to point to their path. Note that if dcc can't find its signature
|
||||
files, it will be severely handicapped.
|
||||
@@ -2,5 +2,6 @@
|
||||
#cd bld
|
||||
#make -j5
|
||||
#cd ..
|
||||
mkdir -p tests/outputs
|
||||
./test_use_base.sh
|
||||
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff -wB tests/prev/ tests/outputs/
|
||||
|
||||
7
common/CMakeLists.txt
Normal file
7
common/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
set(SRC
|
||||
perfhlib.cpp
|
||||
perfhlib.h
|
||||
PatternCollector.h
|
||||
|
||||
)
|
||||
add_library(dcc_hash STATIC ${SRC})
|
||||
82
common/PatternCollector.h
Normal file
82
common/PatternCollector.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef PATTERNCOLLECTOR
|
||||
#define PATTERNCOLLECTOR
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#define SYMLEN 16 /* Number of chars in the symbol name, incl null */
|
||||
#define PATLEN 23 /* Number of bytes in the pattern part */
|
||||
|
||||
struct HASHENTRY
|
||||
{
|
||||
char name[SYMLEN]; /* The symbol name */
|
||||
uint8_t pat [PATLEN]; /* The pattern */
|
||||
uint16_t offset; /* Offset (needed temporarily) */
|
||||
};
|
||||
|
||||
struct PatternCollector {
|
||||
uint8_t buf[100], bufSave[7]; /* Temp buffer for reading the file */
|
||||
uint16_t readShort(FILE *f)
|
||||
{
|
||||
uint8_t b1, b2;
|
||||
|
||||
if (fread(&b1, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
if (fread(&b2, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
return (b2 << 8) + b1;
|
||||
}
|
||||
|
||||
void grab(FILE *f,int n)
|
||||
{
|
||||
if (fread(buf, 1, n, f) != (size_t)n)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t readByte(FILE *f)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
if (fread(&b, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
uint16_t readWord(FILE *fl)
|
||||
{
|
||||
uint8_t b1, b2;
|
||||
|
||||
b1 = readByte(fl);
|
||||
b2 = readByte(fl);
|
||||
|
||||
return b1 + (b2 << 8);
|
||||
}
|
||||
|
||||
/* Called by map(). Return the i+1th key in *pKeys */
|
||||
uint8_t *getKey(int i)
|
||||
{
|
||||
return keys[i].pat;
|
||||
}
|
||||
/* Display key i */
|
||||
void dispKey(int i)
|
||||
{
|
||||
printf("%s", keys[i].name);
|
||||
}
|
||||
std::vector<HASHENTRY> keys; /* array of keys */
|
||||
virtual int readSyms(FILE *f)=0;
|
||||
};
|
||||
#endif // PATTERNCOLLECTOR
|
||||
|
||||
438
common/perfhlib.cpp
Normal file
438
common/perfhlib.cpp
Normal file
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
*$Log: perfhlib.c,v $
|
||||
* Revision 1.5 93/09/29 14:45:02 emmerik
|
||||
* Oops, didn't do the casts last check in
|
||||
*
|
||||
* Revision 1.4 93/09/29 14:41:45 emmerik
|
||||
* Added casts to mod instructions to keep the SVR4 compiler happy
|
||||
*
|
||||
*
|
||||
* Perfect hashing function library. Contains functions to generate perfect
|
||||
* hashing functions
|
||||
*/
|
||||
#include "perfhlib.h"
|
||||
#include "PatternCollector.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cassert>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
/* Private data structures */
|
||||
|
||||
//static int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
//static int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
//static int SetSize; /* Size of the char set */
|
||||
//static char SetMin; /* First char in the set */
|
||||
//static int NumVert; /* c times NumEntry */
|
||||
|
||||
//static uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
static uint16_t *T1, *T2; /* Pointers to T1[i], T2[i] */
|
||||
|
||||
static int *graphNode; /* The array of edges */
|
||||
static int *graphNext; /* Linked list of edges */
|
||||
static int *graphFirst;/* First edge at a vertex */
|
||||
|
||||
|
||||
static int numEdges; /* An edge counter */
|
||||
static bool *visited; /* Array of bools: whether visited */
|
||||
static bool *deleted; /* Array of bools: whether deleted */
|
||||
|
||||
/* Private prototypes */
|
||||
static void duplicateKeys(int v1, int v2);
|
||||
|
||||
void PerfectHash::setHashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||
int _NumVert)
|
||||
{
|
||||
/* These parameters are stored in statics so as to obviate the need for
|
||||
passing all these (or defererencing pointers) for every call to hash()
|
||||
*/
|
||||
|
||||
NumEntry = _NumEntry;
|
||||
EntryLen = _EntryLen;
|
||||
SetSize = _SetSize;
|
||||
SetMin = _SetMin;
|
||||
NumVert = _NumVert;
|
||||
|
||||
/* Allocate the variable sized tables etc */
|
||||
if ((T1base = (uint16_t *)malloc(EntryLen * SetSize * sizeof(uint16_t))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((T2base = (uint16_t *)malloc(EntryLen * SetSize * sizeof(uint16_t))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
|
||||
if ((graphNode = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((graphNext = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((graphFirst = (int *)malloc((NumVert + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
|
||||
if ((g = (short *)malloc((NumVert+1) * sizeof(short))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((visited = (bool *)malloc((NumVert+1) * sizeof(bool))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((deleted = (bool *)malloc((NumEntry+1) * sizeof(bool))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
return;
|
||||
|
||||
BadAlloc:
|
||||
printf("Could not allocate memory\n");
|
||||
hashCleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void PerfectHash::hashCleanup(void)
|
||||
{
|
||||
/* Free the storage for variable sized tables etc */
|
||||
if (T1base) free(T1base);
|
||||
if (T2base) free(T2base);
|
||||
if (graphNode) free(graphNode);
|
||||
if (graphNext) free(graphNext);
|
||||
if (graphFirst) free(graphFirst);
|
||||
if (g) free(g);
|
||||
if (visited) free(visited);
|
||||
if (deleted) free(deleted);
|
||||
}
|
||||
|
||||
void PerfectHash::map(PatternCollector *collector)
|
||||
{
|
||||
m_collector = collector;
|
||||
assert(nullptr!=collector);
|
||||
int i, j, c;
|
||||
uint16_t f1, f2;
|
||||
bool cycle;
|
||||
uint8_t *keys;
|
||||
|
||||
c = 0;
|
||||
|
||||
do
|
||||
{
|
||||
initGraph();
|
||||
cycle = false;
|
||||
|
||||
/* Randomly generate T1 and T2 */
|
||||
for (i=0; i < SetSize*EntryLen; i++)
|
||||
{
|
||||
T1base[i] = rand() % NumVert;
|
||||
T2base[i] = rand() % NumVert;
|
||||
}
|
||||
|
||||
for (i=0; i < NumEntry; i++)
|
||||
{
|
||||
f1 = 0; f2 = 0;
|
||||
keys = m_collector->getKey(i);
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
T2 = T2base + j * SetSize;
|
||||
f1 += T1[keys[j] - SetMin];
|
||||
f2 += T2[keys[j] - SetMin];
|
||||
}
|
||||
f1 %= (uint16_t)NumVert;
|
||||
f2 %= (uint16_t)NumVert;
|
||||
if (f1 == f2)
|
||||
{
|
||||
/* A self loop. Reject! */
|
||||
printf("Self loop on vertex %d!\n", f1);
|
||||
cycle = true;
|
||||
break;
|
||||
}
|
||||
addToGraph(numEdges++, f1, f2);
|
||||
}
|
||||
if (cycle or (cycle = isCycle())) /* OK - is there a cycle? */
|
||||
{
|
||||
printf("Iteration %d\n", ++c);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (/* there is a cycle */ 1);
|
||||
|
||||
}
|
||||
|
||||
/* Initialise the graph */
|
||||
void PerfectHash::initGraph()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1; i <= NumVert; i++)
|
||||
{
|
||||
graphFirst[i] = 0;
|
||||
}
|
||||
|
||||
for (i= -NumEntry; i <= NumEntry; i++)
|
||||
{
|
||||
/* No need to init graphNode[] as they will all be filled by successive
|
||||
calls to addToGraph() */
|
||||
graphNext[NumEntry+i] = 0;
|
||||
}
|
||||
|
||||
numEdges = 0;
|
||||
}
|
||||
|
||||
/* Add an edge e between vertices v1 and v2 */
|
||||
/* e, v1, v2 are 0 based */
|
||||
void PerfectHash::addToGraph(int e, int v1, int v2)
|
||||
{
|
||||
e++; v1++; v2++; /* So much more convenient */
|
||||
|
||||
graphNode[NumEntry+e] = v2; /* Insert the edge information */
|
||||
graphNode[NumEntry-e] = v1;
|
||||
|
||||
graphNext[NumEntry+e] = graphFirst[v1]; /* Insert v1 to list of alphas */
|
||||
graphFirst[v1]= e;
|
||||
graphNext[NumEntry-e] = graphFirst[v2]; /* Insert v2 to list of omegas */
|
||||
graphFirst[v2]= -e;
|
||||
|
||||
}
|
||||
|
||||
bool PerfectHash::DFS(int parentE, int v)
|
||||
{
|
||||
int e, w;
|
||||
|
||||
/* Depth first search of the graph, starting at vertex v, looking for
|
||||
cycles. parent and v are origin 1. Note parent is an EDGE,
|
||||
not a vertex */
|
||||
|
||||
visited[v] = true;
|
||||
|
||||
/* For each e incident with v .. */
|
||||
for (e = graphFirst[v]; e; e = graphNext[NumEntry+e])
|
||||
{
|
||||
uint8_t *key1;
|
||||
|
||||
if (deleted[abs(e)])
|
||||
{
|
||||
/* A deleted key. Just ignore it */
|
||||
continue;
|
||||
}
|
||||
key1 = m_collector->getKey(abs(e)-1);
|
||||
w = graphNode[NumEntry+e];
|
||||
if (visited[w])
|
||||
{
|
||||
/* Did we just come through this edge? If so, ignore it. */
|
||||
if (abs(e) != abs(parentE))
|
||||
{
|
||||
/* There is a cycle in the graph. There is some subtle code here
|
||||
to work around the distinct possibility that there may be
|
||||
duplicate keys. Duplicate keys will always cause unit
|
||||
cycles, since f1 and f2 (used to select v and w) will be the
|
||||
same for both. The edges (representing an index into the
|
||||
array of keys) are distinct, but the key values are not.
|
||||
The logic is as follows: for the candidate edge e, check to
|
||||
see if it terminates in the parent vertex. If so, we test
|
||||
the keys associated with e and the parent, and if they are
|
||||
the same, we can safely ignore e for the purposes of cycle
|
||||
detection, since edge e adds nothing to the cycle. Cycles
|
||||
involving v, w, and e0 will still be found. The parent
|
||||
edge was not similarly eliminated because at the time when
|
||||
it was a candidate, v was not yet visited.
|
||||
We still have to remove the key from further consideration,
|
||||
since each edge is visited twice, but with a different
|
||||
parent edge each time.
|
||||
*/
|
||||
/* We save some stack space by calculating the parent vertex
|
||||
for these relatively few cases where it is needed */
|
||||
int parentV = graphNode[NumEntry-parentE];
|
||||
|
||||
if (w == parentV)
|
||||
{
|
||||
uint8_t *key2;
|
||||
|
||||
key2=m_collector->getKey(abs(parentE)-1);
|
||||
if (memcmp(key1, key2, EntryLen) == 0)
|
||||
{
|
||||
printf("Duplicate keys with edges %d and %d (",
|
||||
e, parentE);
|
||||
m_collector->dispKey(abs(e)-1);
|
||||
printf(" & ");
|
||||
m_collector->dispKey(abs(parentE)-1);
|
||||
printf(")\n");
|
||||
deleted[abs(e)] = true; /* Wipe the key */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A genuine (unit) cycle. */
|
||||
printf("There is a unit cycle involving vertex %d and edge %d\n", v, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have reached a previously visited vertex not the
|
||||
parent. Therefore, we have uncovered a genuine cycle */
|
||||
printf("There is a cycle involving vertex %d and edge %d\n", v, e);
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Not yet seen. Traverse it */
|
||||
{
|
||||
if (DFS(e, w))
|
||||
{
|
||||
/* Cycle found deeper down. Exit */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PerfectHash::isCycle(void)
|
||||
{
|
||||
int v, e;
|
||||
|
||||
for (v=1; v <= NumVert; v++)
|
||||
{
|
||||
visited[v] = false;
|
||||
}
|
||||
for (e=1; e <= NumEntry; e++)
|
||||
{
|
||||
deleted[e] = false;
|
||||
}
|
||||
for (v=1; v <= NumVert; v++)
|
||||
{
|
||||
if (not visited[v])
|
||||
{
|
||||
if (DFS(-32767, v))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PerfectHash::traverse(int u)
|
||||
{
|
||||
int w, e;
|
||||
|
||||
visited[u] = true;
|
||||
/* Find w, the neighbours of u, by searching the edges e associated with u */
|
||||
e = graphFirst[1+u];
|
||||
while (e)
|
||||
{
|
||||
w = graphNode[NumEntry+e]-1;
|
||||
if (not visited[w])
|
||||
{
|
||||
g[w] = (abs(e)-1 - g[u]) % NumEntry;
|
||||
if (g[w] < 0) g[w] += NumEntry; /* Keep these positive */
|
||||
traverse(w);
|
||||
}
|
||||
e = graphNext[NumEntry+e];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PerfectHash::assign(void)
|
||||
{
|
||||
int v;
|
||||
|
||||
|
||||
for (v=0; v < NumVert; v++)
|
||||
{
|
||||
g[v] = 0; /* g is sparse; leave the gaps 0 */
|
||||
visited[v] = false;
|
||||
}
|
||||
|
||||
for (v=0; v < NumVert; v++)
|
||||
{
|
||||
if (not visited[v])
|
||||
{
|
||||
g[v] = 0;
|
||||
traverse(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PerfectHash::hash(uint8_t *string)
|
||||
{
|
||||
uint16_t u, v;
|
||||
int j;
|
||||
|
||||
u = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
u += T1[string[j] - SetMin];
|
||||
}
|
||||
u %= NumVert;
|
||||
|
||||
v = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T2 = T2base + j * SetSize;
|
||||
v += T2[string[j] - SetMin];
|
||||
}
|
||||
v %= NumVert;
|
||||
|
||||
return (g[u] + g[v]) % NumEntry;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void dispRecord(int i);
|
||||
|
||||
void
|
||||
duplicateKeys(int v1, int v2)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t *keys;
|
||||
int u, v;
|
||||
|
||||
v1--; v2--; /* These guys are origin 1 */
|
||||
|
||||
printf("Duplicate keys:\n");
|
||||
|
||||
for (i=0; i < NumEntry; i++)
|
||||
{
|
||||
getKey(i, &keys);
|
||||
u = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
u += T1[keys[j] - SetMin];
|
||||
}
|
||||
u %= NumVert;
|
||||
if ((u != v1) and (u != v2)) continue;
|
||||
|
||||
v = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T2 = T2base + j * SetSize;
|
||||
v += T2[keys[j] - SetMin];
|
||||
}
|
||||
v %= NumVert;
|
||||
|
||||
if ((v == v2) or (v == v1))
|
||||
{
|
||||
printf("Entry #%d key: ", i+1);
|
||||
for (j=0; j < EntryLen; j++) printf("%02X ", keys[j]);
|
||||
printf("\n");
|
||||
dispRecord(i+1);
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
39
common/perfhlib.h
Normal file
39
common/perfhlib.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
/** Perfect hashing function library. Contains functions to generate perfect
|
||||
hashing functions */
|
||||
struct PatternCollector;
|
||||
struct PerfectHash {
|
||||
uint16_t *T1base;
|
||||
uint16_t *T2base; /* Pointers to start of T1, T2 */
|
||||
short *g; /* g[] */
|
||||
|
||||
int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
int SetSize; /* Size of the char set */
|
||||
char SetMin; /* First char in the set */
|
||||
int NumVert; /* c times NumEntry */
|
||||
/** Set the parameters for the hash table */
|
||||
void setHashParams(int _numEntry, int _entryLen, int _setSize, char _setMin, int _numVert);
|
||||
|
||||
public:
|
||||
void map(PatternCollector * collector); /* Part 1 of creating the tables */
|
||||
void hashCleanup(); /* Frees memory allocated by setHashParams() */
|
||||
void assign(); /* Part 2 of creating the tables */
|
||||
int hash(uint8_t *string); /* Hash the string to an int 0 .. NUMENTRY-1 */
|
||||
const uint16_t *readT1(void) const { return T1base; }
|
||||
const uint16_t *readT2(void) const { return T2base; }
|
||||
const uint16_t *readG(void) const { return (uint16_t *)g; }
|
||||
uint16_t *readT1(void){ return T1base; }
|
||||
uint16_t *readT2(void){ return T2base; }
|
||||
uint16_t *readG(void) { return (uint16_t *)g; }
|
||||
private:
|
||||
void initGraph();
|
||||
void addToGraph(int e, int v1, int v2);
|
||||
bool isCycle();
|
||||
bool DFS(int parentE, int v);
|
||||
void traverse(int u);
|
||||
PatternCollector *m_collector; /* used to retrieve the keys */
|
||||
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/bin/bash
|
||||
mkdir -p tests/outputs
|
||||
./test_use_all.sh
|
||||
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff -wB tests/prev/ tests/outputs/
|
||||
|
||||
@@ -3,15 +3,13 @@
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <string>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include "icode.h"
|
||||
#include "types.h"
|
||||
#include "graph.h"
|
||||
//#include "icode.h"
|
||||
/* Basic block (BB) node definition */
|
||||
struct Function;
|
||||
class Function;
|
||||
class CIcodeRec;
|
||||
struct BB;
|
||||
struct LOCAL_ID;
|
||||
@@ -27,9 +25,9 @@ struct TYPEADR_TYPE
|
||||
TYPEADR_TYPE(interval *v) : ip(0),BBptr(nullptr),intPtr(v)
|
||||
{}
|
||||
};
|
||||
struct BB : public llvm::ilist_node<BB>
|
||||
struct BB
|
||||
{
|
||||
friend struct Function;
|
||||
friend class Function;
|
||||
private:
|
||||
BB(const BB&);
|
||||
BB() : nodeType(0),traversed(DFS_NONE),
|
||||
@@ -59,10 +57,10 @@ public:
|
||||
ICODE &front();
|
||||
ICODE &back();
|
||||
size_t size();
|
||||
uint8_t nodeType; /* Type of node */
|
||||
eDFS traversed; /* last traversal id is held here traversed yet? */
|
||||
int numHlIcodes; /* No. of high-level icodes */
|
||||
uint32_t flg; /* BB flags */
|
||||
uint8_t nodeType; /* Type of node */
|
||||
eDFS traversed; /* last traversal id is held here traversed yet? */
|
||||
int numHlIcodes; /* No. of high-level icodes */
|
||||
uint32_t flg; /* BB flags */
|
||||
|
||||
/* In edges and out edges */
|
||||
std::vector<BB *> inEdges; // does not own held pointers
|
||||
@@ -80,10 +78,10 @@ public:
|
||||
interval *correspInt; //!< Corresponding interval in derived graph Gi-1
|
||||
// For live register analysis
|
||||
// LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b))
|
||||
LivenessSet liveUse; /* LiveUse(b) */
|
||||
LivenessSet def; /* Def(b) */
|
||||
LivenessSet liveIn; /* LiveIn(b) */
|
||||
LivenessSet liveOut; /* LiveOut(b) */
|
||||
LivenessSet liveUse; /* LiveUse(b) */
|
||||
LivenessSet def; /* Def(b) */
|
||||
LivenessSet liveIn; /* LiveIn(b) */
|
||||
LivenessSet liveOut; /* LiveOut(b) */
|
||||
|
||||
/* For structuring analysis */
|
||||
int dfsFirstNum; /* DFS #: first visit of node */
|
||||
@@ -111,7 +109,7 @@ public:
|
||||
///
|
||||
const Function *getParent() const { return Parent; }
|
||||
Function *getParent() { return Parent; }
|
||||
void writeBB(std::ostream &ostr, int lev, Function *pProc, int *numLoc);
|
||||
void writeBB(QTextStream & ostr, int lev, Function *pProc, int *numLoc);
|
||||
BB * rmJMP(int marker, BB *pBB);
|
||||
void genDU1();
|
||||
void findBBExps(LOCAL_ID &locals, Function *f);
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
struct PROG /* Loaded program image parameters */
|
||||
{
|
||||
int16_t initCS;
|
||||
int16_t initIP; /* These are initial load values */
|
||||
int16_t initSS; /* Probably not of great interest */
|
||||
uint16_t initSP;
|
||||
bool fCOM; /* Flag set if COM program (else EXE)*/
|
||||
int cReloc; /* No. of relocation table entries */
|
||||
uint32_t * relocTable; /* Ptr. to relocation table */
|
||||
uint8_t * map; /* Memory bitmap ptr */
|
||||
int cProcs; /* Number of procedures so far */
|
||||
int offMain; /* The offset of the main() proc */
|
||||
uint16_t segMain; /* The segment of the main() proc */
|
||||
bool bSigs; /* True if signatures loaded */
|
||||
int cbImage; /* Length of image in bytes */
|
||||
int16_t initCS=0;
|
||||
int16_t initIP=0; /* These are initial load values */
|
||||
int16_t initSS=0; /* Probably not of great interest */
|
||||
uint16_t initSP=0;
|
||||
bool fCOM=false; /* Flag set if COM program (else EXE)*/
|
||||
int cReloc=0; /* No. of relocation table entries */
|
||||
std::vector<uint32_t> relocTable; /* Ptr. to relocation table */
|
||||
uint8_t * map=nullptr; /* Memory bitmap ptr */
|
||||
int cProcs=0; /* Number of procedures so far */
|
||||
int offMain=0; /* The offset of the main() proc */
|
||||
uint16_t segMain=0; /* The segment of the main() proc */
|
||||
int cbImage=0; /* Length of image in bytes */
|
||||
uint8_t * Imagez=nullptr; /* Allocated by loader to hold entire program image */
|
||||
public:
|
||||
const uint8_t *image() const {return Imagez;}
|
||||
uint8_t * Imagez; /* Allocated by loader to hold entire program image */
|
||||
int addressingMode;
|
||||
void displayLoadInfo();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,31 +1,41 @@
|
||||
#pragma once
|
||||
#include "ast.h"
|
||||
|
||||
#ifdef PASCAL
|
||||
#undef PASCAL
|
||||
#endif
|
||||
class QTextStream;
|
||||
|
||||
struct CConv {
|
||||
enum Type {
|
||||
enum CC_Type {
|
||||
UNKNOWN=0,
|
||||
C,
|
||||
PASCAL
|
||||
};
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode)=0;
|
||||
virtual void writeComments(std::ostream &)=0;
|
||||
static CConv * create(Type v);
|
||||
//! given return and argument types fill Function's STKFRAME and return locations
|
||||
virtual void calculateStackLayout(Function *func)=0;
|
||||
virtual void writeComments(QTextStream &)=0;
|
||||
static CConv * create(CC_Type v);
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
struct C_CallingConvention : public CConv {
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode);
|
||||
virtual void writeComments(std::ostream &);
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode) override;
|
||||
virtual void writeComments(QTextStream &) override;
|
||||
void calculateStackLayout(Function *func) override;
|
||||
|
||||
private:
|
||||
int processCArg(Function *callee, Function *pProc, ICODE *picode, size_t numArgs);
|
||||
};
|
||||
struct Pascal_CallingConvention : public CConv {
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode);
|
||||
virtual void writeComments(std::ostream &);
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode) override;
|
||||
virtual void writeComments(QTextStream &) override;
|
||||
void calculateStackLayout(Function *func) override;
|
||||
};
|
||||
struct Unknown_CallingConvention : public CConv {
|
||||
void processHLI(Function *func, Expr *_exp, iICODE picode) {}
|
||||
virtual void writeComments(std::ostream &);
|
||||
void processHLI(Function *func, Expr *_exp, iICODE picode) override {}
|
||||
void calculateStackLayout(Function *func) override;
|
||||
virtual void writeComments(QTextStream &) override;
|
||||
};
|
||||
|
||||
19
include/CallGraph.h
Normal file
19
include/CallGraph.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "Procedure.h"
|
||||
/* CALL GRAPH NODE */
|
||||
struct CALL_GRAPH
|
||||
{
|
||||
PtrFunction proc; /* Pointer to procedure in pProcList */
|
||||
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
|
||||
public:
|
||||
void write();
|
||||
CALL_GRAPH()
|
||||
{
|
||||
}
|
||||
public:
|
||||
void writeNodeCallGraph(int indIdx);
|
||||
bool insertCallGraph(PtrFunction caller, PtrFunction callee);
|
||||
//bool insertCallGraph(PtrFunction caller, PtrFunction callee);
|
||||
void insertArc(PtrFunction newProc);
|
||||
};
|
||||
//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
44
include/DccFrontend.h
Normal file
44
include/DccFrontend.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#include <QtCore/QObject>
|
||||
#include "src/Command.h"
|
||||
#include "project.h"
|
||||
|
||||
class Project;
|
||||
class DccFrontend : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
void LoadImage();
|
||||
void parse(Project &proj);
|
||||
public:
|
||||
explicit DccFrontend(QObject *parent = 0);
|
||||
bool FrontEnd(); /* frontend.c */
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
struct MachineStateInitialization : public Command {
|
||||
|
||||
MachineStateInitialization() : Command("Initialize simulated machine state",eProject) {}
|
||||
bool execute(CommandContext *ctx) override;
|
||||
};
|
||||
|
||||
struct FindMain : public Command {
|
||||
FindMain() : Command("Locate the main entry point",eProject) {}
|
||||
bool execute(CommandContext *ctx);
|
||||
};
|
||||
|
||||
struct CreateFunction : public Command {
|
||||
QString m_name;
|
||||
SegOffAddr m_addr;
|
||||
FunctionType *m_type;
|
||||
CreateFunction(QString name,SegOffAddr address,FunctionType *f) : Command("Create function",eProject),
|
||||
m_name(name),
|
||||
m_addr(address),
|
||||
m_type(f)
|
||||
{}
|
||||
QString instanceDescription() const override;
|
||||
|
||||
bool execute(CommandContext *ctx) override;
|
||||
};
|
||||
@@ -90,9 +90,9 @@ enum eLLFlags
|
||||
/* Types of icodes */
|
||||
enum icodeType
|
||||
{
|
||||
NOT_SCANNED = 0, // not even scanned yet
|
||||
LOW_LEVEL, // low-level icode
|
||||
HIGH_LEVEL // high-level icode
|
||||
NOT_SCANNED_ICODE = 0, // not even scanned yet
|
||||
LOW_LEVEL_ICODE, // low-level icode
|
||||
HIGH_LEVEL_ICODE // high-level icode
|
||||
};
|
||||
|
||||
|
||||
@@ -263,7 +263,8 @@ enum hlType
|
||||
TYPE_STR, /* string */
|
||||
TYPE_CONST, /* constant (any type) */
|
||||
TYPE_FLOAT, /* floating point */
|
||||
TYPE_DOUBLE /* double precision float */
|
||||
TYPE_DOUBLE, /* double precision float */
|
||||
TYPE_FUNC
|
||||
};
|
||||
|
||||
/* Operand is defined, used or both flag */
|
||||
|
||||
@@ -1,77 +1,89 @@
|
||||
#pragma once
|
||||
#include <llvm/ADT/ilist.h>
|
||||
//#include <llvm/ADT/ilist_node.h>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include "BasicBlock.h"
|
||||
#include "locident.h"
|
||||
#include "state.h"
|
||||
#include "icode.h"
|
||||
#include "StackFrame.h"
|
||||
#include "CallConvention.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <QtCore/QString>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
|
||||
class QIODevice;
|
||||
class QTextStream;
|
||||
|
||||
/* PROCEDURE NODE */
|
||||
struct CALL_GRAPH;
|
||||
struct Expr;
|
||||
struct Disassembler;
|
||||
struct Function;
|
||||
class Function;
|
||||
struct CALL_GRAPH;
|
||||
struct PROG;
|
||||
struct IStructuredTextTarget;
|
||||
|
||||
struct Function;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
// Traits for intrusive list of basic blocks...
|
||||
template<>
|
||||
struct ilist_traits<BB> : public ilist_default_traits<BB>
|
||||
{
|
||||
|
||||
// createSentinel is used to get hold of the node that marks the end of the
|
||||
// list... (same trick used here as in ilist_traits<Instruction>)
|
||||
BB *createSentinel() const {
|
||||
return static_cast<BB*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(BB*) {}
|
||||
|
||||
BB *provideInitialHead() const { return createSentinel(); }
|
||||
BB *ensureHead(BB*) const { return createSentinel(); }
|
||||
static void noteHead(BB*, BB*) {}
|
||||
|
||||
//static ValueSymbolTable *getSymTab(Function *ItemParent);
|
||||
private:
|
||||
mutable ilist_half_node<BB> Sentinel;
|
||||
};
|
||||
}
|
||||
/* Procedure FLAGS */
|
||||
enum PROC_FLAGS
|
||||
{
|
||||
PROC_BADINST=0x00000100,/* Proc contains invalid or 386 instruction */
|
||||
PROC_IJMP =0x00000200,/* Proc incomplete due to indirect jmp */
|
||||
PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */
|
||||
PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */
|
||||
// CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */
|
||||
// CALL_C =0x00004000, /* Proc uses C calling convention */
|
||||
// CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */
|
||||
PROC_NEAR =0x00010000, /* Proc exits with near return */
|
||||
PROC_FAR =0x00020000, /* Proc exits with far return */
|
||||
GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
|
||||
SI_REGVAR =0x00200000, /* SI is used as a stack variable */
|
||||
DI_REGVAR =0x00400000, /* DI is used as a stack variable */
|
||||
PROC_IS_FUNC=0x00800000, /* Proc is a function */
|
||||
REG_ARGS =0x01000000, /* Proc has registers as arguments */
|
||||
// PROC_VARARG =0x02000000, /* Proc has variable arguments */
|
||||
PROC_OUTPUT =0x04000000, /* C for this proc has been output */
|
||||
PROC_RUNTIME=0x08000000, /* Proc is part of the runtime support */
|
||||
PROC_ISLIB =0x10000000, /* Proc is a library function */
|
||||
PROC_ASM =0x20000000, /* Proc is an intrinsic assembler routine */
|
||||
PROC_IS_HLL =0x40000000 /* Proc has HLL prolog code */
|
||||
//#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
PROC_BADINST=0x00000100, /* Proc contains invalid or 386 instruction */
|
||||
PROC_IJMP =0x00000200, /* Proc incomplete due to indirect jmp */
|
||||
PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */
|
||||
PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */
|
||||
PROC_NEAR =0x00010000, /* Proc exits with near return */
|
||||
PROC_FAR =0x00020000, /* Proc exits with far return */
|
||||
GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
|
||||
SI_REGVAR =0x00200000, /* SI is used as a stack variable */
|
||||
DI_REGVAR =0x00400000, /* DI is used as a stack variable */
|
||||
REG_ARGS =0x01000000, /* Proc has registers as arguments */
|
||||
// PROC_VARARG =0x02000000, /* Proc has variable arguments */
|
||||
PROC_OUTPUT =0x04000000, /* C for this proc has been output */
|
||||
PROC_RUNTIME=0x08000000, /* Proc is part of the runtime support */
|
||||
PROC_ISLIB =0x10000000, /* Proc is a library function */
|
||||
PROC_ASM =0x20000000, /* Proc is an intrinsic assembler routine */
|
||||
PROC_IS_HLL =0x40000000 /* Proc has HLL prolog code */
|
||||
//#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
};
|
||||
|
||||
struct FunctionType
|
||||
struct Type {
|
||||
hlType dcc_type;
|
||||
};
|
||||
struct FunctionType : public Type
|
||||
{
|
||||
CConv * m_call_conv;
|
||||
std::vector<Type> ContainedTys;
|
||||
ID retVal; /* Return value - identifier */
|
||||
bool m_vararg=false;
|
||||
unsigned getNumParams() const { return ContainedTys.size(); }
|
||||
bool isVarArg() const {return m_vararg;}
|
||||
void setReturnType(hlType t) {
|
||||
retVal.type = t;
|
||||
}
|
||||
void setReturnLocation(const LONGID_TYPE &v) {
|
||||
retVal.loc = REG_FRAME;
|
||||
retVal.longId() = v;
|
||||
}
|
||||
void setReturnLocation(eReg reg) {
|
||||
retVal.loc = REG_FRAME;
|
||||
retVal.id.regi = reg;
|
||||
}
|
||||
hlType getReturnType() const { return retVal.type; }
|
||||
void addArgument(hlType hl) {
|
||||
ContainedTys.push_back(Type {hl});
|
||||
}
|
||||
void clearArguments() { ContainedTys.clear(); }
|
||||
|
||||
void setCallingConvention(CConv::CC_Type cc);
|
||||
|
||||
static FunctionType *get(Type result,std::vector<Type> params, bool vararg_func) {
|
||||
FunctionType * res = new FunctionType;
|
||||
res->setReturnType(result.dcc_type);
|
||||
std::swap(res->ContainedTys,params);
|
||||
res->m_vararg = vararg_func;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
struct Assignment
|
||||
{
|
||||
@@ -107,33 +119,44 @@ public:
|
||||
}
|
||||
void push_back(BB *v) { m_listBB.push_back(v);}
|
||||
};
|
||||
struct Function : public llvm::ilist_node<Function>
|
||||
typedef std::shared_ptr<Function> PtrFunction;
|
||||
enum DecompilationStep : uint32_t {
|
||||
eNotDecoded, // no processing done yet
|
||||
eDisassemblyInProgress,
|
||||
eDissassembled, // low level disassembly done
|
||||
//eLocatedImpureRefs,
|
||||
//eStackTracing, // tracing stack depth across function calls
|
||||
|
||||
};
|
||||
|
||||
class Function : public std::enable_shared_from_this<Function>
|
||||
{
|
||||
typedef llvm::iplist<BB> BasicBlockListType;
|
||||
typedef std::list<BB *> BasicBlockListType;
|
||||
// BasicBlock iterators...
|
||||
typedef BasicBlockListType::iterator iterator;
|
||||
typedef BasicBlockListType::const_iterator const_iterator;
|
||||
protected:
|
||||
BasicBlockListType BasicBlocks; ///< The basic blocks
|
||||
Function(FunctionType */*ty*/) : procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0),
|
||||
Function(FunctionType *ty) : nStep(eNotDecoded),procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0),
|
||||
hasCase(false),liveAnal(0)
|
||||
{
|
||||
type = new FunctionType;
|
||||
type = ty;
|
||||
if(!ty) // No type was provided, create it
|
||||
type = new FunctionType;
|
||||
callingConv(CConv::UNKNOWN);
|
||||
}
|
||||
|
||||
public:
|
||||
DecompilationStep nStep; // decompilation step number for this function
|
||||
FunctionType * type;
|
||||
CConv * m_call_conv;
|
||||
uint32_t procEntry; /* label number */
|
||||
std::string name; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
int depth; /* Depth at which we found it - for printing */
|
||||
uint32_t flg; /* Combination of Icode & Proc flags */
|
||||
int16_t cbParam; /* Probable no. of bytes of parameters */
|
||||
STKFRAME args; /* Array of arguments */
|
||||
LOCAL_ID localId; /* Local identifiers */
|
||||
ID retVal; /* Return value - identifier */
|
||||
QString name; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
int depth; /* Depth at which we found it - for printing */
|
||||
uint32_t flg; /* Combination of Icode & Proc flags */
|
||||
int16_t cbParam; /* Probable no. of bytes of parameters */
|
||||
STKFRAME args; /* Array of arguments */
|
||||
LOCAL_ID localId; /* Local identifiers */
|
||||
|
||||
/* Icodes and control flow graph */
|
||||
CIcodeRec Icode; /* Object with ICODE records */
|
||||
@@ -147,26 +170,31 @@ public:
|
||||
/* For interprocedural live analysis */
|
||||
LivenessSet liveIn; /* Registers used before defined */
|
||||
LivenessSet liveOut; /* Registers that may be used in successors */
|
||||
bool liveAnal; /* Procedure has been analysed already */
|
||||
bool liveAnal; /* Procedure has been analysed already */
|
||||
|
||||
virtual ~Function() {
|
||||
delete type;
|
||||
}
|
||||
public:
|
||||
static Function *Create(FunctionType *ty=0,int /*Linkage*/=0,const std::string &nm="",void */*module*/=0)
|
||||
static PtrFunction Create(FunctionType *ty=0,int /*Linkage*/=0,const QString &nm="",void */*module*/=0)
|
||||
{
|
||||
Function *r=new Function(ty);
|
||||
PtrFunction r(new Function(ty));
|
||||
r->name = nm;
|
||||
return r;
|
||||
}
|
||||
hlType getReturnType() const {
|
||||
return getFunctionType()->getReturnType();
|
||||
}
|
||||
FunctionType *getFunctionType() const {
|
||||
return type;
|
||||
}
|
||||
CConv *callingConv() const { return m_call_conv;}
|
||||
void callingConv(CConv::Type v);
|
||||
CConv *callingConv() const { return type->m_call_conv;}
|
||||
void callingConv(CConv::CC_Type v);
|
||||
|
||||
// bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
|
||||
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
|
||||
void markDoNotDecompile() { flg |= PROC_ISLIB; }
|
||||
bool doNotDecompile() const { return isLibrary(); }
|
||||
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
|
||||
void compoundCond();
|
||||
void writeProcComments();
|
||||
@@ -180,19 +208,17 @@ public:
|
||||
void createCFG();
|
||||
void markImpure();
|
||||
void findImmedDom();
|
||||
void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void process_operands(ICODE &pIcode, STATE *pstate);
|
||||
bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
||||
bool process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void freeCFG();
|
||||
void codeGen(std::ostream &fs);
|
||||
void codeGen(QIODevice & fs);
|
||||
void mergeFallThrough(BB *pBB);
|
||||
void structIfs();
|
||||
void structLoops(derSeq *derivedG);
|
||||
void buildCFG(Disassembler &ds);
|
||||
void controlFlowAnalysis();
|
||||
void newRegArg(iICODE picode, iICODE ticode);
|
||||
void writeProcComments(std::ostream &ostr);
|
||||
void writeProcComments(QTextStream & ostr);
|
||||
void toStructuredText(IStructuredTextTarget *out,int level);
|
||||
|
||||
void displayCFG();
|
||||
void displayStats();
|
||||
@@ -200,13 +226,12 @@ public:
|
||||
|
||||
void preprocessReturnDU(LivenessSet &_liveOut);
|
||||
Expr * adjustActArgType(Expr *_exp, hlType forType);
|
||||
std::string writeCall(Function *tproc, STKFRAME &args, int *numLoc);
|
||||
QString writeCall(Function *tproc, STKFRAME &args, int *numLoc);
|
||||
void processDosInt(STATE *pstate, PROG &prog, bool done);
|
||||
ICODE *translate_DIV(LLInst *ll, ICODE &_Icode);
|
||||
ICODE *translate_XCHG(LLInst *ll, ICODE &_Icode);
|
||||
|
||||
void switchState(DecompilationStep s);
|
||||
protected:
|
||||
void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table);
|
||||
bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
bool removeInEdge_Flag_and_ProcessLatch(BB *pbb, BB *a, BB *b);
|
||||
bool Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB);
|
||||
bool Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB);
|
||||
@@ -233,26 +258,8 @@ protected:
|
||||
void genLiveKtes();
|
||||
bool findDerivedSeq(derSeq &derivedGi);
|
||||
bool nextOrderGraph(derSeq &derivedGi);
|
||||
void addOutEdgesForConditionalJump(BB *pBB, int next_ip, LLInst *ll);
|
||||
};
|
||||
namespace llvm {
|
||||
template<> struct ilist_traits<typename ::Function>
|
||||
: public ilist_default_traits<typename ::Function> {
|
||||
|
||||
// createSentinel is used to get hold of the node that marks the end of the
|
||||
// list... (same trick used here as in ilist_traits<Instruction>)
|
||||
typename ::Function *createSentinel() const {
|
||||
return static_cast<typename ::Function*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(typename ::Function*) {}
|
||||
|
||||
typename ::Function *provideInitialHead() const { return createSentinel(); }
|
||||
typename ::Function *ensureHead(::Function*) const { return createSentinel(); }
|
||||
static void noteHead(typename ::Function*, typename ::Function*) {}
|
||||
|
||||
private:
|
||||
mutable ilist_node<typename ::Function> Sentinel;
|
||||
};
|
||||
}
|
||||
typedef llvm::iplist<Function> FunctionListType;
|
||||
typedef std::list<PtrFunction> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef lFunction::iterator ilFunction;
|
||||
|
||||
@@ -10,11 +10,11 @@ struct STKFRAME : public SymbolTableCommon<STKSYM>
|
||||
//std::vector<STKSYM> sym;
|
||||
//STKSYM * sym; /* Symbols */
|
||||
int16_t m_minOff; /* Initial offset in stack frame*/
|
||||
int16_t maxOff; /* Maximum offset in stack frame*/
|
||||
int16_t m_maxOff; /* Maximum offset in stack frame*/
|
||||
int cb; /* Number of bytes in arguments */
|
||||
int numArgs; /* No. of arguments in the table*/
|
||||
void adjustForArgType(size_t numArg_, hlType actType_);
|
||||
STKFRAME() : m_minOff(0),maxOff(0),cb(0),numArgs(0)
|
||||
STKFRAME() : m_minOff(0),m_maxOff(0),cb(0),numArgs(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "Enums.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include "Enums.h"
|
||||
|
||||
static const int operandSize=20;
|
||||
/* The following definitions and types define the Conditional Expression
|
||||
* attributed syntax tree, as defined by the following EBNF:
|
||||
@@ -24,7 +28,7 @@ static const condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER,
|
||||
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
|
||||
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
|
||||
struct AstIdent;
|
||||
struct Function;
|
||||
class Function;
|
||||
struct STKFRAME;
|
||||
struct LOCAL_ID;
|
||||
struct ICODE;
|
||||
@@ -54,7 +58,7 @@ public:
|
||||
/** Recursively deallocates the abstract syntax tree rooted at *exp */
|
||||
virtual ~Expr() {}
|
||||
public:
|
||||
virtual std::string walkCondExpr (Function * pProc, int* numLoc) const=0;
|
||||
virtual QString walkCondExpr (Function * pProc, int* numLoc) const=0;
|
||||
virtual Expr *inverse() const=0; // return new COND_EXPR that is invarse of this
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId)=0;
|
||||
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)=0;
|
||||
@@ -96,10 +100,12 @@ struct UnaryOperator : public Expr
|
||||
}
|
||||
public:
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
virtual std::string walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
virtual QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
virtual hlType expType(Function *pproc) const;
|
||||
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
|
||||
private:
|
||||
QString wrapUnary(Function *pProc, int *numLoc, QChar op) const;
|
||||
};
|
||||
|
||||
struct BinaryOperator : public Expr
|
||||
@@ -120,7 +126,7 @@ struct BinaryOperator : public Expr
|
||||
}
|
||||
~BinaryOperator()
|
||||
{
|
||||
assert(m_lhs!=m_rhs || m_lhs==nullptr);
|
||||
assert(m_lhs!=m_rhs or m_lhs==nullptr);
|
||||
delete m_lhs;
|
||||
delete m_rhs;
|
||||
m_lhs=m_rhs=nullptr;
|
||||
@@ -184,7 +190,7 @@ struct BinaryOperator : public Expr
|
||||
condOp op() const { return m_op;}
|
||||
/* Changes the boolean conditional operator at the root of this expression */
|
||||
void op(condOp o) { m_op=o;}
|
||||
std::string walkCondExpr (Function * pProc, int* numLoc) const;
|
||||
QString walkCondExpr(Function * pProc, int* numLoc) const;
|
||||
public:
|
||||
hlType expType(Function *pproc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
@@ -211,7 +217,7 @@ struct AstIdent : public UnaryOperator
|
||||
virtual int hlTypeSize(Function *pproc) const;
|
||||
virtual hlType expType(Function *pproc) const;
|
||||
virtual Expr * performLongRemoval(eReg regi, LOCAL_ID *locId);
|
||||
virtual std::string walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
virtual QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
|
||||
@@ -228,30 +234,30 @@ struct GlobalVariable : public AstIdent
|
||||
return new GlobalVariable(*this);
|
||||
}
|
||||
GlobalVariable(int16_t segValue, int16_t off);
|
||||
std::string walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
hlType expType(Function *pproc) const;
|
||||
};
|
||||
struct GlobalVariableIdx : public AstIdent
|
||||
{
|
||||
bool valid;
|
||||
int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
|
||||
int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
|
||||
|
||||
virtual Expr *clone() const
|
||||
{
|
||||
return new GlobalVariableIdx(*this);
|
||||
}
|
||||
GlobalVariableIdx(int16_t segValue, int16_t off, uint8_t regi, const LOCAL_ID *locSym);
|
||||
std::string walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
hlType expType(Function *pproc) const;
|
||||
};
|
||||
struct Constant : public AstIdent
|
||||
{
|
||||
struct _kte
|
||||
{ /* for CONSTANT only */
|
||||
uint32_t kte; /* value of the constant */
|
||||
uint8_t size; /* #bytes size constant */
|
||||
{ /* for CONSTANT only */
|
||||
uint32_t kte; /* value of the constant */
|
||||
uint8_t size; /* #bytes size constant */
|
||||
} kte;
|
||||
|
||||
Constant(uint32_t _kte, uint8_t size)
|
||||
@@ -264,13 +270,13 @@ struct Constant : public AstIdent
|
||||
{
|
||||
return new Constant(*this);
|
||||
}
|
||||
std::string walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
hlType expType(Function *pproc) const;
|
||||
};
|
||||
struct FuncNode : public AstIdent
|
||||
{
|
||||
struct _call { /* for FUNCTION only */
|
||||
struct _call { /* for FUNCTION only */
|
||||
Function *proc;
|
||||
STKFRAME *args;
|
||||
} call;
|
||||
@@ -284,15 +290,15 @@ struct FuncNode : public AstIdent
|
||||
{
|
||||
return new FuncNode(*this);
|
||||
}
|
||||
std::string walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
hlType expType(Function *pproc) const;
|
||||
};
|
||||
struct RegisterNode : public AstIdent
|
||||
{
|
||||
const LOCAL_ID *m_syms;
|
||||
regType regiType; /* for REGISTER only */
|
||||
int regiIdx; /* index into localId, REGISTER */
|
||||
regType regiType; /* for REGISTER only */
|
||||
int regiIdx; /* index into localId, REGISTER */
|
||||
|
||||
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
|
||||
@@ -310,7 +316,7 @@ struct RegisterNode : public AstIdent
|
||||
{
|
||||
return new RegisterNode(*this);
|
||||
}
|
||||
std::string walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *) const;
|
||||
hlType expType(Function *pproc) const;
|
||||
bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
struct strTable : std::vector<std::string>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QIODevice>
|
||||
|
||||
struct strTable : std::vector<QString>
|
||||
{
|
||||
/* Returns the next available index into the table */
|
||||
size_t nextIdx() {return size();}
|
||||
@@ -20,9 +22,9 @@ struct bundle
|
||||
{
|
||||
public:
|
||||
void appendCode(const char *format, ...);
|
||||
void appendCode(const std::string &s);
|
||||
void appendCode(const QString &s);
|
||||
void appendDecl(const char *format, ...);
|
||||
void appendDecl(const std::string &);
|
||||
void appendDecl(const QString &);
|
||||
void init()
|
||||
{
|
||||
decl.clear();
|
||||
@@ -34,9 +36,9 @@ public:
|
||||
};
|
||||
|
||||
extern bundle cCode;
|
||||
#define lineSize 360 /* 3 lines in the mean time */
|
||||
#define lineSize 360 /* 3 lines in the mean time */
|
||||
|
||||
//void newBundle (bundle *procCode);
|
||||
void writeBundle (std::ostream &ios, bundle procCode);
|
||||
void writeBundle (QIODevice & ios, bundle procCode);
|
||||
void freeBundle (bundle *procCode);
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
#pragma once
|
||||
//TODO: Remove boolT
|
||||
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include "Enums.h"
|
||||
#include "types.h"
|
||||
@@ -22,11 +22,11 @@
|
||||
#include "BasicBlock.h"
|
||||
class Project;
|
||||
/* CALL GRAPH NODE */
|
||||
extern bundle cCode; /* Output C procedure's declaration and code */
|
||||
extern bundle cCode; /* Output C procedure's declaration and code */
|
||||
|
||||
/**** Global variables ****/
|
||||
|
||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
extern QString asm1_name, asm2_name; /* Assembler output filenames */
|
||||
|
||||
typedef struct { /* Command line option flags */
|
||||
unsigned verbose : 1;
|
||||
@@ -37,7 +37,8 @@ typedef struct { /* Command line option flags */
|
||||
unsigned Stats : 1;
|
||||
unsigned Interact : 1; /* Interactive mode */
|
||||
unsigned Calls : 1; /* Follow register indirect calls */
|
||||
char filename[80]; /* The input filename */
|
||||
QString filename; /* The input filename */
|
||||
uint32_t CustomEntryPoint;
|
||||
} OPTION;
|
||||
|
||||
extern OPTION option; /* Command line options */
|
||||
@@ -58,53 +59,41 @@ enum eAreaType
|
||||
/* Intermediate instructions statistics */
|
||||
struct STATS
|
||||
{
|
||||
int numBBbef; /* number of basic blocks initially */
|
||||
int numBBaft; /* number of basic blocks at the end */
|
||||
int nOrder; /* n-th order */
|
||||
int numLLIcode; /* number of low-level Icode instructions */
|
||||
int numHLIcode; /* number of high-level Icode instructions */
|
||||
int totalLL; /* total number of low-level Icode insts */
|
||||
int totalHL; /* total number of high-level Icod insts */
|
||||
int numBBbef; /* number of basic blocks initially */
|
||||
int numBBaft; /* number of basic blocks at the end */
|
||||
int nOrder; /* n-th order */
|
||||
int numLLIcode; /* number of low-level Icode instructions */
|
||||
int numHLIcode; /* number of high-level Icode instructions */
|
||||
int totalLL; /* total number of low-level Icode insts */
|
||||
int totalHL; /* total number of high-level Icod insts */
|
||||
};
|
||||
|
||||
extern STATS stats; /* Icode statistics */
|
||||
|
||||
|
||||
/**** Global function prototypes ****/
|
||||
class DccFrontend
|
||||
{
|
||||
void LoadImage(Project &proj);
|
||||
void parse(Project &proj);
|
||||
std::string m_fname;
|
||||
public:
|
||||
DccFrontend(const std::string &fname) : m_fname(fname)
|
||||
{
|
||||
}
|
||||
bool FrontEnd(); /* frontend.c */
|
||||
};
|
||||
|
||||
void udm(void); /* udm.c */
|
||||
void freeCFG(BB * cfg); /* graph.c */
|
||||
BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */
|
||||
void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */
|
||||
void BackEnd(CALL_GRAPH *); /* backend.c */
|
||||
extern char *cChar(uint8_t c); /* backend.c */
|
||||
eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */
|
||||
void parse (CALL_GRAPH * *); /* parser.c */
|
||||
|
||||
extern int strSize (const uint8_t *, char); /* parser.c */
|
||||
//void disassem(int pass, Function * pProc); /* disassem.c */
|
||||
void interactDis(Function *, int initIC); /* disassem.c */
|
||||
void interactDis(const PtrFunction &, int initIC); /* disassem.c */
|
||||
bool JmpInst(llIcode opcode); /* idioms.c */
|
||||
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */
|
||||
|
||||
void SetupLibCheck(void); /* chklib.c */
|
||||
bool SetupLibCheck(QString pattern_file_id); /* chklib.c */
|
||||
void CleanupLibCheck(void); /* chklib.c */
|
||||
bool LibCheck(Function &p); /* chklib.c */
|
||||
|
||||
|
||||
/* Exported functions from hlicode.c */
|
||||
const char *writeJcond(const HLTYPE &, Function *, int *);
|
||||
const char *writeJcondInv (HLTYPE, Function *, int *);
|
||||
QString writeJcond(const HLTYPE &, Function *, int *);
|
||||
QString writeJcondInv(HLTYPE, Function *, int *);
|
||||
|
||||
|
||||
/* Exported funcions from locident.c */
|
||||
|
||||
14
include/dcc_interface.h
Normal file
14
include/dcc_interface.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "Procedure.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
class IStructuredTextTarget;
|
||||
|
||||
struct IDcc {
|
||||
static IDcc *get();
|
||||
virtual bool load(QString name)=0; // load and preprocess -> find entry point
|
||||
virtual QDir installDir()=0;
|
||||
virtual QDir dataDir(QString kind)=0;
|
||||
};
|
||||
@@ -5,47 +5,54 @@
|
||||
***************************************************************************
|
||||
*/
|
||||
#pragma once
|
||||
#include "bundle.h"
|
||||
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include "bundle.h"
|
||||
#include <QString>
|
||||
#include <QTextStream>
|
||||
|
||||
struct LLInst;
|
||||
class Function;
|
||||
typedef std::shared_ptr<Function> PtrFunction;
|
||||
|
||||
struct Disassembler
|
||||
{
|
||||
protected:
|
||||
int pass;
|
||||
int g_lab;
|
||||
//bundle &cCode;
|
||||
std::ofstream m_fp;
|
||||
int pass=0;
|
||||
int g_lab=0;
|
||||
QIODevice *m_disassembly_target=nullptr;
|
||||
QTextStream m_fp;
|
||||
std::vector<std::string> m_decls;
|
||||
std::vector<std::string> m_code;
|
||||
|
||||
public:
|
||||
Disassembler(int _p) : pass(_p)
|
||||
{
|
||||
g_lab=0;
|
||||
}
|
||||
public:
|
||||
void disassem(Function *ppProc);
|
||||
void disassem(Function *ppProc, int i);
|
||||
|
||||
void disassem(PtrFunction ppProc);
|
||||
void disassem(PtrFunction ppProc, int i);
|
||||
void dis1Line(LLInst &inst, int loc_ip, int pass);
|
||||
};
|
||||
/* Definitions for extended keys (first key is zero) */
|
||||
|
||||
#define EXT 0x100 /* "Extended" flag */
|
||||
#define EXT 0x100 /* "Extended" flag */
|
||||
|
||||
#ifdef __UNIX__
|
||||
#define KEY_DOWN EXT+'B'
|
||||
#define KEY_LEFT EXT+'D'
|
||||
#define KEY_UP EXT+'A'
|
||||
#define KEY_RIGHT EXT+'C'
|
||||
#define KEY_NPAGE EXT+'J' /* Enter correct value! */
|
||||
#define KEY_PPAGE EXT+'K' /* Another guess! */
|
||||
#define KEY_DOWN EXT+'B'
|
||||
#define KEY_LEFT EXT+'D'
|
||||
#define KEY_UP EXT+'A'
|
||||
#define KEY_RIGHT EXT+'C'
|
||||
#define KEY_NPAGE EXT+'J' /* Enter correct value! */
|
||||
#define KEY_PPAGE EXT+'K' /* Another guess! */
|
||||
#endif
|
||||
|
||||
/* "Attributes" */
|
||||
#define A_NORMAL 'N' /* For Dos/Unix */
|
||||
#define A_REVERSE 'I'
|
||||
#define A_BOLD 'B'
|
||||
#define A_NORMAL 'N' /* For Dos/Unix */
|
||||
#define A_REVERSE 'I'
|
||||
#define A_BOLD 'B'
|
||||
|
||||
#define LINES 24
|
||||
#define COLS 80
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
|
||||
struct Function;
|
||||
class Function;
|
||||
/* Types of basic block nodes */
|
||||
/* Real basic blocks: type defined according to their out-edges */
|
||||
enum eBBKind
|
||||
@@ -51,16 +51,16 @@ enum eNodeHeaderType
|
||||
|
||||
/* Uninitialized values for certain fields */
|
||||
#define NO_NODE MAX /* node has no associated node */
|
||||
#define NO_DOM MAX /* node has no dominator */
|
||||
#define UN_INIT MAX /* uninitialized variable */
|
||||
#define NO_DOM MAX /* node has no dominator */
|
||||
#define UN_INIT MAX /* uninitialized variable */
|
||||
|
||||
#define THEN 0 /* then edge */
|
||||
#define ELSE 1 /* else edge */
|
||||
|
||||
/* Basic Block (BB) flags */
|
||||
|
||||
#define INVALID_BB 0x0001 /* BB is not valid any more */
|
||||
#define IS_LATCH_NODE 0x0002 /* BB is the latching node of a loop */
|
||||
#define INVALID_BB 0x0001 /* BB is not valid any more */
|
||||
#define IS_LATCH_NODE 0x0002 /* BB is the latching node of a loop */
|
||||
|
||||
struct BB;
|
||||
/* Interval structure */
|
||||
|
||||
406
include/icode.h
406
include/icode.h
@@ -3,6 +3,16 @@
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include "msvc_fixes.h"
|
||||
#include "BinaryImage.h"
|
||||
#include "libdis.h"
|
||||
#include "Enums.h"
|
||||
#include "state.h" // State depends on INDEXBASE, but later need STATE
|
||||
#include "CallConvention.h"
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
@@ -10,21 +20,12 @@
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <llvm/MC/MCInst.h>
|
||||
#include <llvm/IR/Instruction.h>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include "libdis.h"
|
||||
#include "Enums.h"
|
||||
#include "state.h" // State depends on INDEXBASE, but later need STATE
|
||||
#include "CallConvention.h"
|
||||
|
||||
//enum condId;
|
||||
|
||||
struct LOCAL_ID;
|
||||
struct BB;
|
||||
struct Function;
|
||||
class Function;
|
||||
struct STKFRAME;
|
||||
class CIcodeRec;
|
||||
struct ICODE;
|
||||
@@ -58,12 +59,7 @@ public:
|
||||
}
|
||||
friend void swap(LivenessSet& first, LivenessSet& second) // nothrow
|
||||
{
|
||||
// enable ADL (not necessary in our case, but good practice)
|
||||
using std::swap;
|
||||
|
||||
// by swapping the members of two classes,
|
||||
// the two classes are effectively swapped
|
||||
swap(first.registers, second.registers);
|
||||
std::swap(first.registers, second.registers);
|
||||
}
|
||||
LivenessSet &operator|=(const LivenessSet &other)
|
||||
{
|
||||
@@ -132,7 +128,7 @@ struct DU
|
||||
};
|
||||
|
||||
/* Definition-use chain for level 1 (within a basic block) */
|
||||
#define MAX_REGS_DEF 4 /* 2 regs def'd for long-reg vars */
|
||||
#define MAX_REGS_DEF 4 /* 2 regs def'd for long-reg vars */
|
||||
|
||||
|
||||
struct Expr;
|
||||
@@ -141,8 +137,8 @@ struct UnaryOperator;
|
||||
struct HlTypeSupport
|
||||
{
|
||||
//hlIcode opcode; /* hlIcode opcode */
|
||||
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
|
||||
virtual std::string writeOut(Function *pProc, int *numLoc) const=0;
|
||||
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
|
||||
virtual QString writeOut(Function *pProc, int *numLoc) const=0;
|
||||
protected:
|
||||
Expr * performLongRemoval (eReg regi, LOCAL_ID *locId, Expr *tree);
|
||||
};
|
||||
@@ -157,12 +153,12 @@ struct CallType : public HlTypeSupport
|
||||
void placeStkArg(Expr *exp, int pos);
|
||||
virtual Expr * toAst();
|
||||
public:
|
||||
bool removeRegFromLong(eReg /*regi*/, LOCAL_ID */*locId*/)
|
||||
bool removeRegFromLong(eReg /*regi*/, LOCAL_ID * /*locId*/)
|
||||
{
|
||||
printf("CallType : removeRegFromLong not supproted");
|
||||
printf("CallType : removeRegFromLong not supproted\n");
|
||||
return false;
|
||||
}
|
||||
std::string writeOut(Function *pProc, int *numLoc) const;
|
||||
QString writeOut(Function *pProc, int *numLoc) const;
|
||||
};
|
||||
struct AssignType : public HlTypeSupport
|
||||
{
|
||||
@@ -170,12 +166,12 @@ struct AssignType : public HlTypeSupport
|
||||
protected:
|
||||
public:
|
||||
Expr *m_lhs;
|
||||
Expr *rhs;
|
||||
Expr *m_rhs;
|
||||
AssignType() {}
|
||||
Expr *lhs() const {return m_lhs;}
|
||||
void lhs(Expr *l);
|
||||
bool removeRegFromLong(eReg regi, LOCAL_ID *locId);
|
||||
std::string writeOut(Function *pProc, int *numLoc) const;
|
||||
QString writeOut(Function *pProc, int *numLoc) const;
|
||||
};
|
||||
struct ExpType : public HlTypeSupport
|
||||
{
|
||||
@@ -187,7 +183,7 @@ struct ExpType : public HlTypeSupport
|
||||
v=performLongRemoval(regi,locId,v);
|
||||
return true;
|
||||
}
|
||||
std::string writeOut(Function *pProc, int *numLoc) const;
|
||||
QString writeOut(Function *pProc, int *numLoc) const;
|
||||
};
|
||||
|
||||
struct HLTYPE
|
||||
@@ -241,26 +237,26 @@ public:
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
std::string write1HlIcode(Function *pProc, int *numLoc) const;
|
||||
QString write1HlIcode(Function *pProc, int *numLoc) const;
|
||||
void setAsgn(Expr *lhs, Expr *rhs);
|
||||
} ;
|
||||
/* LOW_LEVEL icode operand record */
|
||||
struct LLOperand
|
||||
{
|
||||
eReg seg; /* CS, DS, ES, SS */
|
||||
eReg segOver; /* CS, DS, ES, SS if segment override */
|
||||
int16_t segValue; /* Value of segment seg during analysis */
|
||||
eReg regi; /* 0 < regs < INDEXBASE <= index modes */
|
||||
int16_t off; /* memory address offset */
|
||||
uint32_t opz; /* idx of immed src op */
|
||||
bool immed;
|
||||
bool is_offset; // set by jumps
|
||||
bool is_compound;
|
||||
size_t width;
|
||||
//union {/* Source operand if (flg & I) */
|
||||
struct { /* Call & # actual arg bytes */
|
||||
eReg seg; /* CS, DS, ES, SS */
|
||||
eReg segOver; /* CS, DS, ES, SS if segment override */
|
||||
int16_t segValue; /* Value of segment seg during analysis */
|
||||
eReg regi; /* 0 < regs < INDEXBASE <= index modes */
|
||||
int16_t off; /* memory address offset */
|
||||
uint32_t opz; /* idx of immed src op */
|
||||
bool immed;
|
||||
bool is_offset; // set by jumps
|
||||
bool is_compound;
|
||||
size_t width;
|
||||
/* Source operand if (flg & I) */
|
||||
struct { /* Call & # actual arg bytes */
|
||||
Function *proc; /* pointer to target proc (for CALL(F))*/
|
||||
int cb; /* # actual arg bytes */
|
||||
int cb; /* # actual arg bytes */
|
||||
} proc;
|
||||
LLOperand() : seg(rUNDEF),segOver(rUNDEF),segValue(0),regi(rUNDEF),off(0),
|
||||
opz(0),immed(0),is_offset(false),is_compound(0),width(0)
|
||||
@@ -275,12 +271,12 @@ struct LLOperand
|
||||
}
|
||||
bool operator==(const LLOperand &with) const
|
||||
{
|
||||
return (seg==with.seg) &&
|
||||
(segOver==with.segOver) &&
|
||||
(segValue==with.segValue) &&
|
||||
(regi == with.regi) &&
|
||||
(off == with.off) &&
|
||||
(opz==with.opz) &&
|
||||
return (seg==with.seg) and
|
||||
(segOver==with.segOver) and
|
||||
(segValue==with.segValue) and
|
||||
(regi == with.regi) and
|
||||
(off == with.off) and
|
||||
(opz==with.opz) and
|
||||
(proc.proc==with.proc.proc);
|
||||
}
|
||||
int64_t getImm2() const {return opz;}
|
||||
@@ -304,140 +300,139 @@ struct LLOperand
|
||||
Op.regi = (eReg)Val;
|
||||
return Op;
|
||||
}
|
||||
bool isSet()
|
||||
bool isSet() const
|
||||
{
|
||||
return not (*this == LLOperand());
|
||||
}
|
||||
void addProcInformation(int param_count, CConv::Type call_conv);
|
||||
void addProcInformation(int param_count, CConv::CC_Type call_conv);
|
||||
bool isImmediate() const { return immed;}
|
||||
void setImmediate(bool x) { immed=x;}
|
||||
bool compound() const {return is_compound;} // dx:ax pair
|
||||
size_t byteWidth() const { assert(width<=4); return width;}
|
||||
};
|
||||
struct LLInst : public llvm::MCInst //: public llvm::ilist_node<LLInst>
|
||||
struct LLInst
|
||||
{
|
||||
protected:
|
||||
uint32_t flg; /* icode flags */
|
||||
LLOperand m_src; /* source operand */
|
||||
uint32_t m_opcode; // Low level opcode identifier
|
||||
uint32_t flg; /* icode flags */
|
||||
LLOperand m_src; /* source operand */
|
||||
public:
|
||||
int codeIdx; /* Index into cCode.code */
|
||||
uint8_t numBytes; /* Number of bytes this instr */
|
||||
uint32_t label; /* offset in image (20-bit adr) */
|
||||
LLOperand m_dst; /* destination operand */
|
||||
DU flagDU; /* def/use of flags */
|
||||
int caseEntry;
|
||||
int codeIdx; /* Index into cCode.code */
|
||||
uint8_t numBytes; /* Number of bytes this instr */
|
||||
uint32_t label; /* offset in image (20-bit adr) */
|
||||
LLOperand m_dst; /* destination operand */
|
||||
DU flagDU; /* def/use of flags */
|
||||
int caseEntry;
|
||||
std::vector<uint32_t> caseTbl2;
|
||||
int hllLabNum; /* label # for hll codegen */
|
||||
bool conditionalJump()
|
||||
{
|
||||
return (getOpcode() >= iJB) && (getOpcode() < iJCXZ);
|
||||
}
|
||||
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
|
||||
void setFlags(uint32_t flag) {flg |= flag;}
|
||||
void clrFlags(uint32_t flag)
|
||||
{
|
||||
if(getOpcode()==iMOD)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
flg &= ~flag;
|
||||
}
|
||||
uint32_t getFlag() const {return flg;}
|
||||
uint32_t GetLlLabel() const { return label;}
|
||||
int hllLabNum; /* label # for hll codegen */
|
||||
|
||||
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
|
||||
uint32_t getOpcode() const { return m_opcode;}
|
||||
void setOpcode(uint32_t op) { m_opcode=op; }
|
||||
bool conditionalJump()
|
||||
{
|
||||
return (getOpcode() >= iJB) and (getOpcode() < iJCXZ);
|
||||
}
|
||||
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
|
||||
void setFlags(uint32_t flag) {flg |= flag;}
|
||||
void clrFlags(uint32_t flag);
|
||||
uint32_t getFlag() const {return flg;}
|
||||
uint32_t GetLlLabel() const { return label;}
|
||||
|
||||
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
|
||||
|
||||
bool match(llIcode op)
|
||||
{
|
||||
return (getOpcode()==op);
|
||||
}
|
||||
bool matchWithRegDst(llIcode op)
|
||||
{
|
||||
return (getOpcode()==op) and m_dst.isReg();
|
||||
}
|
||||
bool match(llIcode op,eReg dest)
|
||||
{
|
||||
return (getOpcode()==op)&&m_dst.regi==dest;
|
||||
}
|
||||
bool match(llIcode op,eReg dest,uint32_t flgs)
|
||||
{
|
||||
return (getOpcode()==op) and (m_dst.regi==dest) and testFlags(flgs);
|
||||
}
|
||||
bool match(llIcode op,eReg dest,eReg src_reg)
|
||||
{
|
||||
return (getOpcode()==op)&&(m_dst.regi==dest)&&(m_src.regi==src_reg);
|
||||
}
|
||||
bool match(eReg dest,eReg src_reg)
|
||||
{
|
||||
return (m_dst.regi==dest)&&(m_src.regi==src_reg);
|
||||
}
|
||||
bool match(eReg dest)
|
||||
{
|
||||
return (m_dst.regi==dest);
|
||||
}
|
||||
bool match(llIcode op,uint32_t flgs)
|
||||
{
|
||||
return (getOpcode()==op) and testFlags(flgs);
|
||||
}
|
||||
void set(llIcode op,uint32_t flags)
|
||||
{
|
||||
setOpcode(op);
|
||||
flg =flags;
|
||||
}
|
||||
void set(llIcode op,uint32_t flags,eReg dst_reg)
|
||||
{
|
||||
setOpcode(op);
|
||||
m_dst = LLOperand::CreateReg2(dst_reg);
|
||||
flg =flags;
|
||||
}
|
||||
void set(llIcode op,uint32_t flags,eReg dst_reg,const LLOperand &src_op)
|
||||
{
|
||||
setOpcode(op);
|
||||
m_dst = LLOperand::CreateReg2(dst_reg);
|
||||
m_src = src_op;
|
||||
flg =flags;
|
||||
}
|
||||
void emitGotoLabel(int indLevel);
|
||||
void findJumpTargets(CIcodeRec &_pc);
|
||||
void writeIntComment(std::ostringstream &s);
|
||||
void dis1Line(int loc_ip, int pass);
|
||||
std::ostringstream &strSrc(std::ostringstream &os,bool skip_comma=false);
|
||||
bool match(llIcode op)
|
||||
{
|
||||
return (getOpcode()==op);
|
||||
}
|
||||
bool matchWithRegDst(llIcode op)
|
||||
{
|
||||
return match(op) and m_dst.isReg();
|
||||
}
|
||||
bool match(llIcode op,eReg dest)
|
||||
{
|
||||
return match(op) and match(dest);
|
||||
}
|
||||
bool match(llIcode op,eReg dest,uint32_t flgs)
|
||||
{
|
||||
return match(op) and match(dest) and testFlags(flgs);
|
||||
}
|
||||
bool match(llIcode op,eReg dest,eReg src_reg)
|
||||
{
|
||||
return match(op) and match(dest) and (m_src.regi==src_reg);
|
||||
}
|
||||
bool match(eReg dest,eReg src_reg)
|
||||
{
|
||||
return match(dest) and (m_src.regi==src_reg);
|
||||
}
|
||||
bool matchAny(std::initializer_list<llIcode> ops) {
|
||||
for(llIcode op : ops) {
|
||||
if(match(op))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool match(eReg dest)
|
||||
{
|
||||
return (m_dst.regi==dest);
|
||||
}
|
||||
bool match(llIcode op,uint32_t flgs)
|
||||
{
|
||||
return match(op) and testFlags(flgs);
|
||||
}
|
||||
void set(llIcode op,uint32_t flags)
|
||||
{
|
||||
setOpcode(op);
|
||||
flg =flags;
|
||||
}
|
||||
void set(llIcode op,uint32_t flags,eReg dst_reg)
|
||||
{
|
||||
setOpcode(op);
|
||||
m_dst = LLOperand::CreateReg2(dst_reg);
|
||||
flg =flags;
|
||||
}
|
||||
void set(llIcode op,uint32_t flags,eReg dst_reg,const LLOperand &src_op)
|
||||
{
|
||||
setOpcode(op);
|
||||
m_dst = LLOperand::CreateReg2(dst_reg);
|
||||
m_src = src_op;
|
||||
flg =flags;
|
||||
}
|
||||
void emitGotoLabel(int indLevel);
|
||||
void findJumpTargets(CIcodeRec &_pc);
|
||||
void writeIntComment(QTextStream & s);
|
||||
void dis1Line(int loc_ip, int pass);
|
||||
|
||||
void flops(std::ostringstream &out);
|
||||
bool isJmpInst();
|
||||
HLTYPE createCall();
|
||||
LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container)
|
||||
{
|
||||
setOpcode(0);
|
||||
}
|
||||
const LLOperand &src() const {return m_src;}
|
||||
LLOperand &src() {return m_src;}
|
||||
void replaceSrc(const LLOperand &with)
|
||||
{
|
||||
m_src = with;
|
||||
}
|
||||
void replaceSrc(eReg r)
|
||||
{
|
||||
m_src = LLOperand::CreateReg2(r);
|
||||
}
|
||||
void replaceSrc(int64_t r)
|
||||
{
|
||||
m_src = LLOperand::CreateImm2(r);
|
||||
}
|
||||
void replaceDst(const LLOperand &with)
|
||||
{
|
||||
m_dst = with;
|
||||
}
|
||||
// void replaceDst(eReg r)
|
||||
// {
|
||||
// dst = LLOperand::CreateReg2(r);
|
||||
// }
|
||||
ICODE *m_link;
|
||||
condId idType(opLoc sd) const;
|
||||
void flops(QTextStream & out);
|
||||
bool isJmpInst();
|
||||
HLTYPE createCall();
|
||||
LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container)
|
||||
{
|
||||
setOpcode(0);
|
||||
}
|
||||
const LLOperand & dst() const { return m_dst; }
|
||||
LLOperand & dst() { return m_dst; }
|
||||
const LLOperand & src() const { return m_src; }
|
||||
LLOperand & src() { return m_src; }
|
||||
void replaceSrc(const LLOperand &with) { m_src = with; }
|
||||
void replaceSrc(eReg r) { m_src = LLOperand::CreateReg2(r); }
|
||||
void replaceSrc(int64_t r) { m_src = LLOperand::CreateImm2(r); }
|
||||
void replaceDst(const LLOperand &with) { m_dst = with; }
|
||||
bool srcIsImmed() const { return (flg & I)!=0; }
|
||||
condId idType(opLoc sd) const;
|
||||
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &m_dst; }
|
||||
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &m_dst; }
|
||||
|
||||
ICODE * m_link;
|
||||
};
|
||||
struct ADDRESS {
|
||||
|
||||
};
|
||||
struct BinaryArea {
|
||||
ADDRESS start;
|
||||
ADDRESS fin;
|
||||
};
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
#include <boost/icl/interval_map.hpp>
|
||||
|
||||
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
|
||||
struct ICODE
|
||||
@@ -445,7 +440,7 @@ struct ICODE
|
||||
// use llvm names at least
|
||||
typedef BB MachineBasicBlock;
|
||||
protected:
|
||||
LLInst m_ll;
|
||||
LLInst *m_ll;
|
||||
HLTYPE m_hl;
|
||||
MachineBasicBlock * Parent; /* BB to which this icode belongs */
|
||||
bool invalid; /* Has no HIGH_LEVEL equivalent */
|
||||
@@ -460,17 +455,17 @@ public:
|
||||
template<int TYPE>
|
||||
struct TypeFilter
|
||||
{
|
||||
bool operator()(ICODE *ic) {return ic->type==HIGH_LEVEL;}
|
||||
bool operator()(ICODE &ic) {return ic.type==HIGH_LEVEL;}
|
||||
bool operator()(ICODE *ic) {return ic->type==TYPE;}
|
||||
bool operator()(ICODE &ic) {return ic.type==TYPE;}
|
||||
};
|
||||
template<int TYPE>
|
||||
struct TypeAndValidFilter
|
||||
{
|
||||
bool operator()(ICODE *ic) {return (ic->type==HIGH_LEVEL)&&(ic->valid());}
|
||||
bool operator()(ICODE &ic) {return (ic.type==HIGH_LEVEL)&&ic.valid();}
|
||||
bool operator()(ICODE *ic) {return (ic->type==TYPE) and (ic->valid());}
|
||||
bool operator()(ICODE &ic) {return (ic.type==TYPE) and ic.valid();}
|
||||
};
|
||||
static TypeFilter<HIGH_LEVEL> select_high_level;
|
||||
static TypeAndValidFilter<HIGH_LEVEL> select_valid_high_level;
|
||||
static TypeFilter<HIGH_LEVEL_ICODE> select_high_level;
|
||||
static TypeAndValidFilter<HIGH_LEVEL_ICODE> select_valid_high_level;
|
||||
/* Def/Use of registers and stack variables */
|
||||
struct DU_ICODE
|
||||
{
|
||||
@@ -506,7 +501,7 @@ public:
|
||||
if(iter==uses.end())
|
||||
return;
|
||||
uses.erase(iter);
|
||||
assert("Same user more then once!" && uses.end()==std::find(uses.begin(),uses.end(),us));
|
||||
assert("Same user more then once!" and uses.end()==std::find(uses.begin(),uses.end(),us));
|
||||
}
|
||||
|
||||
};
|
||||
@@ -544,12 +539,12 @@ public:
|
||||
}
|
||||
};
|
||||
icodeType type; /* Icode type */
|
||||
DU_ICODE du; /* Def/use regs/vars */
|
||||
DU1 du1; /* du chain 1 */
|
||||
DU_ICODE du; /* Def/use regs/vars */
|
||||
DU1 du1; /* du chain 1 */
|
||||
int loc_ip; // used by CICodeRec to number ICODEs
|
||||
|
||||
LLInst * ll() { return &m_ll;}
|
||||
const LLInst * ll() const { return &m_ll;}
|
||||
LLInst * ll() { return m_ll;}
|
||||
const LLInst * ll() const { return m_ll;}
|
||||
|
||||
HLTYPE * hlU() {
|
||||
// assert(type==HIGH_LEVEL);
|
||||
@@ -572,7 +567,7 @@ public:
|
||||
// set this icode to be an assign
|
||||
void setAsgn(Expr *lhs, Expr *rhs)
|
||||
{
|
||||
type=HIGH_LEVEL;
|
||||
type=HIGH_LEVEL_ICODE;
|
||||
hlU()->setAsgn(lhs,rhs);
|
||||
}
|
||||
void setUnary(hlIcode op, Expr *_exp);
|
||||
@@ -589,8 +584,46 @@ public:
|
||||
{
|
||||
return hlU()->call.newStkArg(exp,opcode,pproc);
|
||||
}
|
||||
ICODE() : m_ll(this),Parent(0),invalid(false),type(NOT_SCANNED),loc_ip(0)
|
||||
ICODE() :Parent(0),invalid(false),type(NOT_SCANNED_ICODE),loc_ip(0)
|
||||
{
|
||||
m_ll = new LLInst(this);
|
||||
}
|
||||
~ICODE() {
|
||||
delete m_ll;
|
||||
}
|
||||
ICODE(const ICODE &v) {
|
||||
m_ll = new LLInst(*v.m_ll);
|
||||
m_hl = v.m_hl;
|
||||
Parent = v.Parent;
|
||||
insn = v.insn;
|
||||
type = v.type;
|
||||
du = v.du;
|
||||
du1 = v.du1;
|
||||
loc_ip = v.loc_ip;
|
||||
|
||||
}
|
||||
ICODE & operator=(const ICODE &v) {
|
||||
delete m_ll;
|
||||
m_ll = v.m_ll;
|
||||
m_hl = v.m_hl;
|
||||
Parent = v.Parent;
|
||||
insn = v.insn;
|
||||
type = v.type;
|
||||
du = v.du;
|
||||
du1 = v.du1;
|
||||
loc_ip = v.loc_ip;
|
||||
return *this;
|
||||
}
|
||||
ICODE & operator=(ICODE &&v) {
|
||||
std::swap(m_ll,v.m_ll);
|
||||
std::swap(m_hl,v.m_hl);
|
||||
std::swap(Parent , v.Parent);
|
||||
std::swap(insn , v.insn);
|
||||
std::swap(type , v.type);
|
||||
std::swap(du , v.du);
|
||||
std::swap(du1 , v.du1);
|
||||
std::swap(loc_ip , v.loc_ip);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
const MachineBasicBlock* getParent() const { return Parent; }
|
||||
@@ -600,24 +633,23 @@ public:
|
||||
};
|
||||
/** Map n low level instructions to m high level instructions
|
||||
*/
|
||||
struct MappingLLtoML
|
||||
{
|
||||
typedef llvm::iplist<llvm::Instruction> InstListType;
|
||||
typedef boost::iterator_range<iICODE> rSourceRange;
|
||||
typedef boost::iterator_range<InstListType::iterator> rTargetRange;
|
||||
rSourceRange m_low_level;
|
||||
rTargetRange m_middle_level;
|
||||
};
|
||||
//struct MappingLLtoML
|
||||
//{
|
||||
// typedef boost::iterator_range<iICODE> rSourceRange;
|
||||
// typedef boost::iterator_range<InstListType::iterator> rTargetRange;
|
||||
// rSourceRange m_low_level;
|
||||
// rTargetRange m_middle_level;
|
||||
//};
|
||||
// This is the icode array object.
|
||||
class CIcodeRec : public std::list<ICODE>
|
||||
{
|
||||
public:
|
||||
CIcodeRec(); // Constructor
|
||||
CIcodeRec(); // Constructor
|
||||
|
||||
ICODE * addIcode(ICODE *pIcode);
|
||||
void SetInBB(rCODE &rang, BB* pnewBB);
|
||||
bool labelSrch(uint32_t target, uint32_t &pIndex);
|
||||
ICODE * addIcode(const ICODE * pIcode);
|
||||
void SetInBB(rCODE &rang, BB* pnewBB);
|
||||
bool labelSrch(uint32_t target, uint32_t &pIndex);
|
||||
iterator labelSrch(uint32_t target);
|
||||
ICODE * GetIcode(size_t ip);
|
||||
ICODE * GetIcode(size_t ip);
|
||||
bool alreadyDecoded(uint32_t target);
|
||||
};
|
||||
|
||||
@@ -6,14 +6,17 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "msvc_fixes.h"
|
||||
#include "types.h"
|
||||
#include "Enums.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include "types.h"
|
||||
#include "Enums.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
/* Type definition */
|
||||
// this array has to stay in-order of addition i.e. not std::set<iICODE,std::less<iICODE> >
|
||||
@@ -33,32 +36,32 @@ struct IDX_ARRAY : public std::vector<iICODE>
|
||||
|
||||
enum frameType
|
||||
{
|
||||
STK_FRAME, /* For stack vars */
|
||||
REG_FRAME, /* For register variables */
|
||||
GLB_FRAME /* For globals */
|
||||
STK_FRAME, /* For stack vars */
|
||||
REG_FRAME, /* For register variables */
|
||||
GLB_FRAME /* For globals */
|
||||
};
|
||||
|
||||
struct BWGLB_TYPE
|
||||
{
|
||||
int16_t seg; /* segment value */
|
||||
int16_t off; /* offset */
|
||||
eReg regi; /* optional indexed register */
|
||||
int16_t seg; /* segment value */
|
||||
int16_t off; /* offset */
|
||||
eReg regi; /* optional indexed register */
|
||||
} ;
|
||||
|
||||
|
||||
/* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
struct LONG_STKID_TYPE
|
||||
{
|
||||
int offH; /* high offset from BP */
|
||||
int offL; /* low offset from BP */
|
||||
int offH; /* high offset from BP */
|
||||
int offL; /* low offset from BP */
|
||||
LONG_STKID_TYPE(int h,int l) : offH(h),offL(l) {}
|
||||
};
|
||||
/* For TYPE_LONG_(UN)SIGN registers */
|
||||
/* For TYPE_LONG_(UN)SIGN registers */
|
||||
struct LONGID_TYPE
|
||||
{
|
||||
protected:
|
||||
eReg m_h; /* high register */
|
||||
eReg m_l; /* low register */
|
||||
eReg m_h; /* high register */
|
||||
eReg m_l; /* low register */
|
||||
public:
|
||||
void set(eReg highpart,eReg lowpart)
|
||||
{
|
||||
@@ -72,7 +75,7 @@ public:
|
||||
LONGID_TYPE(eReg h,eReg l) : m_h(h),m_l(l) {}
|
||||
};
|
||||
|
||||
struct LONGGLB_TYPE /* For TYPE_LONG_(UN)SIGN globals */
|
||||
struct LONGGLB_TYPE /* For TYPE_LONG_(UN)SIGN globals */
|
||||
{
|
||||
int16_t seg; /* segment value */
|
||||
int16_t offH; /* offset high */
|
||||
@@ -90,7 +93,7 @@ struct LONGGLB_TYPE /* For TYPE_LONG_(UN)SIGN globals */
|
||||
struct ID
|
||||
{
|
||||
protected:
|
||||
LONGID_TYPE m_longId; /* For TYPE_LONG_(UN)SIGN registers */
|
||||
LONGID_TYPE m_longId; /* For TYPE_LONG_(UN)SIGN registers */
|
||||
public:
|
||||
hlType type; /* Probable type */
|
||||
bool illegal; /* Boolean: not a valid field any more */
|
||||
@@ -99,40 +102,38 @@ public:
|
||||
frameType loc; /* Frame location */
|
||||
bool hasMacro; /* Identifier requires a macro */
|
||||
char macro[10]; /* Macro for this identifier */
|
||||
std::string name; /* Identifier's name */
|
||||
QString name; /* Identifier's name */
|
||||
union ID_UNION { /* Different types of identifiers */
|
||||
friend struct ID;
|
||||
protected:
|
||||
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
public:
|
||||
eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */
|
||||
struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */
|
||||
eReg regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */
|
||||
struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */
|
||||
uint8_t regOff; /* register offset (if any) */
|
||||
int off; /* offset from BP */
|
||||
} bwId;
|
||||
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(UN)SIGN globals */
|
||||
int off; /* offset from BP */
|
||||
} bwId;
|
||||
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(UN)SIGN globals */
|
||||
LONGGLB_TYPE longGlb;
|
||||
struct { /* For TYPE_LONG_(UN)SIGN constants */
|
||||
uint32_t h; /* high uint16_t */
|
||||
uint32_t l; /* low uint16_t */
|
||||
struct { /* For TYPE_LONG_(UN)SIGN constants */
|
||||
uint32_t h; /* high uint16_t */
|
||||
uint32_t l; /* low uint16_t */
|
||||
} longKte;
|
||||
ID_UNION() { /*new (&longStkId) LONG_STKID_TYPE();*/}
|
||||
} id;
|
||||
LONGID_TYPE & longId() {assert(isLong() && loc==REG_FRAME); return m_longId;}
|
||||
const LONGID_TYPE & longId() const {assert(isLong() && loc==REG_FRAME); return m_longId;}
|
||||
LONG_STKID_TYPE & longStkId() {assert(isLong() && loc==STK_FRAME); return id.longStkId;}
|
||||
const LONG_STKID_TYPE & longStkId() const {assert(isLong() && loc==STK_FRAME); return id.longStkId;}
|
||||
|
||||
LONGID_TYPE & longId() {assert(isLong() and loc==REG_FRAME); return m_longId;}
|
||||
const LONGID_TYPE & longId() const {assert(isLong() and loc==REG_FRAME); return m_longId;}
|
||||
LONG_STKID_TYPE & longStkId() {assert(isLong() and loc==STK_FRAME); return id.longStkId;}
|
||||
const LONG_STKID_TYPE & longStkId() const {assert(isLong() and loc==STK_FRAME); return id.longStkId;}
|
||||
ID();
|
||||
ID(hlType t, frameType f);
|
||||
ID(hlType t, const LONGID_TYPE &s);
|
||||
ID(hlType t, const LONG_STKID_TYPE &s);
|
||||
ID(hlType t, const LONGGLB_TYPE &s);
|
||||
bool isSigned() const { return (type==TYPE_BYTE_SIGN)||(type==TYPE_WORD_SIGN)||(type==TYPE_LONG_SIGN);}
|
||||
bool isSigned() const { return (type==TYPE_BYTE_SIGN) or (type==TYPE_WORD_SIGN) or (type==TYPE_LONG_SIGN);}
|
||||
uint16_t typeBitsize() const
|
||||
{
|
||||
return TypeContainer::typeSize(type)*8;
|
||||
}
|
||||
bool isLong() const { return (type==TYPE_LONG_UNSIGN)||(type==TYPE_LONG_SIGN); }
|
||||
bool isLong() const { return (type==TYPE_LONG_UNSIGN) or (type==TYPE_LONG_SIGN); }
|
||||
void setLocalName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
@@ -164,7 +165,7 @@ public:
|
||||
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
|
||||
void newIdent(hlType t, frameType f);
|
||||
void flagByteWordId(int off);
|
||||
void propLongId(uint8_t regL, uint8_t regH, const char *name);
|
||||
void propLongId(uint8_t regL, uint8_t regH, const QString & name);
|
||||
size_t csym() const {return id_arr.size();}
|
||||
void newRegArg(iICODE picode, iICODE ticode) const;
|
||||
void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong) const;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
|
||||
class QTextStream;
|
||||
|
||||
struct LivenessSet;
|
||||
/* Machine registers */
|
||||
enum eReg
|
||||
@@ -60,13 +62,13 @@ class Machine_X86 : public SourceMachine
|
||||
public:
|
||||
Machine_X86();
|
||||
virtual ~Machine_X86() {}
|
||||
static const std::string ®Name(eReg r);
|
||||
static const std::string &opcodeName(unsigned r);
|
||||
static const std::string &floatOpName(unsigned r);
|
||||
static const QString & regName(eReg r);
|
||||
static const QString & opcodeName(unsigned r);
|
||||
static const QString & floatOpName(unsigned r);
|
||||
bool physicalReg(eReg r);
|
||||
/* Writes the registers that are set in the bitvector */
|
||||
//TODO: move this into Machine_X86 ?
|
||||
static void writeRegVector (std::ostream &ostr,const LivenessSet ®i);
|
||||
static void writeRegVector (QTextStream & ostr, const LivenessSet ®i);
|
||||
static eReg subRegH(eReg reg);
|
||||
static eReg subRegL(eReg reg);
|
||||
static bool isMemOff(eReg r);
|
||||
|
||||
3
include/msvc_fixes.h
Normal file
3
include/msvc_fixes.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#ifdef _MSC_VER
|
||||
#include <iso646.h>
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
/* Perfect hashing function library. Contains functions to generate perfect
|
||||
hashing functions
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
/* Prototypes */
|
||||
void hashCleanup(void); /* Frees memory allocated by hashParams() */
|
||||
void map(void); /* Part 1 of creating the tables */
|
||||
|
||||
/* The application must provide these functions: */
|
||||
void getKey(int i, uint8_t **pKeys);/* Set *keys to point to the i+1th key */
|
||||
void dispKey(int i); /* Display the key */
|
||||
class PatternHasher
|
||||
{
|
||||
uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
int SetSize; /* Size of the char set */
|
||||
char SetMin; /* First char in the set */
|
||||
int NumVert; /* c times NumEntry */
|
||||
int *graphNode; /* The array of edges */
|
||||
int *graphNext; /* Linked list of edges */
|
||||
int *graphFirst;/* First edge at a vertex */
|
||||
public:
|
||||
uint16_t *readT1(void); /* Returns a pointer to the T1 table */
|
||||
uint16_t *readT2(void); /* Returns a pointer to the T2 table */
|
||||
uint16_t *readG(void); /* Returns a pointer to the g table */
|
||||
void init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,int _NumVert); /* Set the parameters for the hash table */
|
||||
void cleanup();
|
||||
int hash(unsigned char *string); //!< Hash the string to an int 0 .. NUMENTRY-1
|
||||
};
|
||||
extern PatternHasher g_pattern_hasher;
|
||||
/* Macro reads a LH uint16_t from the image regardless of host convention */
|
||||
#ifndef LH
|
||||
#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8))
|
||||
#endif
|
||||
@@ -1,67 +1,174 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <boost/icl/interval.hpp>
|
||||
#include <boost/icl/interval_map.hpp>
|
||||
#include <boost/icl/split_interval_map.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "symtab.h"
|
||||
#include "BinaryImage.h"
|
||||
#include "Procedure.h"
|
||||
#include "state.h"
|
||||
#include "src/Command.h"
|
||||
|
||||
#include <boost/icl/interval.hpp>
|
||||
#include <boost/icl/interval_map.hpp>
|
||||
#include <boost/icl/split_interval_map.hpp>
|
||||
#include <QtCore/QString>
|
||||
#include <list>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
class QString;
|
||||
class SourceMachine;
|
||||
struct CALL_GRAPH;
|
||||
class IProject
|
||||
{
|
||||
virtual PROG *binary()=0;
|
||||
virtual const std::string & project_name() const =0;
|
||||
virtual const std::string & binary_path() const =0;
|
||||
struct DosLoader;
|
||||
struct SegOffAddr {
|
||||
uint16_t seg;
|
||||
uint32_t addr;
|
||||
};
|
||||
class Project : public IProject
|
||||
enum CompilerVendor {
|
||||
eUnknownVendor=0,
|
||||
eBorland,
|
||||
eMicrosoft,
|
||||
eLogitech,
|
||||
};
|
||||
enum CompilerLanguage {
|
||||
eUnknownLanguage=0,
|
||||
eAnsiCorCPP,
|
||||
ePascal,
|
||||
eModula2
|
||||
};
|
||||
enum CompilerMemoryModel {
|
||||
eUnknownMemoryModel=0,
|
||||
eTiny,
|
||||
eSmall,
|
||||
eCompact,
|
||||
eMedium,
|
||||
eLarge
|
||||
};
|
||||
struct LoaderMetadata {
|
||||
CompilerVendor compiler_vendor;
|
||||
CompilerLanguage compiler_language;
|
||||
CompilerMemoryModel compiler_memory_model;
|
||||
int compiler_version;
|
||||
QString compilerId() const {
|
||||
switch(compiler_vendor) {
|
||||
case eBorland:
|
||||
switch(compiler_language) {
|
||||
case eUnknownLanguage:
|
||||
return QString("bx") + codeModelChar();
|
||||
case eAnsiCorCPP:
|
||||
return QString("b%1%2").arg(compiler_version).arg(codeModelChar());
|
||||
case ePascal:
|
||||
return QString("tp%1").arg(compiler_version);
|
||||
default:
|
||||
return "xxx";
|
||||
}
|
||||
case eMicrosoft:
|
||||
assert(compiler_language==eAnsiCorCPP);
|
||||
return QString("m%1%2").arg(compiler_version).arg(codeModelChar());
|
||||
case eLogitech:
|
||||
assert(compiler_language==eModula2);
|
||||
return QString("l%1%2").arg(compiler_version).arg(codeModelChar());
|
||||
case eUnknownVendor:
|
||||
return "xxx";
|
||||
}
|
||||
return "xxx";
|
||||
}
|
||||
QChar codeModelChar() const {
|
||||
switch(compiler_memory_model) {
|
||||
case eUnknownMemoryModel: return 'x';
|
||||
case eTiny: return 't';
|
||||
case eSmall: return 's';
|
||||
case eCompact: return 'c';
|
||||
case eMedium: return 'm';
|
||||
case eLarge: return 'l';
|
||||
}
|
||||
return 'x';
|
||||
}
|
||||
};
|
||||
class Project : public QObject
|
||||
{
|
||||
static Project *s_instance;
|
||||
std::string m_fname;
|
||||
std::string m_project_name;
|
||||
Q_OBJECT
|
||||
public:
|
||||
DosLoader * m_selected_loader;
|
||||
bool m_metadata_available=false;
|
||||
LoaderMetadata m_loader_data;
|
||||
uint32_t SynthLab; //!< Last snthetic lab idx
|
||||
SYMTAB symtab; //!< Global symbol table
|
||||
FunctionListType pProcList; //!< List of located functions
|
||||
CALL_GRAPH * callGraph; //!< Pointer to the head of the call graph
|
||||
STATE m_entry_state; //!< Machine state at program load
|
||||
|
||||
typedef llvm::iplist<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef FunctionListType::iterator ilFunction;
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
|
||||
FunctionListType pProcList;
|
||||
CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
PROG prog; /* Loaded program image parameters */
|
||||
// no copies
|
||||
Project(const Project&) = delete;
|
||||
const Project &operator=(const Project & l) =delete;
|
||||
// only moves
|
||||
Project(); // default constructor,
|
||||
PROG prog; /* Loaded program image parameters */
|
||||
CommandStream m_project_command_stream;
|
||||
std::unordered_map<PtrFunction,CommandStream> m_function_streams;
|
||||
|
||||
bool m_error_state;
|
||||
struct PatternLocator *m_pattern_locator;
|
||||
public:
|
||||
void create(const std::string & a);
|
||||
const std::string &project_name() const {return m_project_name;}
|
||||
const std::string &binary_path() const {return m_fname;}
|
||||
ilFunction funcIter(Function *to_find);
|
||||
ilFunction findByEntry(uint32_t entry);
|
||||
ilFunction createFunction(FunctionType *f,const std::string &name);
|
||||
bool valid(ilFunction iter);
|
||||
// prevent Project instance copying
|
||||
Project(const Project&) = delete;
|
||||
const Project & operator=(const Project & l) =delete;
|
||||
// only moves
|
||||
Project(); // default constructor,
|
||||
|
||||
int getSymIdxByAdd(uint32_t adr);
|
||||
bool validSymIdx(size_t idx);
|
||||
size_t symbolSize(size_t idx);
|
||||
hlType symbolType(size_t idx);
|
||||
const std::string &symbolName(size_t idx);
|
||||
const SYM &getSymByIdx(size_t idx) const;
|
||||
void create(const QString &a);
|
||||
|
||||
static Project *get();
|
||||
PROG * binary() {return &prog;}
|
||||
SourceMachine *machine();
|
||||
bool addLoadCommands(QString fname);
|
||||
void processAllCommands();
|
||||
void resetCommandsAndErrorState();
|
||||
|
||||
|
||||
const QString & output_path() const {return m_output_path;}
|
||||
const QString & project_name() const {return m_project_name;}
|
||||
const QString & binary_path() const {return m_fname;}
|
||||
QString output_name(const char *ext);
|
||||
ilFunction funcIter(Function *to_find);
|
||||
PtrFunction findByEntry(uint32_t entry);
|
||||
PtrFunction findByName(const QString &name);
|
||||
PtrFunction createFunction(FunctionType *f, const QString & name, SegOffAddr addr);
|
||||
bool valid(ilFunction iter);
|
||||
|
||||
int getSymIdxByAdd(uint32_t adr);
|
||||
bool validSymIdx(size_t idx);
|
||||
size_t symbolSize(size_t idx);
|
||||
hlType symbolType(size_t idx);
|
||||
const QString & symbolName(size_t idx);
|
||||
const SYM & getSymByIdx(size_t idx) const;
|
||||
|
||||
LoaderMetadata &getLoaderMetadata() { assert(m_metadata_available); return m_loader_data; }
|
||||
void setLoaderMetadata(LoaderMetadata d) { m_loader_data = d; m_metadata_available=true;}
|
||||
static Project * get();
|
||||
PROG * binary() {return &prog;}
|
||||
SourceMachine *machine();
|
||||
|
||||
const FunctionListType &functions() const { return pProcList; }
|
||||
FunctionListType &functions() { return pProcList; }
|
||||
|
||||
bool addCommand(Command *cmd);
|
||||
bool addCommand(PtrFunction f, Command *cmd); // Add function level command
|
||||
bool hasCommands(const PtrFunction &f);
|
||||
CommandStream *functionCommands(const PtrFunction &f);
|
||||
void dumpAllErrors();
|
||||
void setLoader(DosLoader *ins);
|
||||
void processCommands(int count=1);
|
||||
void processFunctionCommands(const PtrFunction & func, int count);
|
||||
public slots:
|
||||
void onCommandStreamFinished(bool state);
|
||||
signals:
|
||||
void newFunctionCreated(PtrFunction);
|
||||
void functionUpdate(const PtrFunction &);
|
||||
void loaderSelected();
|
||||
void commandListChanged();
|
||||
protected:
|
||||
void initialize();
|
||||
void writeGlobSymTable();
|
||||
|
||||
protected:
|
||||
void initialize();
|
||||
void writeGlobSymTable();
|
||||
static Project * s_instance;
|
||||
QString m_fname;
|
||||
QString m_project_name;
|
||||
QString m_output_path;
|
||||
CommandContext m_command_ctx;
|
||||
|
||||
};
|
||||
//extern Project g_proj;
|
||||
|
||||
@@ -3,21 +3,22 @@
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include "machine_x86.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* STATE TABLE */
|
||||
struct STATE
|
||||
{
|
||||
uint32_t IP; /* Offset into Image */
|
||||
int16_t r[INDEX_BX_SI]; /* Value of segs and AX */
|
||||
uint32_t IP; /* Offset into Image */
|
||||
int16_t r[INDEX_BX_SI]; /* Register values */
|
||||
bool f[INDEX_BX_SI]; /* True if r[.] has a value */
|
||||
struct
|
||||
{ /* For case stmt indexed reg */
|
||||
uint8_t regi; /* Last conditional jump */
|
||||
int16_t immed; /* Contents of the previous register */
|
||||
} JCond;
|
||||
{ /* For case stmt indexed reg */
|
||||
uint8_t regi; /* Last conditional jump */
|
||||
int16_t immed; /* Contents of the previous register */
|
||||
} JCond;
|
||||
void setState(uint16_t reg, int16_t value);
|
||||
void checkStartup();
|
||||
bool isKnown(eReg v) {return f[v];}
|
||||
|
||||
@@ -3,10 +3,17 @@
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "Enums.h"
|
||||
#include "types.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
class QTextStream;
|
||||
|
||||
struct Expr;
|
||||
struct AstIdent;
|
||||
struct TypeContainer;
|
||||
@@ -15,10 +22,10 @@ struct TypeContainer;
|
||||
/* * * * * * * * * * * * * * * * * */
|
||||
struct SymbolCommon
|
||||
{
|
||||
std::string name; /* New name for this variable/symbol/argument */
|
||||
int size; /* Size/maximum size */
|
||||
QString name; /* New name for this variable/symbol/argument */
|
||||
int size; /* Size/maximum size */
|
||||
hlType type; /* probable type */
|
||||
eDuVal duVal; /* DEF, USE, VAL */
|
||||
eDuVal duVal; /* DEF, USE, VAL */
|
||||
SymbolCommon() : size(0),type(TYPE_UNKNOWN)
|
||||
{}
|
||||
};
|
||||
@@ -36,21 +43,14 @@ struct SYM : public SymbolCommon
|
||||
struct STKSYM : public SymbolCommon
|
||||
{
|
||||
typedef int16_t tLabel;
|
||||
Expr *actual; /* Expression tree of actual parameter */
|
||||
AstIdent *regs; /* For register arguments only */
|
||||
tLabel label; /* Immediate off from BP (+:args, -:params) */
|
||||
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
|
||||
bool hasMacro; /* This type needs a macro */
|
||||
std::string macro; /* Macro name */
|
||||
bool invalid; /* Boolean: invalid entry in formal arg list*/
|
||||
STKSYM()
|
||||
{
|
||||
actual=0;
|
||||
regs=0;
|
||||
label=0;
|
||||
regOff=0;
|
||||
invalid=hasMacro = false;
|
||||
}
|
||||
Expr * actual=0; /* Expression tree of actual parameter */
|
||||
AstIdent * regs=0; /* For register arguments only */
|
||||
tLabel label=0; /* Immediate off from BP (+:args, -:params) */
|
||||
uint8_t regOff=0; /* Offset is a register (e.g. SI, DI) */
|
||||
bool hasMacro=false; /* This type needs a macro */
|
||||
QString macro; /* Macro name */
|
||||
bool invalid=false; /* Boolean: invalid entry in formal arg list*/
|
||||
int arrayMembers=1; // for local variables if >1 marks this stack symbol as an array
|
||||
void setArgName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
void updateSymType(uint32_t symbol, const TypeContainer &tc);
|
||||
SYM *updateGlobSym(uint32_t operand, int size, uint16_t duFlag, bool &inserted_new);
|
||||
};
|
||||
struct Function;
|
||||
class Function;
|
||||
struct SYMTABLE
|
||||
{
|
||||
std::string pSymName; /* Ptr to symbolic name or comment */
|
||||
@@ -99,19 +99,19 @@ struct SYMTABLE
|
||||
{
|
||||
// does not yse pSymName, to ease finding by symOff/symProc combo
|
||||
// in map<SYMTABLE,X>
|
||||
return (symOff==other.symOff) && symProc==(other.symProc);
|
||||
return (symOff==other.symOff) and symProc==(other.symProc);
|
||||
}
|
||||
};
|
||||
|
||||
enum tableType /* The table types */
|
||||
{
|
||||
Label=0, /* The label table */
|
||||
Comment /* The comment table */
|
||||
Comment, /* The comment table */
|
||||
NUM_TABLE_TYPES /* Number of entries: must be last */
|
||||
};
|
||||
constexpr int NUM_TABLE_TYPES = int(Comment)+1; /* Number of entries: must be last */
|
||||
|
||||
void createSymTables(void);
|
||||
void destroySymTables(void);
|
||||
bool readVal (std::ostringstream &symName, uint32_t symOff, Function *symProc);
|
||||
bool readVal (QTextStream & symName, uint32_t symOff, Function *symProc);
|
||||
void selectTable(tableType); /* Select a particular table */
|
||||
|
||||
|
||||
@@ -5,9 +5,13 @@
|
||||
***************************************************************************
|
||||
*/
|
||||
#pragma once
|
||||
#include "Enums.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdint.h>
|
||||
#include "Enums.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/**** Common definitions and macros ****/
|
||||
#define MAX 0x7FFFFFFF
|
||||
|
||||
@@ -25,7 +29,7 @@
|
||||
// Macro reads a LH word from the image regardless of host convention
|
||||
// Returns a 16 bit quantity, e.g. C000 is read into an Int as C000
|
||||
//#define LH(p) ((int16)((byte *)(p))[0] + ((int16)((byte *)(p))[1] << 8))
|
||||
#define LH(p) ((uint16_t)((uint8_t *)(p))[0] + ((uint16_t)((uint8_t *)(p))[1] << 8))
|
||||
#define LH(p) ((uint16_t)((uint8_t *)(p))[0] + ((uint16_t)((uint8_t *)(p))[1] << 8))
|
||||
|
||||
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
@@ -64,12 +68,22 @@ struct eDuVal
|
||||
use = x&USE;
|
||||
val = x&VAL;
|
||||
}
|
||||
bool isUSE_VAL() {return use&&val;} //Use and Val
|
||||
bool isUSE_VAL() {return use and val;} //Use and Val
|
||||
};
|
||||
static constexpr const char * hlTypes[13] = {
|
||||
"", "char", "unsigned char", "int", "unsigned int",
|
||||
"long", "unsigned long", "record", "int *", "char *",
|
||||
"", "float", "double"
|
||||
"",
|
||||
"char",
|
||||
"unsigned char",
|
||||
"int",
|
||||
"unsigned int",
|
||||
"long",
|
||||
"unsigned long",
|
||||
"record",
|
||||
"int *",
|
||||
"char *",
|
||||
"",
|
||||
"float",
|
||||
"double"
|
||||
};
|
||||
|
||||
struct TypeContainer
|
||||
@@ -91,6 +105,8 @@ struct TypeContainer
|
||||
return 4;
|
||||
case TYPE_FLOAT:
|
||||
return 4;
|
||||
case TYPE_PTR:
|
||||
return 2;
|
||||
default:
|
||||
return ~0;
|
||||
}
|
||||
|
||||
BIN
prototypes/dcclibs.dat
Normal file
BIN
prototypes/dcclibs.dat
Normal file
Binary file not shown.
@@ -14,9 +14,9 @@ def perform_test(exepath,filepath,outname,args)
|
||||
filepath=path_local(filepath)
|
||||
joined_args = args.join(' ')
|
||||
printf("calling:" + "#{exepath} -a1 #{joined_args} -o#{output_path}.a1 #{filepath}\n")
|
||||
STDERR << "Errors for : #{filepath}"
|
||||
result = `#{exepath} -a1 -o#{output_path}.a1 #{filepath}`
|
||||
result = `#{exepath} -a2 #{joined_args} -o#{output_path}.a2 #{filepath}`
|
||||
STDERR << "Errors for : #{filepath}\n"
|
||||
result = `#{exepath} -a 1 -o#{output_path}.a1 #{filepath}`
|
||||
result = `#{exepath} -a 2 #{joined_args} -o#{output_path}.a2 #{filepath}`
|
||||
result = `#{exepath} #{joined_args} -o#{output_path} #{filepath}`
|
||||
puts result
|
||||
p $?
|
||||
|
||||
BIN
sigs/dccb2s.sig
Normal file
BIN
sigs/dccb2s.sig
Normal file
Binary file not shown.
BIN
sigs/dccb3l.sig
Normal file
BIN
sigs/dccb3l.sig
Normal file
Binary file not shown.
BIN
sigs/dccb3s.SIG
Normal file
BIN
sigs/dccb3s.SIG
Normal file
Binary file not shown.
6
src/Address.h
Normal file
6
src/Address.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint32_t LinearAddress;
|
||||
#define INVALID_ADDR Address(~0U)
|
||||
60
src/AutomatedPlanner.cpp
Normal file
60
src/AutomatedPlanner.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "AutomatedPlanner.h"
|
||||
|
||||
#include "project.h"
|
||||
#include "FollowControlFlow.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
/**
|
||||
* @class AutomatedPlanner
|
||||
* @brief Class responsible for building command lists
|
||||
*
|
||||
* The goal for top level [Project] plan is to build a fully decompiled representation of source binaries
|
||||
*/
|
||||
|
||||
AutomatedPlanner::AutomatedPlanner()
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Given a state of a project, add actions that will advance the decompilation
|
||||
* @param project
|
||||
*/
|
||||
void AutomatedPlanner::planFor(Project &project) {
|
||||
// TODO: For now this logic is sprinkled all over the place, should move it here
|
||||
// IF NO BINARY IMAGE LOADED - > add SelectImage/SelectProject command
|
||||
// IF NO LOADER SELECTED -> add SelectLoader command
|
||||
// ...
|
||||
}
|
||||
|
||||
void AutomatedPlanner::planFor(Function & func) {
|
||||
if(func.doNotDecompile())
|
||||
return; // for functions marked as non-decompileable we don't add any commands
|
||||
//TODO: Consider cases where commands are queued, but we can still plan some additional steps
|
||||
bool function_has_commands = Project::get()->hasCommands(func.shared_from_this());
|
||||
if(function_has_commands) {
|
||||
qDebug() << "Function "<<func.name<<"still has some commands queued, planning skipped";
|
||||
}
|
||||
switch(func.nStep) {
|
||||
case eNotDecoded:
|
||||
addAction(func,new FollowControlFlow(func.state));
|
||||
break;
|
||||
case eDisassemblyInProgress:
|
||||
// The command queue is empty and function is in eDisassemblyInProgress state ? Switch to eDisassembled
|
||||
assert(false and "Not implemented yet");
|
||||
break;
|
||||
case eDissassembled:
|
||||
// addAction(func,new LowLevelMarkImpure(func)
|
||||
assert(false and "Not implemented yet");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AutomatedPlanner::addAction(Function & func, Command * cmd)
|
||||
{
|
||||
Project::get()->addCommand(func.shared_from_this(),cmd);
|
||||
}
|
||||
|
||||
void AutomatedPlanner::addAction(Project & func, Command * cmd)
|
||||
{
|
||||
func.addCommand(cmd);
|
||||
}
|
||||
20
src/AutomatedPlanner.h
Normal file
20
src/AutomatedPlanner.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef AUTOMATEDPLANNER_H
|
||||
#define AUTOMATEDPLANNER_H
|
||||
|
||||
class Project;
|
||||
class Function;
|
||||
class Command;
|
||||
|
||||
class AutomatedPlanner
|
||||
{
|
||||
public:
|
||||
AutomatedPlanner();
|
||||
|
||||
void planFor(Project & project);
|
||||
void planFor(Function & func);
|
||||
protected:
|
||||
void addAction(Function &func,Command *cmd);
|
||||
void addAction(Project &func,Command *cmd);
|
||||
};
|
||||
|
||||
#endif // AUTOMATEDPLANNER_H
|
||||
@@ -1,11 +1,16 @@
|
||||
#include "BasicBlock.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "Procedure.h"
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <QtCore/QTextStream>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <boost/range/rbegin.hpp>
|
||||
#include <boost/range/rend.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
#include "BasicBlock.h"
|
||||
#include "Procedure.h"
|
||||
#include "dcc.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
@@ -23,16 +28,16 @@ BB *BB::Create(const rCODE &r,eBBKind _nodeType, Function *parent)
|
||||
{
|
||||
BB* pnewBB;
|
||||
pnewBB = new BB;
|
||||
pnewBB->nodeType = _nodeType; /* Initialise */
|
||||
pnewBB->nodeType = _nodeType; /* Initialise */
|
||||
pnewBB->immedDom = NO_DOM;
|
||||
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
|
||||
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
|
||||
pnewBB->instructions = r;
|
||||
int addr = pnewBB->begin()->loc_ip;
|
||||
/* Mark the basic block to which the icodes belong to, but only for
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
if(parent)
|
||||
{
|
||||
int addr = pnewBB->begin()->loc_ip;
|
||||
//setInBB should automatically handle if our range is empty
|
||||
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
|
||||
|
||||
@@ -40,10 +45,10 @@ BB *BB::Create(const rCODE &r,eBBKind _nodeType, Function *parent)
|
||||
parent->m_ip_to_bb[addr] = pnewBB;
|
||||
parent->m_actual_cfg.push_back(pnewBB);
|
||||
pnewBB->Parent = parent;
|
||||
}
|
||||
|
||||
if ( r.begin() != parent->Icode.end() ) /* Only for code BB's */
|
||||
if ( r.begin() != parent->Icode.end() ) /* Only for code BB's */
|
||||
stats.numBBbef++;
|
||||
}
|
||||
return pnewBB;
|
||||
|
||||
}
|
||||
@@ -90,7 +95,7 @@ void BB::displayDfs()
|
||||
dfsFirstNum, dfsLastNum,
|
||||
immedDom == MAX ? -1 : immedDom);
|
||||
printf("loopType = %s, loopHead = %d, latchNode = %d, follow = %d\n",
|
||||
s_loopType[loopType],
|
||||
s_loopType[(int)loopType],
|
||||
loopHead == MAX ? -1 : loopHead,
|
||||
latchNode == MAX ? -1 : latchNode,
|
||||
loopFollow == MAX ? -1 : loopFollow);
|
||||
@@ -136,12 +141,15 @@ void BB::displayDfs()
|
||||
*/
|
||||
ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, bool &repCond)
|
||||
{
|
||||
if(loopType == eNodeHeaderType::NO_TYPE)
|
||||
return nullptr;
|
||||
latch = pProc->m_dfsLast[this->latchNode];
|
||||
std::ostringstream ostr;
|
||||
QString ostr_contents;
|
||||
QTextStream ostr(&ostr_contents);
|
||||
ICODE* picode;
|
||||
switch (loopType)
|
||||
{
|
||||
case WHILE_TYPE:
|
||||
case eNodeHeaderType::WHILE_TYPE:
|
||||
picode = &this->back();
|
||||
|
||||
/* Check for error in while condition */
|
||||
@@ -163,43 +171,45 @@ ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&lat
|
||||
picode->hlU()->replaceExpr(picode->hl()->expr()->inverse());
|
||||
}
|
||||
{
|
||||
string e=picode->hl()->expr()->walkCondExpr (pProc, numLoc);
|
||||
QString e=picode->hl()->expr()->walkCondExpr (pProc, numLoc);
|
||||
ostr << "\n"<<indentStr(indLevel)<<"while ("<<e<<") {\n";
|
||||
}
|
||||
picode->invalidate();
|
||||
break;
|
||||
|
||||
case REPEAT_TYPE:
|
||||
case eNodeHeaderType::REPEAT_TYPE:
|
||||
ostr << "\n"<<indentStr(indLevel)<<"do {\n";
|
||||
picode = &latch->back();
|
||||
picode->invalidate();
|
||||
break;
|
||||
|
||||
case ENDLESS_TYPE:
|
||||
case eNodeHeaderType::ENDLESS_TYPE:
|
||||
ostr << "\n"<<indentStr(indLevel)<<"for (;;) {\n";
|
||||
picode = &latch->back();
|
||||
break;
|
||||
}
|
||||
cCode.appendCode(ostr.str());
|
||||
ostr.flush();
|
||||
cCode.appendCode(ostr_contents);
|
||||
stats.numHLIcode += 1;
|
||||
indLevel++;
|
||||
return picode;
|
||||
}
|
||||
bool BB::isEndOfPath(int latch_node_idx) const
|
||||
{
|
||||
return nodeType == RETURN_NODE || nodeType == TERMINATE_NODE ||
|
||||
nodeType == NOWHERE_NODE || (dfsLastNum == latch_node_idx);
|
||||
return nodeType == RETURN_NODE or nodeType == TERMINATE_NODE or
|
||||
nodeType == NOWHERE_NODE or dfsLastNum == latch_node_idx;
|
||||
}
|
||||
void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, int _ifFollow)
|
||||
{
|
||||
int follow; /* ifFollow */
|
||||
BB * succ, *latch; /* Successor and latching node */
|
||||
ICODE * picode; /* Pointer to HLI_JCOND instruction */
|
||||
std::string l; /* Pointer to HLI_JCOND expression */
|
||||
bool emptyThen, /* THEN clause is empty */
|
||||
repCond; /* Repeat condition for while() */
|
||||
int follow; /* ifFollow */
|
||||
BB * succ, *latch; /* Successor and latching node */
|
||||
ICODE * picode; /* Pointer to HLI_JCOND instruction */
|
||||
QString l; /* Pointer to HLI_JCOND expression */
|
||||
bool emptyThen, /* THEN clause is empty */
|
||||
repCond; /* Repeat condition for while() */
|
||||
|
||||
/* Check if this basic block should be analysed */
|
||||
if ((_ifFollow != UN_INIT) && (this == pProc->m_dfsLast[_ifFollow]))
|
||||
if ((_ifFollow != UN_INIT) and (this == pProc->m_dfsLast[_ifFollow]))
|
||||
return;
|
||||
|
||||
if (wasTraversedAtLevel(DFS_ALPHA))
|
||||
@@ -209,17 +219,16 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
/* Check for start of loop */
|
||||
repCond = false;
|
||||
latch = nullptr;
|
||||
if (loopType)
|
||||
{
|
||||
picode=writeLoopHeader(indLevel, pProc, numLoc, latch, repCond);
|
||||
}
|
||||
|
||||
/* Write the code for this basic block */
|
||||
if (repCond == false)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
QString ostr_contents;
|
||||
QTextStream ostr(&ostr_contents);
|
||||
writeBB(ostr,indLevel, pProc, numLoc);
|
||||
cCode.appendCode(ostr.str());
|
||||
ostr.flush();
|
||||
cCode.appendCode(ostr_contents);
|
||||
}
|
||||
|
||||
/* Check for end of path */
|
||||
@@ -227,12 +236,12 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
return;
|
||||
|
||||
/* Check type of loop/node and process code */
|
||||
if ( loopType ) /* there is a loop */
|
||||
if ( loopType!=eNodeHeaderType::NO_TYPE ) /* there is a loop */
|
||||
{
|
||||
assert(latch);
|
||||
if (this != latch) /* loop is over several bbs */
|
||||
if (this != latch) /* loop is over several bbs */
|
||||
{
|
||||
if (loopType == WHILE_TYPE)
|
||||
if (loopType == eNodeHeaderType::WHILE_TYPE)
|
||||
{
|
||||
succ = edges[THEN].BBptr;
|
||||
if (succ->dfsLastNum == loopFollow)
|
||||
@@ -242,15 +251,16 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
succ = edges[0].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc, numLoc, latch->dfsLastNum,_ifFollow);
|
||||
else /* has been traversed so we need a goto */
|
||||
else /* has been traversed so we need a goto */
|
||||
succ->front().ll()->emitGotoLabel (indLevel);
|
||||
}
|
||||
|
||||
/* Loop epilogue: generate the loop trailer */
|
||||
indLevel--;
|
||||
if (loopType == WHILE_TYPE)
|
||||
if (loopType == eNodeHeaderType::WHILE_TYPE)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
QString ostr_contents;
|
||||
QTextStream ostr(&ostr_contents);
|
||||
/* Check if there is need to repeat other statements involved
|
||||
* in while condition, then, emit the loop trailer */
|
||||
if (repCond)
|
||||
@@ -258,13 +268,14 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
writeBB(ostr,indLevel+1, pProc, numLoc);
|
||||
}
|
||||
ostr <<indentStr(indLevel)<< "} /* end of while */\n";
|
||||
cCode.appendCode(ostr.str());
|
||||
ostr.flush();
|
||||
cCode.appendCode(ostr_contents);
|
||||
}
|
||||
else if (loopType == ENDLESS_TYPE)
|
||||
else if (loopType == eNodeHeaderType::ENDLESS_TYPE)
|
||||
cCode.appendCode( "%s} /* end of loop */\n",indentStr(indLevel));
|
||||
else if (loopType == REPEAT_TYPE)
|
||||
else if (loopType == eNodeHeaderType::REPEAT_TYPE)
|
||||
{
|
||||
string e = "//*failed*//";
|
||||
QString e = "//*failed*//";
|
||||
if (picode->hl()->opcode != HLI_JCOND)
|
||||
{
|
||||
reportError (REPEAT_FAIL);
|
||||
@@ -273,7 +284,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
{
|
||||
e=picode->hl()->expr()->walkCondExpr (pProc, numLoc);
|
||||
}
|
||||
cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),e.c_str());
|
||||
cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),qPrintable(e));
|
||||
}
|
||||
|
||||
/* Recurse on the loop follow */
|
||||
@@ -282,20 +293,20 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
succ = pProc->m_dfsLast[loopFollow];
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
|
||||
else /* has been traversed so we need a goto */
|
||||
else /* has been traversed so we need a goto */
|
||||
succ->front().ll()->emitGotoLabel (indLevel);
|
||||
}
|
||||
}
|
||||
|
||||
else /* no loop, process nodeType of the graph */
|
||||
else /* no loop, process nodeType of the graph */
|
||||
{
|
||||
if (nodeType == TWO_BRANCH) /* if-then[-else] */
|
||||
if (nodeType == TWO_BRANCH) /* if-then[-else] */
|
||||
{
|
||||
stats.numHLIcode++;
|
||||
indLevel++;
|
||||
emptyThen = false;
|
||||
|
||||
if (ifFollow != MAX) /* there is a follow */
|
||||
if (ifFollow != MAX) /* there is a follow */
|
||||
{
|
||||
/* process the THEN part */
|
||||
follow = ifFollow;
|
||||
@@ -305,13 +316,13 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
if (succ->dfsLastNum != follow) /* THEN part */
|
||||
{
|
||||
l = writeJcond ( *back().hl(), pProc, numLoc);
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l.c_str());
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), qPrintable(l));
|
||||
succ->writeCode (indLevel, pProc, numLoc, _latchNode,follow);
|
||||
}
|
||||
else /* empty THEN part => negate ELSE part */
|
||||
else /* empty THEN part => negate ELSE part */
|
||||
{
|
||||
l = writeJcondInv ( *back().hl(), pProc, numLoc);
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l.c_str());
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), qPrintable(l));
|
||||
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, follow);
|
||||
emptyThen = true;
|
||||
}
|
||||
@@ -321,9 +332,9 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
|
||||
/* process the ELSE part */
|
||||
succ = edges[ELSE].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA) /* not visited */
|
||||
if (succ->traversed != DFS_ALPHA) /* not visited */
|
||||
{
|
||||
if (succ->dfsLastNum != follow) /* ELSE part */
|
||||
if (succ->dfsLastNum != follow) /* ELSE part */
|
||||
{
|
||||
cCode.appendCode( "%s}\n%selse {\n",
|
||||
indentStr(indLevel-1), indentStr(indLevel - 1));
|
||||
@@ -331,7 +342,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
}
|
||||
/* else (empty ELSE part) */
|
||||
}
|
||||
else if (! emptyThen) /* already visited => emit label */
|
||||
else if (not emptyThen) /* already visited => emit label */
|
||||
{
|
||||
cCode.appendCode( "%s}\n%selse {\n",
|
||||
indentStr(indLevel-1), indentStr(indLevel - 1));
|
||||
@@ -344,10 +355,10 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc, numLoc, _latchNode,_ifFollow);
|
||||
}
|
||||
else /* no follow => if..then..else */
|
||||
else /* no follow => if..then..else */
|
||||
{
|
||||
l = writeJcond ( *back().hl(), pProc, numLoc);
|
||||
cCode.appendCode( "%s%s", indentStr(indLevel-1), l.c_str());
|
||||
cCode.appendCode( "%s%s", indentStr(indLevel-1), qPrintable(l));
|
||||
edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
|
||||
cCode.appendCode( "%s}\n%selse {\n", indentStr(indLevel-1), indentStr(indLevel - 1));
|
||||
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
|
||||
@@ -357,7 +368,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
|
||||
else /* fall, call, 1w */
|
||||
{
|
||||
succ = edges[0].BBptr; /* fall-through edge */
|
||||
succ = edges[0].BBptr; /* fall-through edge */
|
||||
assert(succ->size()>0);
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
{
|
||||
@@ -368,9 +379,9 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
}
|
||||
/* Writes the code for the current basic block.
|
||||
* Args: pBB: pointer to the current basic block.
|
||||
* Icode: pointer to the array of icodes for current procedure.
|
||||
* lev: indentation level - used for formatting. */
|
||||
void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
|
||||
* Icode: pointer to the array of icodes for current procedure.
|
||||
* lev: indentation level - used for formatting. */
|
||||
void BB::writeBB(QTextStream &ostr,int lev, Function * pProc, int *numLoc)
|
||||
{
|
||||
/* Save the index into the code table in case there is a later goto
|
||||
* into this instruction (first instruction of the BB) */
|
||||
@@ -380,10 +391,10 @@ void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
|
||||
|
||||
for(ICODE &pHli : instructions)
|
||||
{
|
||||
if ((pHli.type == HIGH_LEVEL) && ( pHli.valid() )) //TODO: use filtering range here.
|
||||
if ((pHli.type == HIGH_LEVEL_ICODE) and ( pHli.valid() )) //TODO: use filtering range here.
|
||||
{
|
||||
std::string line = pHli.hl()->write1HlIcode(pProc, numLoc);
|
||||
if (!line.empty())
|
||||
QString line = pHli.hl()->write1HlIcode(pProc, numLoc);
|
||||
if (not line.isEmpty())
|
||||
{
|
||||
ostr<<indentStr(lev)<<line;
|
||||
stats.numHLIcode++;
|
||||
|
||||
@@ -1,13 +1,131 @@
|
||||
SET(dcc_test_SOURCES
|
||||
tests/comwrite.cpp
|
||||
tests/project.cpp
|
||||
tests/loader.cpp
|
||||
set(dcc_LIB_SOURCES
|
||||
CallConvention.cpp
|
||||
ast.cpp
|
||||
backend.cpp
|
||||
bundle.cpp
|
||||
chklib.cpp
|
||||
comwrite.cpp
|
||||
control.cpp
|
||||
dataflow.cpp
|
||||
disassem.cpp
|
||||
DccFrontend.cpp
|
||||
error.cpp
|
||||
fixwild.cpp
|
||||
graph.cpp
|
||||
hlicode.cpp
|
||||
hltype.cpp
|
||||
machine_x86.cpp
|
||||
icode.cpp
|
||||
RegisterNode
|
||||
idioms.cpp
|
||||
idioms/idiom1.cpp
|
||||
idioms/arith_idioms.cpp
|
||||
idioms/call_idioms.cpp
|
||||
idioms/epilogue_idioms.cpp
|
||||
idioms/mov_idioms.cpp
|
||||
idioms/neg_idioms.cpp
|
||||
idioms/shift_idioms.cpp
|
||||
idioms/xor_idioms.cpp
|
||||
locident.cpp
|
||||
liveness_set.cpp
|
||||
parser.h
|
||||
parser.cpp
|
||||
procs.cpp
|
||||
project.cpp
|
||||
Procedure.cpp
|
||||
proplong.cpp
|
||||
reducible.cpp
|
||||
scanner.cpp
|
||||
symtab.cpp
|
||||
udm.cpp
|
||||
BasicBlock.cpp
|
||||
dcc_interface.cpp
|
||||
|
||||
MemoryChunk
|
||||
MemorySegment
|
||||
MemorySegmentCoordinator
|
||||
|
||||
Command.cpp
|
||||
Command.h
|
||||
Loaders.cpp
|
||||
Loaders.h
|
||||
FollowControlFlow.cpp
|
||||
FollowControlFlow.h
|
||||
|
||||
AutomatedPlanner
|
||||
)
|
||||
set(dcc_UI_SOURCES
|
||||
ui/DccMainWindow.ui
|
||||
ui/DccMainWindow.h
|
||||
ui/DccMainWindow.cpp
|
||||
ui/FunctionViewWidget.ui
|
||||
ui/FunctionViewWidget.h
|
||||
ui/FunctionViewWidget.cpp
|
||||
ui/FunctionListDockWidget.ui
|
||||
ui/FunctionListDockWidget.cpp
|
||||
ui/FunctionListDockWidget.h
|
||||
ui/RenderTags.cpp
|
||||
ui/RenderTags.h
|
||||
ui/CommandQueueView.cpp
|
||||
ui/CommandQueueView.h
|
||||
ui/CommandQueueView.ui
|
||||
)
|
||||
set(dcc_HEADERS
|
||||
../include/ast.h
|
||||
../include/bundle.h
|
||||
../include/BinaryImage.h
|
||||
../include/DccFrontend.h
|
||||
../include/Enums.h
|
||||
../include/dcc.h
|
||||
../include/disassem.h
|
||||
../include/dosdcc.h
|
||||
../include/error.h
|
||||
../include/graph.h
|
||||
../include/hlicode.h
|
||||
../include/machine_x86.h
|
||||
../include/icode.h
|
||||
../include/idioms/idiom.h
|
||||
../include/idioms/idiom1.h
|
||||
../include/idioms/arith_idioms.h
|
||||
../include/idioms/call_idioms.h
|
||||
../include/idioms/epilogue_idioms.h
|
||||
../include/idioms/mov_idioms.h
|
||||
../include/idioms/neg_idioms.h
|
||||
../include/idioms/shift_idioms.h
|
||||
../include/idioms/xor_idioms.h
|
||||
../include/locident.h
|
||||
../include/CallConvention.h
|
||||
../include/project.h
|
||||
../include/scanner.h
|
||||
../include/state.h
|
||||
../include/symtab.h
|
||||
../include/types.h
|
||||
../include/Procedure.h
|
||||
../include/StackFrame.h
|
||||
../include/BasicBlock.h
|
||||
../include/dcc_interface.h
|
||||
)
|
||||
include_directories(${GMOCK_INCLUDE_DIRS} ${GMOCK_ROOT}/gtest/include)
|
||||
add_executable(tester ${dcc_test_SOURCES})
|
||||
ADD_DEPENDENCIES(tester dcc_lib)
|
||||
|
||||
target_link_libraries(tester dcc_lib disasm_s
|
||||
${GMOCK_BOTH_LIBRARIES} ${REQ_LLVM_LIBRARIES})
|
||||
add_test(dcc-tests tester)
|
||||
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
|
||||
|
||||
set(dcc_SOURCES
|
||||
dcc.cpp
|
||||
)
|
||||
|
||||
SOURCE_GROUP(Source FILES ${dcc_SOURCES} ${dcc_LIB_SOURCES})
|
||||
|
||||
ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
|
||||
qt5_use_modules(dcc_lib Core)
|
||||
|
||||
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_UI_SOURCES})
|
||||
ADD_DEPENDENCIES(dcc_original dcc_lib)
|
||||
TARGET_LINK_LIBRARIES(dcc_original dcc_lib dcc_hash disasm_s)
|
||||
qt5_use_modules(dcc_original Core Widgets)
|
||||
SET_PROPERTY(TARGET dcc_original PROPERTY CXX_STANDARD 11)
|
||||
SET_PROPERTY(TARGET dcc_original PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
|
||||
if(dcc_build_tests)
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
endif()
|
||||
|
||||
@@ -1,17 +1,98 @@
|
||||
#include <ostream>
|
||||
#include <cassert>
|
||||
#include "CallConvention.h"
|
||||
|
||||
CConv *CConv::create(Type v)
|
||||
#include "Procedure.h"
|
||||
|
||||
#include <QtCore/QTextStream>
|
||||
#include <ostream>
|
||||
#include <cassert>
|
||||
static void calculateReturnLocations(Function *func) {
|
||||
switch(func->getReturnType()) {
|
||||
case TYPE_LONG_SIGN:
|
||||
case TYPE_LONG_UNSIGN:
|
||||
func->getFunctionType()->setReturnLocation(LONGID_TYPE(rDX,rAX));
|
||||
break;
|
||||
case TYPE_WORD_SIGN:
|
||||
case TYPE_WORD_UNSIGN:
|
||||
func->getFunctionType()->setReturnLocation(rAX);
|
||||
break;
|
||||
case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN:
|
||||
func->getFunctionType()->setReturnLocation(rAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void calculateArgLocations_allOnStack(Function *func) {
|
||||
FunctionType *type = func->type;
|
||||
int stack_offset=2;
|
||||
if(func->args.size() == type->ContainedTys.size())
|
||||
return;
|
||||
func->args.resize(type->ContainedTys.size());
|
||||
func->args.numArgs=0;
|
||||
for(Type & argtype : type->ContainedTys) {
|
||||
STKSYM &arg(func->args[func->args.numArgs]);
|
||||
arg.label= stack_offset;
|
||||
arg.size = TypeContainer::typeSize(argtype.dcc_type);
|
||||
arg.type = argtype.dcc_type;
|
||||
arg.setArgName(func->args.numArgs);
|
||||
stack_offset+=arg.size;
|
||||
func->args.m_maxOff=stack_offset;
|
||||
func->args.numArgs++;
|
||||
}
|
||||
func->cbParam = stack_offset;
|
||||
}
|
||||
|
||||
static void rebuildArguments_FromStackLayout(Function *func) {
|
||||
|
||||
STKFRAME &stk(func->args);
|
||||
std::map<int,const STKSYM *> arg_locations;
|
||||
FunctionType *f;
|
||||
|
||||
for(const STKSYM & s: stk) {
|
||||
if(s.label>0) {
|
||||
arg_locations[s.label] = &s;
|
||||
}
|
||||
}
|
||||
|
||||
if(arg_locations.empty())
|
||||
return;
|
||||
|
||||
std::vector<Type> argtypes;
|
||||
auto stack_loc_iter = arg_locations.begin();
|
||||
for(int i=stack_loc_iter->first; i<=arg_locations.rbegin()->first; ) {
|
||||
int till_next_loc=stack_loc_iter->first-i;
|
||||
if(till_next_loc==0) {
|
||||
int entry_size=stack_loc_iter->second->size;
|
||||
argtypes.push_back({stack_loc_iter->second->type});
|
||||
i+=entry_size;
|
||||
++stack_loc_iter;
|
||||
} else {
|
||||
if(till_next_loc>=4) {
|
||||
argtypes.push_back({TYPE_LONG_SIGN});
|
||||
i+=4;
|
||||
} else if(till_next_loc>=2) {
|
||||
argtypes.push_back({TYPE_WORD_SIGN});
|
||||
i+=2;
|
||||
} else {
|
||||
argtypes.push_back({TYPE_BYTE_SIGN});
|
||||
i+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
f = FunctionType::get({func->type->getReturnType()},argtypes,func->type->isVarArg());
|
||||
f->retVal = func->type->retVal;
|
||||
delete func->type;
|
||||
func->type = f;
|
||||
}
|
||||
CConv *CConv::create(CC_Type v)
|
||||
{
|
||||
static C_CallingConvention *c_call = nullptr;
|
||||
static Pascal_CallingConvention *p_call = nullptr;
|
||||
static Unknown_CallingConvention *u_call= nullptr;
|
||||
if(!c_call)
|
||||
if(nullptr==c_call)
|
||||
c_call = new C_CallingConvention;
|
||||
if(!p_call)
|
||||
if(nullptr==p_call)
|
||||
p_call = new Pascal_CallingConvention;
|
||||
if(!u_call)
|
||||
if(nullptr==u_call)
|
||||
u_call = new Unknown_CallingConvention;
|
||||
switch(v) {
|
||||
case UNKNOWN: return u_call;
|
||||
@@ -22,15 +103,35 @@ CConv *CConv::create(Type v)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void C_CallingConvention::writeComments(std::ostream &ostr)
|
||||
void C_CallingConvention::writeComments(QTextStream & ostr)
|
||||
{
|
||||
ostr << " * C calling convention.\n";
|
||||
}
|
||||
void Pascal_CallingConvention::writeComments(std::ostream &ostr)
|
||||
|
||||
void C_CallingConvention::calculateStackLayout(Function *func)
|
||||
{
|
||||
calculateReturnLocations(func);
|
||||
rebuildArguments_FromStackLayout(func);
|
||||
calculateArgLocations_allOnStack(func);
|
||||
}
|
||||
void Pascal_CallingConvention::writeComments(QTextStream & ostr)
|
||||
{
|
||||
ostr << " * Pascal calling convention.\n";
|
||||
}
|
||||
void Unknown_CallingConvention::writeComments(std::ostream &ostr)
|
||||
void Pascal_CallingConvention::calculateStackLayout(Function *func)
|
||||
{
|
||||
calculateReturnLocations(func);
|
||||
//TODO: pascal args are passed in reverse order ?
|
||||
rebuildArguments_FromStackLayout(func);
|
||||
calculateArgLocations_allOnStack(func);
|
||||
}
|
||||
void Unknown_CallingConvention::writeComments(QTextStream & ostr)
|
||||
{
|
||||
ostr << " * Unknown calling convention.\n";
|
||||
}
|
||||
void Unknown_CallingConvention::calculateStackLayout(Function *func)
|
||||
{
|
||||
calculateReturnLocations(func);
|
||||
rebuildArguments_FromStackLayout(func);
|
||||
calculateArgLocations_allOnStack(func);
|
||||
}
|
||||
|
||||
138
src/Command.cpp
Normal file
138
src/Command.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "Command.h"
|
||||
|
||||
#include "DccFrontend.h"
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
#include "Loaders.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
bool LoaderSelection::execute(CommandContext * ctx)
|
||||
{
|
||||
Project *proj=ctx->m_project;
|
||||
if(nullptr==proj) {
|
||||
ctx->recordFailure(this,"No active project ");
|
||||
return false;
|
||||
}
|
||||
if(m_filename.isEmpty()) {
|
||||
ctx->recordFailure(this,"No executable path given to loader selector");
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile finfo(m_filename);
|
||||
/* Open the input file */
|
||||
if(not finfo.open(QFile::ReadOnly)) {
|
||||
ctx->recordFailure(this,QString("Cannot open file %1").arg(m_filename));
|
||||
return false;
|
||||
}
|
||||
/* Read in first 2 bytes to check EXE signature */
|
||||
if (finfo.size()<=2)
|
||||
{
|
||||
ctx->recordFailure(this,QString("File %1 is too small").arg(m_filename));
|
||||
}
|
||||
ComLoader com_loader;
|
||||
ExeLoader exe_loader;
|
||||
|
||||
if(exe_loader.canLoad(finfo)) {
|
||||
proj->setLoader(new ExeLoader);
|
||||
return true;
|
||||
}
|
||||
if(com_loader.canLoad(finfo)) {
|
||||
proj->setLoader(new ComLoader);
|
||||
return true;
|
||||
}
|
||||
ctx->recordFailure(this,QString("None of the available loaders can load file %1").arg(m_filename));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoaderApplication::execute(CommandContext * ctx)
|
||||
{
|
||||
Project *proj=ctx->m_project;
|
||||
|
||||
if(nullptr==proj) {
|
||||
ctx->recordFailure(this,"No active project ");
|
||||
return false;
|
||||
}
|
||||
if(!proj->m_selected_loader) {
|
||||
ctx->recordFailure(this,QString("No loader selected for project %1").arg(proj->project_name()));
|
||||
return false;
|
||||
}
|
||||
QFile finfo(m_filename);
|
||||
if(not finfo.open(QFile::ReadOnly)) {
|
||||
ctx->recordFailure(this,QString("Cannot open file %1").arg(m_filename));
|
||||
return false;
|
||||
}
|
||||
bool load_res = proj->m_selected_loader->load(proj->prog,finfo);
|
||||
if(!load_res) {
|
||||
ctx->recordFailure(this,QString("Failure during load: %1").arg(m_filename));
|
||||
return false;
|
||||
}
|
||||
if (option.verbose)
|
||||
proj->prog.displayLoadInfo();
|
||||
FunctionType *main_type = FunctionType::get(Type{TYPE_UNKNOWN},{ },false);
|
||||
main_type->setCallingConvention(CConv::UNKNOWN);
|
||||
/* Create initial procedure at program start address */
|
||||
PROG &prog(proj->prog);
|
||||
CreateFunction *cmd = new CreateFunction("start",
|
||||
SegOffAddr {prog.segMain,((uint32_t)prog.initCS << 4) + prog.initIP},
|
||||
main_type);
|
||||
proj->addCommand(cmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandStream::add(Command * c) {
|
||||
if(m_commands.size()>=m_maximum_command_count)
|
||||
return false;
|
||||
m_commands.push_back(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandStream::setMaximumCommandCount(int maximum_command_count) {
|
||||
m_maximum_command_count = maximum_command_count;
|
||||
}
|
||||
|
||||
void CommandStream::processAll(CommandContext *ctx)
|
||||
{
|
||||
while(not m_commands.isEmpty()) {
|
||||
Command *cmd = m_commands.takeFirst();
|
||||
if(false==cmd->execute(ctx)) {
|
||||
emit streamCompleted(false);
|
||||
break;
|
||||
}
|
||||
m_recently_executed.push_back(cmd);
|
||||
}
|
||||
emit streamCompleted(true);
|
||||
}
|
||||
|
||||
bool CommandStream::processOne(CommandContext *ctx)
|
||||
{
|
||||
if(not m_commands.isEmpty()) {
|
||||
Command *cmd = m_commands.takeFirst();
|
||||
if(false==cmd->execute(ctx)) {
|
||||
emit streamChanged();
|
||||
return false;
|
||||
}
|
||||
m_recently_executed.push_back(cmd);
|
||||
}
|
||||
emit streamChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandStream::clear()
|
||||
{
|
||||
qDeleteAll(m_commands);
|
||||
qDeleteAll(m_recently_executed);
|
||||
m_commands.clear();
|
||||
m_recently_executed.clear();
|
||||
}
|
||||
|
||||
|
||||
void CommandContext::reset()
|
||||
{
|
||||
for(int i=0; i<m_failures.size(); ++i) {
|
||||
delete m_failures[i].first;
|
||||
}
|
||||
m_failures.clear();
|
||||
}
|
||||
95
src/Command.h
Normal file
95
src/Command.h
Normal file
@@ -0,0 +1,95 @@
|
||||
#ifndef COMMAND_H
|
||||
#define COMMAND_H
|
||||
|
||||
#include <memory>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QPair>
|
||||
|
||||
class Project;
|
||||
class Function;
|
||||
typedef std::shared_ptr<Function> PtrFunction;
|
||||
enum CommandLevel {
|
||||
eProject,
|
||||
eBinary,
|
||||
eFunction,
|
||||
eBasicBlock,
|
||||
eInstruction
|
||||
};
|
||||
class Command;
|
||||
|
||||
class CommandContext {
|
||||
public:
|
||||
void recordFailure(Command *cmd,QString error_message) {
|
||||
m_failures.push_back({cmd,error_message});
|
||||
}
|
||||
|
||||
Project *m_project;
|
||||
PtrFunction m_func;
|
||||
QVector<QPair<Command *,QString>> m_failures;
|
||||
void reset();
|
||||
};
|
||||
|
||||
class Command
|
||||
{
|
||||
QString m_command_name;
|
||||
CommandLevel m_level;
|
||||
public:
|
||||
Command(QString n,CommandLevel level) : m_command_name(n),m_level(level) {}
|
||||
virtual ~Command() {}
|
||||
|
||||
QString name() const { return m_command_name;}
|
||||
virtual QString instanceDescription() const { return m_command_name; }
|
||||
virtual bool execute(CommandContext *) { return false; }
|
||||
};
|
||||
class CompoundCommand : public Command {
|
||||
QVector<Command *> m_contained;
|
||||
public:
|
||||
CompoundCommand(QString n,CommandLevel l) : Command(n,l) {
|
||||
}
|
||||
void addCommand(Command *c) {
|
||||
m_contained.push_back(c);
|
||||
}
|
||||
bool execute(CommandContext * ctx) {
|
||||
for(Command * c : m_contained) {
|
||||
if(!c->execute(ctx))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
class CommandStream : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
int m_maximum_command_count=5;
|
||||
public:
|
||||
QVector<Command *> m_recently_executed;
|
||||
QVector<Command *> m_commands;
|
||||
bool add(Command *c);
|
||||
void setMaximumCommandCount(int maximum_command_count);
|
||||
bool processOne(CommandContext *ctx);
|
||||
void processAll(CommandContext *ctx);
|
||||
void clear();
|
||||
bool isEmpty() const { return m_commands.isEmpty(); }
|
||||
signals:
|
||||
void streamCompleted(bool success);
|
||||
void streamChanged();
|
||||
};
|
||||
// Effect: loader has been selected and set in current project
|
||||
class LoaderSelection : public Command {
|
||||
QString m_filename;
|
||||
public:
|
||||
virtual ~LoaderSelection() {}
|
||||
LoaderSelection(QString f) : Command("Select loader",eProject),m_filename(f) {}
|
||||
bool execute(CommandContext * ctx) override;
|
||||
};
|
||||
// trigger Project->m_selected_loader has changed
|
||||
// Effect: the PROG object is loaded using the current loader
|
||||
class LoaderApplication : public Command {
|
||||
QString m_filename;
|
||||
public:
|
||||
virtual ~LoaderApplication() {}
|
||||
LoaderApplication(QString f) : Command("Apply loader",eProject),m_filename(f) {}
|
||||
bool execute(CommandContext * ctx) override;
|
||||
};
|
||||
#endif // COMMAND_H
|
||||
230
src/DccFrontend.cpp
Normal file
230
src/DccFrontend.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
#include "DccFrontend.h"
|
||||
|
||||
#include "Loaders.h"
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "project.h"
|
||||
#include "disassem.h"
|
||||
#include "CallGraph.h"
|
||||
#include "Command.h"
|
||||
#include "chklib.h"
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QDebug>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
//static void LoadImage(char *filename);
|
||||
static void displayMemMap(void);
|
||||
/****************************************************************************
|
||||
* displayLoadInfo - Displays low level loader type info.
|
||||
***************************************************************************/
|
||||
void PROG::displayLoadInfo(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("File type is %s\n", (fCOM)?"COM":"EXE");
|
||||
// if (not fCOM) {
|
||||
// printf("Signature = %02X%02X\n", header.sigLo, header.sigHi);
|
||||
// printf("File size %% 512 = %04X\n", LH(&header.lastPageSize));
|
||||
// printf("File size / 512 = %04X pages\n", LH(&header.numPages));
|
||||
// printf("# relocation items = %04X\n", LH(&header.numReloc));
|
||||
// printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
|
||||
// printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
|
||||
// printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
|
||||
// }
|
||||
printf("Load image size = %08lX\n", cbImage); // - sizeof(PSP)
|
||||
printf("Initial SS:SP = %04X:%04X\n", initSS, initSP);
|
||||
printf("Initial CS:IP = %04X:%04X\n", initCS, initIP);
|
||||
|
||||
if (option.VeryVerbose and cReloc)
|
||||
{
|
||||
printf("\nRelocation Table\n");
|
||||
for (i = 0; i < cReloc; i++)
|
||||
{
|
||||
printf("%06X -> [%04X]\n", relocTable[i],LH(image() + relocTable[i]));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* fill - Fills line for displayMemMap()
|
||||
****************************************************************************/
|
||||
static void fill(int ip, char *bf)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
static uint8_t type[4] = {'.', 'd', 'c', 'x'};
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 16; i++, ip++)
|
||||
{
|
||||
*bf++ = ' ';
|
||||
*bf++ = (ip < prog.cbImage)? type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
|
||||
}
|
||||
*bf = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* displayMemMap - Displays the memory bitmap
|
||||
****************************************************************************/
|
||||
static void displayMemMap(void)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
|
||||
char c, b1[33], b2[33], b3[33];
|
||||
uint8_t i;
|
||||
int ip = 0;
|
||||
|
||||
printf("\nMemory Map\n");
|
||||
while (ip < prog.cbImage)
|
||||
{
|
||||
fill(ip, b1);
|
||||
printf("%06X %s\n", ip, b1);
|
||||
ip += 16;
|
||||
for (i = 3, c = b1[1]; i < 32 and c == b1[i]; i += 2)
|
||||
; /* Check if all same */
|
||||
if (i > 32)
|
||||
{
|
||||
fill(ip, b2); /* Skip until next two are not same */
|
||||
fill(ip+16, b3);
|
||||
if (not (strcmp(b1, b2) || strcmp(b1, b3)))
|
||||
{
|
||||
printf(" :\n");
|
||||
do
|
||||
{
|
||||
ip += 16;
|
||||
fill(ip+16, b1);
|
||||
} while (0==strcmp(b1, b2));
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
DccFrontend::DccFrontend(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
|
||||
* rewritter, and displays any useful information.
|
||||
****************************************************************************/
|
||||
bool DccFrontend::FrontEnd ()
|
||||
{
|
||||
|
||||
/* Do depth first flow analysis building call graph and procedure list,
|
||||
* and attaching the I-code to each procedure */
|
||||
parse (*Project::get());
|
||||
|
||||
if (option.asm1)
|
||||
{
|
||||
qWarning() << "dcc: writing assembler file "<<asm1_name<<'\n';
|
||||
}
|
||||
|
||||
/* Search through code looking for impure references and flag them */
|
||||
Disassembler ds(1);
|
||||
for(PtrFunction &f : Project::get()->pProcList)
|
||||
{
|
||||
f->markImpure();
|
||||
if (option.asm1)
|
||||
{
|
||||
ds.disassem(f);
|
||||
}
|
||||
}
|
||||
if (option.Interact)
|
||||
{
|
||||
interactDis(Project::get()->pProcList.front(), 0); /* Interactive disassembler */
|
||||
}
|
||||
|
||||
/* Converts jump target addresses to icode offsets */
|
||||
for(PtrFunction &f : Project::get()->pProcList)
|
||||
{
|
||||
f->bindIcodeOff();
|
||||
}
|
||||
/* Print memory bitmap */
|
||||
if (option.Map)
|
||||
displayMemMap();
|
||||
return(true); // we no longer own proj !
|
||||
}
|
||||
/*****************************************************************************
|
||||
* LoadImage
|
||||
****************************************************************************/
|
||||
|
||||
/* Parses the program, builds the call graph, and returns the list of
|
||||
* procedures found */
|
||||
void DccFrontend::parse(Project &proj)
|
||||
{
|
||||
/* Set initial state */
|
||||
proj.addCommand(new MachineStateInitialization);
|
||||
proj.addCommand(new FindMain);
|
||||
}
|
||||
|
||||
bool MachineStateInitialization::execute(CommandContext *ctx)
|
||||
{
|
||||
assert(ctx && ctx->m_project);
|
||||
Project &proj(*ctx->m_project);
|
||||
const PROG &prog(proj.prog);
|
||||
proj.m_entry_state.setState(rES, 0); /* PSP segment */
|
||||
proj.m_entry_state.setState(rDS, 0);
|
||||
proj.m_entry_state.setState(rCS, prog.initCS);
|
||||
proj.m_entry_state.setState(rSS, prog.initSS);
|
||||
proj.m_entry_state.setState(rSP, prog.initSP);
|
||||
proj.m_entry_state.IP = ((uint32_t)prog.initCS << 4) + prog.initIP;
|
||||
proj.SynthLab = SYNTHESIZED_MIN;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FindMain::execute(CommandContext *ctx) {
|
||||
Project &proj(*ctx->m_project);
|
||||
const PROG &prog(proj.prog);
|
||||
|
||||
PtrFunction start_func = proj.findByName("start");
|
||||
if(ctx->m_project->m_entry_state.IP==0) {
|
||||
ctx->recordFailure(this,"Cannot search for main func when no entry point was found");
|
||||
return false;
|
||||
}
|
||||
/* Check for special settings of initial state, based on idioms of the startup code */
|
||||
if(checkStartup(ctx->m_project->m_entry_state)) {
|
||||
start_func->markDoNotDecompile(); // we have main, do not decompile the start proc
|
||||
//TODO: main arguments and return values should depend on detected compiler/library
|
||||
FunctionType *main_type = FunctionType::get(Type{TYPE_WORD_SIGN},{ Type{TYPE_WORD_SIGN},Type{TYPE_PTR} },false);
|
||||
main_type->setCallingConvention(CConv::C);
|
||||
proj.addCommand(new CreateFunction("main",SegOffAddr {prog.segMain,prog.offMain},main_type));
|
||||
|
||||
proj.addCommand(new LoadPatternLibrary());
|
||||
} else {
|
||||
start_func->state = proj.m_entry_state; // just in case we fail to find main, initialize 'state' for start func
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString CreateFunction::instanceDescription() const {
|
||||
return QString("%1 \"%2\" @ 0x%3").arg(name()).arg(m_name).arg(m_addr.addr,0,16,QChar('0'));
|
||||
}
|
||||
|
||||
bool CreateFunction::execute(CommandContext *ctx) {
|
||||
Project &proj(*ctx->m_project);
|
||||
const PROG &prog(proj.prog);
|
||||
|
||||
PtrFunction func = proj.createFunction(m_type,m_name,m_addr);
|
||||
if(m_name=="main") {
|
||||
/* In medium and large models, the segment of main may (will?) not be
|
||||
the same as the initial CS segment (of the startup code) */
|
||||
proj.m_entry_state.setState(rCS, prog.segMain);
|
||||
proj.m_entry_state.IP = prog.offMain;
|
||||
func->state = proj.m_entry_state;
|
||||
}
|
||||
if(m_name=="start") {
|
||||
proj.addCommand(new MachineStateInitialization);
|
||||
proj.addCommand(new FindMain);
|
||||
}
|
||||
|
||||
// proj.addCommand(new ProcessFunction);
|
||||
//proj.addCommand(new FollowControl());
|
||||
/* Recursively build entire procedure list */
|
||||
//proj.callGraph->proc->FollowCtrl(proj.callGraph, &proj.m_entry_state);
|
||||
return true;
|
||||
}
|
||||
49
src/FollowControlFlow.cpp
Normal file
49
src/FollowControlFlow.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "FollowControlFlow.h"
|
||||
|
||||
#include "project.h"
|
||||
#include "parser.h"
|
||||
|
||||
QString FollowControlFlow::instanceDescription() const
|
||||
{
|
||||
return name() + " @ 0x"+QString::number(m_start_state.IP,16);
|
||||
}
|
||||
|
||||
bool FollowControlFlow::execute(CommandContext *ctx)
|
||||
{
|
||||
Project &proj(*ctx->m_project);
|
||||
PtrFunction scanned_func(ctx->m_func);
|
||||
scanned_func->switchState(eDisassemblyInProgress);
|
||||
FollowCtrl(*scanned_func,proj.callGraph, &m_start_state);
|
||||
return false;
|
||||
}
|
||||
|
||||
QString MarkAsSwitchCase::instanceDescription() const
|
||||
{
|
||||
return name() + QString(" 0x%1 -> 0x%2 ; case %3")
|
||||
.arg(m_src_addr,8,16,QChar('0'))
|
||||
.arg(m_dst_addr,8,16,QChar('0'))
|
||||
.arg(m_case_label);
|
||||
|
||||
}
|
||||
|
||||
bool MarkAsSwitchCase::execute(CommandContext * ctx)
|
||||
{
|
||||
//TODO: record code/data referneces in project for navigation UI purposes ?
|
||||
auto switch_insn = ctx->m_func->Icode.labelSrch(m_src_addr);
|
||||
if(switch_insn==ctx->m_func->Icode.end()) {
|
||||
ctx->recordFailure(this,QString("switch instruction @ 0x%1 not found in procedure's instructions ?")
|
||||
.arg(m_src_addr,8,16,QChar('0')));
|
||||
return false;
|
||||
}
|
||||
auto insn = ctx->m_func->Icode.labelSrch(m_dst_addr);
|
||||
if(insn==ctx->m_func->Icode.end()) {
|
||||
ctx->recordFailure(this,QString("switch target instruction 0x%1 not found in procedure's instructions ?")
|
||||
.arg(m_dst_addr,8,16,QChar('0')));
|
||||
return false;
|
||||
}
|
||||
insn->ll()->caseEntry = m_case_label;
|
||||
insn->ll()->setFlags(CASE);
|
||||
switch_insn->ll()->caseTbl2.push_back( m_dst_addr );
|
||||
return true;
|
||||
|
||||
}
|
||||
39
src/FollowControlFlow.h
Normal file
39
src/FollowControlFlow.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef FOLLOWCONTROLFLOW_H
|
||||
#define FOLLOWCONTROLFLOW_H
|
||||
|
||||
#include "Command.h"
|
||||
|
||||
#include "state.h"
|
||||
|
||||
class FollowControlFlow : public Command
|
||||
{
|
||||
STATE m_start_state;
|
||||
public:
|
||||
FollowControlFlow(STATE addr) : Command("Follow control flow",eFunction),m_start_state(addr) {}
|
||||
|
||||
// Command interface
|
||||
public:
|
||||
QString instanceDescription() const override;
|
||||
bool execute(CommandContext *ctx) override;
|
||||
};
|
||||
// mark instruction at address m_dst_addr as a case m_case_label of switch located at m_src_addr
|
||||
class MarkAsSwitchCase : public Command
|
||||
{
|
||||
uint32_t m_src_addr;
|
||||
uint32_t m_dst_addr;
|
||||
int m_case_label;
|
||||
public:
|
||||
MarkAsSwitchCase(uint32_t src_addr,uint32_t dst_addr,int lab) :
|
||||
Command("Mark as switch case",eFunction),
|
||||
m_src_addr(src_addr),
|
||||
m_dst_addr(dst_addr),
|
||||
m_case_label(lab)
|
||||
{}
|
||||
|
||||
// Command interface
|
||||
public:
|
||||
QString instanceDescription() const override;
|
||||
bool execute(CommandContext *ctx) override;
|
||||
|
||||
};
|
||||
#endif // FOLLOWCONTROLFLOW_H
|
||||
177
src/Loaders.cpp
Normal file
177
src/Loaders.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
#include "Loaders.h"
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
|
||||
|
||||
struct PSP { /* PSP structure */
|
||||
uint16_t int20h; /* interrupt 20h */
|
||||
uint16_t eof; /* segment, end of allocation block */
|
||||
uint8_t res1; /* reserved */
|
||||
uint8_t dosDisp[5]; /* far call to DOS function dispatcher */
|
||||
uint8_t int22h[4]; /* vector for terminate routine */
|
||||
uint8_t int23h[4]; /* vector for ctrl+break routine */
|
||||
uint8_t int24h[4]; /* vector for error routine */
|
||||
uint8_t res2[22]; /* reserved */
|
||||
uint16_t segEnv; /* segment address of environment block */
|
||||
uint8_t res3[34]; /* reserved */
|
||||
uint8_t int21h[6]; /* opcode for int21h and far return */
|
||||
uint8_t res4[6]; /* reserved */
|
||||
uint8_t fcb1[16]; /* default file control block 1 */
|
||||
uint8_t fcb2[16]; /* default file control block 2 */
|
||||
uint8_t res5[4]; /* reserved */
|
||||
uint8_t cmdTail[0x80]; /* command tail and disk transfer area */
|
||||
};
|
||||
|
||||
static struct MZHeader { /* EXE file header */
|
||||
uint8_t sigLo; /* .EXE signature: 0x4D 0x5A */
|
||||
uint8_t sigHi;
|
||||
uint16_t lastPageSize; /* Size of the last page */
|
||||
uint16_t numPages; /* Number of pages in the file */
|
||||
uint16_t numReloc; /* Number of relocation items */
|
||||
uint16_t numParaHeader; /* # of paragraphs in the header*/
|
||||
uint16_t minAlloc; /* Minimum number of paragraphs */
|
||||
uint16_t maxAlloc; /* Maximum number of paragraphs */
|
||||
uint16_t initSS; /* Segment displacement of stack */
|
||||
uint16_t initSP; /* Contents of SP at entry */
|
||||
uint16_t checkSum; /* Complemented checksum */
|
||||
uint16_t initIP; /* Contents of IP at entry */
|
||||
uint16_t initCS; /* Segment displacement of code */
|
||||
uint16_t relocTabOffset; /* Relocation table offset */
|
||||
uint16_t overlayNum; /* Overlay number */
|
||||
} header;
|
||||
|
||||
void DosLoader::prepareImage(PROG & prog, size_t sz, QFile & fp) {
|
||||
/* Allocate a block of memory for the program. */
|
||||
prog.cbImage = sz + sizeof(PSP);
|
||||
prog.Imagez = new uint8_t [prog.cbImage];
|
||||
prog.Imagez[0] = 0xCD; /* Fill in PSP int 20h location */
|
||||
prog.Imagez[1] = 0x20; /* for termination checking */
|
||||
/* Read in the image past where a PSP would go */
|
||||
if (sz != fp.read((char *)prog.Imagez + sizeof(PSP),sz))
|
||||
fatalError(CANNOT_READ, fp.fileName().toLocal8Bit().data());
|
||||
}
|
||||
|
||||
bool ComLoader::canLoad(QFile & fp) {
|
||||
fp.seek(0);
|
||||
char sig[2];
|
||||
if(2==fp.read(sig,2)) {
|
||||
return not (sig[0] == 0x4D and sig[1] == 0x5A);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ComLoader::load(PROG & prog, QFile & fp) {
|
||||
prog.fCOM = true;
|
||||
fp.seek(0);
|
||||
/* COM file
|
||||
* In this case the load module size is just the file length
|
||||
*/
|
||||
auto cb = fp.size();
|
||||
|
||||
/* COM programs start off with an ORG 100H (to leave room for a PSP)
|
||||
* This is also the implied start address so if we load the image
|
||||
* at offset 100H addresses should all line up properly again.
|
||||
*/
|
||||
prog.initCS = 0;
|
||||
prog.initIP = 0x100;
|
||||
prog.initSS = 0;
|
||||
prog.initSP = 0xFFFE;
|
||||
prog.cReloc = 0;
|
||||
|
||||
prepareImage(prog,cb,fp);
|
||||
|
||||
|
||||
/* Set up memory map */
|
||||
cb = (prog.cbImage + 3) / 4;
|
||||
prog.map = (uint8_t *)malloc(cb);
|
||||
memset(prog.map, BM_UNKNOWN, (size_t)cb);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExeLoader::canLoad(QFile & fp) {
|
||||
if(fp.size()<sizeof(header))
|
||||
return false;
|
||||
MZHeader tmp_header;
|
||||
fp.seek(0);
|
||||
fp.read((char *)&tmp_header, sizeof(header));
|
||||
if(not (tmp_header.sigLo == 0x4D and tmp_header.sigHi == 0x5A))
|
||||
return false;
|
||||
|
||||
/* This is a typical DOS kludge! */
|
||||
if (LH(&header.relocTabOffset) == 0x40)
|
||||
{
|
||||
qDebug() << "Don't understand new EXE format";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExeLoader::load(PROG & prog, QFile & fp) {
|
||||
prog.fCOM = false;
|
||||
/* Read rest of header */
|
||||
fp.seek(0);
|
||||
if (fp.read((char *)&header, sizeof(header)) != sizeof(header))
|
||||
return false;
|
||||
|
||||
/* Calculate the load module size.
|
||||
* This is the number of pages in the file
|
||||
* less the length of the header and reloc table
|
||||
* less the number of bytes unused on last page
|
||||
*/
|
||||
uint32_t cb = (uint32_t)LH(&header.numPages) * 512 - (uint32_t)LH(&header.numParaHeader) * 16;
|
||||
if (header.lastPageSize)
|
||||
{
|
||||
cb -= 512 - LH(&header.lastPageSize);
|
||||
}
|
||||
|
||||
/* We quietly ignore minAlloc and maxAlloc since for our
|
||||
* purposes it doesn't really matter where in real memory
|
||||
* the program would end up. EXE programs can't really rely on
|
||||
* their load location so setting the PSP segment to 0 is fine.
|
||||
* Certainly programs that prod around in DOS or BIOS are going
|
||||
* to have to load DS from a constant so it'll be pretty
|
||||
* obvious.
|
||||
*/
|
||||
prog.initCS = (int16_t)LH(&header.initCS) + EXE_RELOCATION;
|
||||
prog.initIP = (int16_t)LH(&header.initIP);
|
||||
prog.initSS = (int16_t)LH(&header.initSS) + EXE_RELOCATION;
|
||||
prog.initSP = (int16_t)LH(&header.initSP);
|
||||
prog.cReloc = (int16_t)LH(&header.numReloc);
|
||||
|
||||
/* Allocate the relocation table */
|
||||
if (prog.cReloc)
|
||||
{
|
||||
prog.relocTable.resize(prog.cReloc);
|
||||
fp.seek(LH(&header.relocTabOffset));
|
||||
|
||||
/* Read in seg:offset pairs and convert to Image ptrs */
|
||||
uint8_t buf[4];
|
||||
for (int i = 0; i < prog.cReloc; i++)
|
||||
{
|
||||
fp.read((char *)buf,4);
|
||||
prog.relocTable[i] = LH(buf) + (((int)LH(buf+2) + EXE_RELOCATION)<<4);
|
||||
}
|
||||
}
|
||||
/* Seek to start of image */
|
||||
uint32_t start_of_image= LH(&header.numParaHeader) * 16;
|
||||
fp.seek(start_of_image);
|
||||
/* Allocate a block of memory for the program. */
|
||||
prepareImage(prog,cb,fp);
|
||||
|
||||
/* Set up memory map */
|
||||
cb = (prog.cbImage + 3) / 4;
|
||||
prog.map = (uint8_t *)malloc(cb);
|
||||
memset(prog.map, BM_UNKNOWN, (size_t)cb);
|
||||
|
||||
/* Relocate segment constants */
|
||||
for(uint32_t v : prog.relocTable) {
|
||||
uint8_t *p = &prog.Imagez[v];
|
||||
uint16_t w = (uint16_t)LH(p) + EXE_RELOCATION;
|
||||
*p++ = (uint8_t)(w & 0x00FF);
|
||||
*p = (uint8_t)((w & 0xFF00) >> 8);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
31
src/Loaders.h
Normal file
31
src/Loaders.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef LOADERS_H
|
||||
#define LOADERS_H
|
||||
|
||||
#include "BinaryImage.h"
|
||||
#include <QtCore/QFile>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct DosLoader {
|
||||
protected:
|
||||
void prepareImage(PROG &prog,size_t sz,QFile &fp);
|
||||
public:
|
||||
virtual bool canLoad(QFile &fp)=0;
|
||||
virtual QString loaderName() const =0;
|
||||
virtual bool load(PROG &prog,QFile &fp)=0;
|
||||
};
|
||||
struct ComLoader : public DosLoader {
|
||||
virtual ~ComLoader() {}
|
||||
|
||||
bool canLoad(QFile &fp) override;
|
||||
bool load(PROG &prog,QFile &fp) override;
|
||||
QString loaderName() const override { return "16-bit DOS - COM loader"; }
|
||||
};
|
||||
struct ExeLoader : public DosLoader {
|
||||
virtual ~ExeLoader() {}
|
||||
|
||||
bool canLoad(QFile &fp) override;
|
||||
bool load(PROG &prog,QFile &fp) override;
|
||||
QString loaderName() const override { return "16-bit DOS - EXE loader"; }
|
||||
};
|
||||
|
||||
#endif // LOADERS_H
|
||||
22
src/MemoryChunk.cpp
Normal file
22
src/MemoryChunk.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "MemoryChunk.h"
|
||||
|
||||
#include <boost/icl/interval.hpp>
|
||||
#include <boost/icl/right_open_interval.hpp>
|
||||
#include <boost/icl/left_open_interval.hpp>
|
||||
#include <boost/icl/closed_interval.hpp>
|
||||
#include <boost/icl/open_interval.hpp>
|
||||
|
||||
using namespace boost::icl;
|
||||
MemoryChunk::MemoryChunk(LinearAddress start, LinearAddress fin) : m_start(start),m_fin(fin)
|
||||
{
|
||||
}
|
||||
|
||||
bool MemoryChunk::contains(LinearAddress addr) const
|
||||
{
|
||||
return addr>=m_start && addr<m_fin;
|
||||
}
|
||||
|
||||
uint64_t MemoryChunk::size() const
|
||||
{
|
||||
return m_fin-m_start;
|
||||
}
|
||||
24
src/MemoryChunk.h
Normal file
24
src/MemoryChunk.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef BYTECHUNK_H
|
||||
#define BYTECHUNK_H
|
||||
|
||||
#include "Address.h"
|
||||
|
||||
#include <utility>
|
||||
#include <inttypes.h>
|
||||
/**
|
||||
* @brief The MemoryChunk class represents a continuous range of Addresses
|
||||
*/
|
||||
class MemoryChunk
|
||||
{
|
||||
private:
|
||||
LinearAddress m_start;
|
||||
LinearAddress m_fin;
|
||||
public:
|
||||
MemoryChunk(LinearAddress start,LinearAddress fin);
|
||||
bool contains(LinearAddress addr) const;
|
||||
uint64_t size() const;
|
||||
|
||||
std::pair<LinearAddress,LinearAddress> bounds() const { return std::make_pair(m_start,m_fin); }
|
||||
};
|
||||
|
||||
#endif // BYTECHUNK_H
|
||||
5
src/MemorySegment.cpp
Normal file
5
src/MemorySegment.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "MemorySegment.h"
|
||||
|
||||
MemorySegment::MemorySegment(LinearAddress base, LinearAddress start, LinearAddress fin) : MemoryChunk(start,fin) {
|
||||
m_base = base;
|
||||
}
|
||||
19
src/MemorySegment.h
Normal file
19
src/MemorySegment.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "MemoryChunk.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
/**
|
||||
* @brief The MemorySegment represents a single chunk of memory with additional properties.
|
||||
*/
|
||||
class MemorySegment : public MemoryChunk
|
||||
{
|
||||
uint16_t m_base;
|
||||
int m_flags;
|
||||
QString m_name;
|
||||
public:
|
||||
MemorySegment(LinearAddress base,LinearAddress start,LinearAddress fin);
|
||||
const QString &getName() const { return m_name; }
|
||||
void setName(const QString &v) { m_name = v; }
|
||||
};
|
||||
|
||||
54
src/MemorySegmentCoordinator.cpp
Normal file
54
src/MemorySegmentCoordinator.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "MemorySegmentCoordinator.h"
|
||||
|
||||
#include <boost/icl/interval_map.hpp>
|
||||
#include <boost/icl/split_interval_map.hpp>
|
||||
#include <utility>
|
||||
using namespace boost::icl;
|
||||
class MemorySegmentCoordinatorImpl {
|
||||
boost::icl::interval_map<LinearAddress,SegmentHolder> m_segmentation_map;
|
||||
public:
|
||||
bool addSegment(LinearAddress base, LinearAddress start, LinearAddress fin, const char * name, int flags) {
|
||||
if(start>fin)
|
||||
return false;
|
||||
if(start<base)
|
||||
return false;
|
||||
MemorySegment *seg = new MemorySegment(base,start,fin);
|
||||
seg->setName(name);
|
||||
//
|
||||
auto segment_bounds(seg->bounds());
|
||||
m_segmentation_map.add(std::make_pair(
|
||||
interval<LinearAddress>::right_open(segment_bounds.first,segment_bounds.second),
|
||||
seg)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
uint32_t numberOfSegments() const { return interval_count(m_segmentation_map); }
|
||||
const MemorySegment *get(LinearAddress addr) {
|
||||
auto iter = m_segmentation_map.find(addr);
|
||||
if(iter==m_segmentation_map.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return iter->second;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
MemorySegmentCoordinator::MemorySegmentCoordinator()
|
||||
{
|
||||
m_impl = new MemorySegmentCoordinatorImpl;
|
||||
}
|
||||
|
||||
bool MemorySegmentCoordinator::addSegment(LinearAddress base, LinearAddress start, LinearAddress fin, const char * name, int flags)
|
||||
{
|
||||
return m_impl->addSegment(base,start,fin,name,flags);
|
||||
}
|
||||
|
||||
uint32_t MemorySegmentCoordinator::size()
|
||||
{
|
||||
return m_impl->numberOfSegments();
|
||||
}
|
||||
|
||||
MemorySegment *MemorySegmentCoordinator::getSegment(LinearAddress addr)
|
||||
{
|
||||
return const_cast<MemorySegment *>(m_impl->get(addr));
|
||||
}
|
||||
34
src/MemorySegmentCoordinator.h
Normal file
34
src/MemorySegmentCoordinator.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "MemorySegment.h"
|
||||
|
||||
struct SegmentHolder {
|
||||
SegmentHolder() : val(nullptr) {}
|
||||
SegmentHolder(MemorySegment *inf) : val(inf) {}
|
||||
|
||||
MemorySegment *operator->() { return val;}
|
||||
MemorySegment &operator*() const { return *val;}
|
||||
operator MemorySegment *() { return val;}
|
||||
operator const MemorySegment *() const { return val;}
|
||||
SegmentHolder operator+=(const SegmentHolder &/*s*/) {
|
||||
throw std::runtime_error("Cannot aggregate MemorySegments !");
|
||||
}
|
||||
|
||||
MemorySegment *val;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The MemorySegmentCoordinator class is responsible for:
|
||||
* - Managing the lifetime of MemorySegments
|
||||
* - Providing convenience functions for querying the segment-related data
|
||||
*/
|
||||
class MemorySegmentCoordinator
|
||||
{
|
||||
class MemorySegmentCoordinatorImpl *m_impl;
|
||||
public:
|
||||
MemorySegmentCoordinator();
|
||||
|
||||
bool addSegment(LinearAddress base,LinearAddress start,LinearAddress fin,const char *name,int flags);
|
||||
uint32_t size();
|
||||
MemorySegment *getSegment(LinearAddress addr);
|
||||
};
|
||||
@@ -1,6 +1,12 @@
|
||||
#include "Procedure.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "project.h"
|
||||
#include "scanner.h"
|
||||
#include "ui/StructuredTextTarget.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
//FunctionType *Function::getFunctionType() const
|
||||
//{
|
||||
// return &m_type;
|
||||
@@ -15,7 +21,7 @@ void JumpTable::pruneEntries(uint16_t cs)
|
||||
for (uint32_t i = start; i < finish; i += 2)
|
||||
{
|
||||
uint32_t target = cs + LH(&prg->image()[i]);
|
||||
if (target < finish && target >= start)
|
||||
if (target < finish and target >= start)
|
||||
finish = target;
|
||||
else if (target >= (uint32_t)prg->cbImage)
|
||||
finish = i;
|
||||
@@ -25,13 +31,107 @@ void JumpTable::pruneEntries(uint16_t cs)
|
||||
{
|
||||
uint32_t target = cs + LH(&prg->image()[i]);
|
||||
/* Be wary of 00 00 as code - it's probably data */
|
||||
if (! (prg->image()[target] || prg->image()[target+1]) || scan(target, _Icode))
|
||||
if (not (prg->image()[target] or prg->image()[target+1]) or scan(target, _Icode))
|
||||
finish = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Function::callingConv(CConv::Type v) {
|
||||
m_call_conv=CConv::create(v);
|
||||
void Function::callingConv(CConv::CC_Type v) {
|
||||
type->setCallingConvention(v);
|
||||
getFunctionType()->m_call_conv->calculateStackLayout(this);
|
||||
}
|
||||
static QString sizeToPtrName(int size)
|
||||
{
|
||||
switch(size)
|
||||
{
|
||||
case 1:
|
||||
return "BYTE ptr" ;
|
||||
case 2:
|
||||
return "WORD ptr";
|
||||
case 4:
|
||||
return "DWORD ptr";
|
||||
}
|
||||
return "UNKOWN ptr";
|
||||
}
|
||||
static void toStructuredText(STKFRAME &stk,IStructuredTextTarget *out, int level) {
|
||||
int curlevel = 0;
|
||||
int maxlevel = stk.m_maxOff - stk.m_minOff;
|
||||
|
||||
for(STKSYM & p : stk)
|
||||
{
|
||||
if (curlevel > p.label)
|
||||
{
|
||||
qWarning() << "error, var collapse!!!";
|
||||
curlevel = p.label;
|
||||
}
|
||||
else if (curlevel < p.label)
|
||||
{
|
||||
out->addSpace(4);
|
||||
out->prtt(QString("gap len = %1").arg(p.label - curlevel,0,16));
|
||||
curlevel = p.label;
|
||||
out->addEOL();
|
||||
}
|
||||
out->addSpace(4);
|
||||
out->addTaggedString(XT_Symbol,p.name,&p);
|
||||
out->prtt("equ");
|
||||
out->addSpace();
|
||||
out->prtt(sizeToPtrName(p.size));
|
||||
out->addSpace();
|
||||
if (p.arrayMembers>1)
|
||||
{
|
||||
out->addTaggedString(XT_Number,QString::number(p.arrayMembers,16));
|
||||
out->prtt("dup (?)");
|
||||
out->addSpace();
|
||||
}
|
||||
out->TAGbegin(XT_Number, NULL);
|
||||
out->prtt(QString("%1h").arg(p.label,0,16));
|
||||
out->TAGend(XT_Number);
|
||||
out->addEOL();
|
||||
|
||||
curlevel += p.size * p.arrayMembers;
|
||||
}
|
||||
|
||||
if (curlevel < maxlevel)
|
||||
{
|
||||
out->prtt(QString(" gap len = %1h").arg(maxlevel - curlevel,0,16));
|
||||
}
|
||||
}
|
||||
extern void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level);
|
||||
|
||||
static void toStructuredText(ICODE &stk,IStructuredTextTarget *out, int level) {
|
||||
if(level==0) {
|
||||
toStructuredText(stk.ll(),out,level);
|
||||
}
|
||||
}
|
||||
|
||||
void Function::toStructuredText(IStructuredTextTarget *out, int level)
|
||||
{
|
||||
|
||||
out->TAGbegin(XT_Function, this);
|
||||
out->addTaggedString(XT_FuncName,name);
|
||||
out->prtt(" proc");
|
||||
out->addEOL();
|
||||
::toStructuredText(args,out,level);
|
||||
out->addEOL();
|
||||
for(ICODE &ic : Icode) {
|
||||
::toStructuredText(ic,out,level);
|
||||
}
|
||||
|
||||
out->addTaggedString(XT_FuncName,name);
|
||||
out->addSpace();
|
||||
out->prtt("endp");
|
||||
out->addEOL();
|
||||
out->TAGend(XT_Function);
|
||||
}
|
||||
|
||||
void FunctionType::setCallingConvention(CConv::CC_Type cc)
|
||||
{
|
||||
m_call_conv=CConv::create(cc);
|
||||
assert(m_call_conv);
|
||||
}
|
||||
void Function::switchState(DecompilationStep s)
|
||||
{
|
||||
nStep = s;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
#include "types.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "ast.h"
|
||||
#include "bundle.h"
|
||||
#include "machine_x86.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
//#include <boost/range/algorithm.hpp>
|
||||
//#include <boost/assign.hpp>
|
||||
|
||||
#include "types.h"
|
||||
#include "ast.h"
|
||||
#include "bundle.h"
|
||||
|
||||
#include "machine_x86.h"
|
||||
#include "project.h"
|
||||
using namespace std;
|
||||
using namespace boost::adaptors;
|
||||
RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym)
|
||||
@@ -41,7 +42,7 @@ RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym)
|
||||
// ident.type(REGISTER);
|
||||
// hlType type_sel;
|
||||
// regType reg_type;
|
||||
// if ((icodeFlg & B) || (icodeFlg & SRC_B))
|
||||
// if ((icodeFlg & B) or (icodeFlg & SRC_B))
|
||||
// {
|
||||
// type_sel = TYPE_BYTE_SIGN;
|
||||
// reg_type = BYTE_REG;
|
||||
@@ -55,42 +56,42 @@ RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym)
|
||||
// regiType = reg_type;
|
||||
//}
|
||||
|
||||
string RegisterNode::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
QString RegisterNode::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
{
|
||||
std::ostringstream codeOut;
|
||||
QString codeOut;
|
||||
|
||||
std::ostringstream o;
|
||||
QString o;
|
||||
assert(&pProc->localId==m_syms);
|
||||
ID *id = &pProc->localId.id_arr[regiIdx];
|
||||
if (id->name[0] == '\0') /* no name */
|
||||
if (id->name[0] == '\0') /* no name */
|
||||
{
|
||||
id->setLocalName(++(*numLoc));
|
||||
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; ";
|
||||
codeOut <<"/* "<<Machine_X86::regName(id->id.regi)<<" */\n";
|
||||
codeOut += QString("%1 %2; ").arg(TypeContainer::typeName(id->type)).arg(id->name);
|
||||
codeOut += QString("/* %1 */\n").arg(Machine_X86::regName(id->id.regi));
|
||||
}
|
||||
if (id->hasMacro)
|
||||
o << id->macro << "("<<id->name<<")";
|
||||
o += QString("%1(%2)").arg(id->macro).arg(id->name);
|
||||
else
|
||||
o << id->name;
|
||||
o += id->name;
|
||||
|
||||
cCode.appendDecl(codeOut.str());
|
||||
return o.str();
|
||||
cCode.appendDecl(codeOut);
|
||||
return o;
|
||||
}
|
||||
|
||||
int RegisterNode::hlTypeSize(Function *) const
|
||||
{
|
||||
if (regiType == BYTE_REG)
|
||||
return (1);
|
||||
return 1;
|
||||
else
|
||||
return (2);
|
||||
return 2;
|
||||
}
|
||||
|
||||
hlType RegisterNode::expType(Function *pproc) const
|
||||
{
|
||||
if (regiType == BYTE_REG)
|
||||
return (TYPE_BYTE_SIGN);
|
||||
return TYPE_BYTE_SIGN;
|
||||
else
|
||||
return (TYPE_WORD_SIGN);
|
||||
return TYPE_WORD_SIGN;
|
||||
}
|
||||
|
||||
Expr *RegisterNode::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)
|
||||
|
||||
557
src/ast.cpp
557
src/ast.cpp
@@ -4,29 +4,32 @@
|
||||
* Date: September 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#include "ast.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "types.h"
|
||||
#include "bundle.h"
|
||||
#include "machine_x86.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <QtCore/QTextStream>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
#include "types.h"
|
||||
#include "ast.h"
|
||||
#include "bundle.h"
|
||||
#include "machine_x86.h"
|
||||
#include "project.h"
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
using namespace boost::adaptors;
|
||||
|
||||
extern int strSize (const uint8_t *, char);
|
||||
extern char *cChar(uint8_t c);
|
||||
|
||||
|
||||
|
||||
// Conditional operator symbols in C. Index by condOp enumeration type
|
||||
static const char * const condOpSym[] = { " <= ", " < ", " == ", " != ", " > ", " >= ",
|
||||
" & ", " | ", " ^ ", " ~ ",
|
||||
@@ -59,19 +62,19 @@ void ICODE::setRegDU (eReg regi, operDu du_in)
|
||||
}
|
||||
switch (du_in)
|
||||
{
|
||||
case eDEF:
|
||||
du.def.addReg(regi);
|
||||
du1.addDef(regi);
|
||||
break;
|
||||
case eUSE:
|
||||
du.use.addReg(regi);
|
||||
break;
|
||||
case USE_DEF:
|
||||
du.addDefinedAndUsed(regi);
|
||||
du1.addDef(regi);
|
||||
break;
|
||||
case NONE: /* do nothing */
|
||||
break;
|
||||
case eDEF:
|
||||
du.def.addReg(regi);
|
||||
du1.addDef(regi);
|
||||
break;
|
||||
case eUSE:
|
||||
du.use.addReg(regi);
|
||||
break;
|
||||
case USE_DEF:
|
||||
du.addDefinedAndUsed(regi);
|
||||
du1.addDef(regi);
|
||||
break;
|
||||
case NONE: /* do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,24 +84,24 @@ void ICODE::copyDU(const ICODE &duIcode, operDu _du, operDu duDu)
|
||||
{
|
||||
switch (_du)
|
||||
{
|
||||
case eDEF:
|
||||
if (duDu == eDEF)
|
||||
du.def=duIcode.du.def;
|
||||
else
|
||||
du.def=duIcode.du.use;
|
||||
break;
|
||||
case eUSE:
|
||||
if (duDu == eDEF)
|
||||
du.use = duIcode.du.def;
|
||||
else
|
||||
du.use = duIcode.du.use;
|
||||
break;
|
||||
case USE_DEF:
|
||||
du = duIcode.du;
|
||||
break;
|
||||
case NONE:
|
||||
assert(false);
|
||||
break;
|
||||
case eDEF:
|
||||
if (duDu == eDEF)
|
||||
du.def=duIcode.du.def;
|
||||
else
|
||||
du.def=duIcode.du.use;
|
||||
break;
|
||||
case eUSE:
|
||||
if (duDu == eDEF)
|
||||
du.use = duIcode.du.def;
|
||||
else
|
||||
du.use = duIcode.du.use;
|
||||
break;
|
||||
case USE_DEF:
|
||||
du = duIcode.du;
|
||||
break;
|
||||
case NONE:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +114,7 @@ void ICODE::copyDU(const ICODE &duIcode, operDu _du, operDu duDu)
|
||||
|
||||
/* Returns a unary conditional expression node. This procedure should
|
||||
* only be used with the following conditional node types: NEGATION,
|
||||
* ADDRESSOF, DEREFERENCE, POST_INC, POST_DEC, PRE_INC, PRE_DEC */
|
||||
* ADDRESSOF, DEREFERENCE, POST_INC, POST_DEC, PRE_INC, PRE_DEC */
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type GLOB_VAR */
|
||||
@@ -130,7 +133,7 @@ GlobalVariable::GlobalVariable(int16_t segValue, int16_t off)
|
||||
globIdx = i;
|
||||
}
|
||||
|
||||
string GlobalVariable::walkCondExpr(Function *, int *) const
|
||||
QString GlobalVariable::walkCondExpr(Function *, int *) const
|
||||
{
|
||||
if(valid)
|
||||
return Project::get()->symtab[globIdx].name;
|
||||
@@ -146,7 +149,7 @@ AstIdent *AstIdent::Loc(int off, LOCAL_ID *localId)
|
||||
for (i = 0; i < localId->csym(); i++)
|
||||
{
|
||||
const ID &lID(localId->id_arr[i]);
|
||||
if ((lID.id.bwId.off == off) && (lID.id.bwId.regOff == 0))
|
||||
if ((lID.id.bwId.off == off) and (lID.id.bwId.regOff == 0))
|
||||
break;
|
||||
}
|
||||
if (i == localId->csym())
|
||||
@@ -181,19 +184,17 @@ GlobalVariableIdx::GlobalVariableIdx (int16_t segValue, int16_t off, uint8_t reg
|
||||
for (i = 0; i < locSym->csym(); i++)
|
||||
{
|
||||
const BWGLB_TYPE &lID(locSym->id_arr[i].id.bwGlb);
|
||||
if ((lID.seg == segValue) && (lID.off == off) && (lID.regi == regi))
|
||||
if ((lID.seg == segValue) and (lID.off == off) and (lID.regi == regi))
|
||||
break;
|
||||
}
|
||||
if (i == locSym->csym())
|
||||
printf ("Error, indexed-glob var not found in local id table\n");
|
||||
idxGlbIdx = i;
|
||||
}
|
||||
string GlobalVariableIdx::walkCondExpr(Function *pProc, int *) const
|
||||
QString GlobalVariableIdx::walkCondExpr(Function *pProc, int *) const
|
||||
{
|
||||
ostringstream o;
|
||||
auto bwGlb = &pProc->localId.id_arr[idxGlbIdx].id.bwGlb;
|
||||
o << (bwGlb->seg << 4) + bwGlb->off << "["<<Machine_X86::regName(bwGlb->regi)<<"]";
|
||||
return o.str();
|
||||
return QString("%1[%2]").arg((bwGlb->seg << 4) + bwGlb->off).arg(Machine_X86::regName(bwGlb->regi));
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +222,7 @@ AstIdent *AstIdent::Long(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f,
|
||||
{
|
||||
AstIdent *newExp;
|
||||
/* Check for long constant and save it as a constant expression */
|
||||
if ((sd == SRC) && pIcode->ll()->testFlags(I)) /* constant */
|
||||
if ((sd == SRC) and pIcode->ll()->srcIsImmed()) /* constant */
|
||||
{
|
||||
int value;
|
||||
if (f == HIGH_FIRST)
|
||||
@@ -255,29 +256,29 @@ AstIdent *AstIdent::Other(eReg seg, eReg regi, int16_t off)
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type TYPE_LONG or
|
||||
* TYPE_WORD_SIGN */
|
||||
* TYPE_WORD_SIGN */
|
||||
AstIdent *AstIdent::idID (const ID *retVal, LOCAL_ID *locsym, iICODE ix_)
|
||||
{
|
||||
int idx;
|
||||
AstIdent *newExp=nullptr;
|
||||
switch(retVal->type)
|
||||
{
|
||||
case TYPE_LONG_SIGN:
|
||||
{
|
||||
newExp = new AstIdent();
|
||||
idx = locsym->newLongReg (TYPE_LONG_SIGN, retVal->longId(), ix_);
|
||||
newExp->ident.idType = LONG_VAR;
|
||||
newExp->ident.idNode.longIdx = idx;
|
||||
break;
|
||||
}
|
||||
case TYPE_WORD_SIGN:
|
||||
newExp = new RegisterNode(locsym->newByteWordReg(retVal->type, retVal->id.regi),WORD_REG,locsym);
|
||||
break;
|
||||
case TYPE_BYTE_SIGN:
|
||||
newExp = new RegisterNode(locsym->newByteWordReg(retVal->type, retVal->id.regi),BYTE_REG,locsym);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"AstIdent::idID unhandled type %d\n",retVal->type);
|
||||
case TYPE_LONG_SIGN:
|
||||
{
|
||||
newExp = new AstIdent();
|
||||
idx = locsym->newLongReg (TYPE_LONG_SIGN, retVal->longId(), ix_);
|
||||
newExp->ident.idType = LONG_VAR;
|
||||
newExp->ident.idNode.longIdx = idx;
|
||||
break;
|
||||
}
|
||||
case TYPE_WORD_SIGN:
|
||||
newExp = new RegisterNode(locsym->newByteWordReg(retVal->type, retVal->id.regi),WORD_REG,locsym);
|
||||
break;
|
||||
case TYPE_BYTE_SIGN:
|
||||
newExp = new RegisterNode(locsym->newByteWordReg(retVal->type, retVal->id.regi),BYTE_REG,locsym);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"AstIdent::idID unhandled type %d\n",retVal->type);
|
||||
}
|
||||
return (newExp);
|
||||
}
|
||||
@@ -296,8 +297,8 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
|
||||
|
||||
const LLOperand &pm(*ll_insn.get(sd));
|
||||
|
||||
if ( ((sd == DST) && ll_insn.testFlags(IM_DST)) or
|
||||
((sd == SRC) && ll_insn.testFlags(IM_SRC)) or
|
||||
if ( ((sd == DST) and ll_insn.testFlags(IM_DST)) or
|
||||
((sd == SRC) and ll_insn.testFlags(IM_SRC)) or
|
||||
(sd == LHS_OP)) /* for MUL lhs */
|
||||
{ /* implicit dx:ax */
|
||||
idx = pProc->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(rDX, rAX), ix_);
|
||||
@@ -306,13 +307,13 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
|
||||
duIcode.setRegDU (rAX, du);
|
||||
}
|
||||
|
||||
else if ((sd == DST) && ll_insn.testFlags(IM_TMP_DST))
|
||||
else if ((sd == DST) and ll_insn.testFlags(IM_TMP_DST))
|
||||
{ /* implicit tmp */
|
||||
newExp = new RegisterNode(LLOperand(rTMP,2), &pProc->localId);
|
||||
duIcode.setRegDU(rTMP, (operDu)eUSE);
|
||||
}
|
||||
|
||||
else if ((sd == SRC) && ll_insn.testFlags(I)) /* constant */
|
||||
else if ((sd == SRC) and ll_insn.srcIsImmed()) /* constant */
|
||||
newExp = new Constant(ll_insn.src().getImm2(), 2);
|
||||
else if (pm.regi == rUNDEF) /* global variable */
|
||||
newExp = new GlobalVariable(pm.segValue, pm.off);
|
||||
@@ -325,14 +326,14 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
|
||||
|
||||
else if (pm.off) /* offset */
|
||||
{ // TODO: this is ABI specific, should be actually based on Function calling conv
|
||||
if ((pm.seg == rSS) && (pm.regi == INDEX_BP)) /* idx on bp */
|
||||
if ((pm.seg == rSS) and (pm.regi == INDEX_BP)) /* idx on bp */
|
||||
{
|
||||
if (pm.off >= 0) /* argument */
|
||||
newExp = AstIdent::Param (pm.off, &pProc->args);
|
||||
else /* local variable */
|
||||
newExp = AstIdent::Loc (pm.off, &pProc->localId);
|
||||
}
|
||||
else if ((pm.seg == rDS) && (pm.regi == INDEX_BX)) /* bx */
|
||||
else if ((pm.seg == rDS) and (pm.regi == INDEX_BX)) /* bx */
|
||||
{
|
||||
if (pm.off > 0) /* global variable */
|
||||
newExp = new GlobalVariableIdx(pm.segValue, pm.off, rBX,&pProc->localId);
|
||||
@@ -345,19 +346,19 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
|
||||
/**** check long ops, indexed global var *****/
|
||||
}
|
||||
|
||||
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */
|
||||
else /* (pm->regi >= INDEXBASE and pm->off = 0) => indexed and no off */
|
||||
{
|
||||
if ((pm.seg == rDS) && (pm.regi > INDEX_BP_DI)) /* dereference */
|
||||
if ((pm.seg == rDS) and (pm.regi > INDEX_BP_DI)) /* dereference */
|
||||
{
|
||||
eReg selected;
|
||||
switch (pm.regi) {
|
||||
case INDEX_SI: selected = rSI; break;
|
||||
case INDEX_DI: selected = rDI; break;
|
||||
case INDEX_BP: selected = rBP; break;
|
||||
case INDEX_BX: selected = rBX; break;
|
||||
default:
|
||||
newExp = nullptr;
|
||||
assert(false);
|
||||
case INDEX_SI: selected = rSI; break;
|
||||
case INDEX_DI: selected = rDI; break;
|
||||
case INDEX_BP: selected = rBP; break;
|
||||
case INDEX_BX: selected = rBX; break;
|
||||
default:
|
||||
newExp = nullptr;
|
||||
assert(false);
|
||||
}
|
||||
//NOTICE: was selected, 0
|
||||
newExp = new RegisterNode(LLOperand(selected, 0), &pProc->localId);
|
||||
@@ -376,13 +377,13 @@ condId LLInst::idType(opLoc sd) const
|
||||
{
|
||||
const LLOperand &pm((sd == SRC) ? src() : m_dst);
|
||||
|
||||
if ((sd == SRC) && testFlags(I))
|
||||
if ((sd == SRC) and srcIsImmed())
|
||||
return (CONSTANT);
|
||||
else if (pm.regi == 0)
|
||||
return (GLOB_VAR);
|
||||
else if ( pm.isReg() )
|
||||
return (REGISTER);
|
||||
else if ((pm.seg == rSS) && (pm.regi == INDEX_BP))
|
||||
else if ((pm.seg == rSS) and (pm.regi == INDEX_BP))
|
||||
{
|
||||
//TODO: which pm.seg/pm.regi pairs should produce PARAM/LOCAL_VAR ?
|
||||
if (pm.off >= 0)
|
||||
@@ -401,9 +402,9 @@ int hlSize[] = {2, 1, 1, 2, 2, 4, 4, 4, 2, 2, 1, 4, 4};
|
||||
int Expr::hlTypeSize(Function * pproc) const
|
||||
{
|
||||
if (this == nullptr)
|
||||
return (2); /* for TYPE_UNKNOWN */
|
||||
return (2); /* for TYPE_UNKNOWN */
|
||||
fprintf(stderr,"hlTypeSize queried for Unkown type %d \n",m_type);
|
||||
return 2; // CC: is this correct?
|
||||
return 2; // CC: is this correct?
|
||||
}
|
||||
|
||||
/* Returns the type of the expression */
|
||||
@@ -428,22 +429,22 @@ int AstIdent::hlTypeSize(Function *pproc) const
|
||||
{
|
||||
switch (ident.idType)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
assert(false);
|
||||
return 1;
|
||||
case LOCAL_VAR:
|
||||
return (hlSize[pproc->localId.id_arr[ident.idNode.localIdx].type]);
|
||||
case PARAM:
|
||||
return (hlSize[pproc->args[ident.idNode.paramIdx].type]);
|
||||
case STRING:
|
||||
return (2);
|
||||
case LONG_VAR:
|
||||
return (4);
|
||||
case OTHER:
|
||||
return (2);
|
||||
default:
|
||||
assert(false);
|
||||
return -1;
|
||||
case GLOB_VAR:
|
||||
assert(false);
|
||||
return 1;
|
||||
case LOCAL_VAR:
|
||||
return (hlSize[pproc->localId.id_arr[ident.idNode.localIdx].type]);
|
||||
case PARAM:
|
||||
return (hlSize[pproc->args[ident.idNode.paramIdx].type]);
|
||||
case STRING:
|
||||
return (2);
|
||||
case LONG_VAR:
|
||||
return (4);
|
||||
case OTHER:
|
||||
return (2);
|
||||
default:
|
||||
assert(false);
|
||||
return -1;
|
||||
} /* eos */
|
||||
}
|
||||
hlType BinaryOperator::expType(Function *pproc) const
|
||||
@@ -477,24 +478,24 @@ hlType AstIdent::expType(Function *pproc) const
|
||||
{
|
||||
switch (ident.idType)
|
||||
{
|
||||
case UNDEF:
|
||||
case CONSTANT:
|
||||
case FUNCTION:
|
||||
case REGISTER:
|
||||
case GLOB_VAR:
|
||||
case GLOB_VAR_IDX:
|
||||
assert(false);
|
||||
return TYPE_UNKNOWN;
|
||||
case LOCAL_VAR:
|
||||
return (pproc->localId.id_arr[ident.idNode.localIdx].type);
|
||||
case PARAM:
|
||||
return (pproc->args[ident.idNode.paramIdx].type);
|
||||
case STRING:
|
||||
return (TYPE_STR);
|
||||
case LONG_VAR:
|
||||
return (pproc->localId.id_arr[ident.idNode.longIdx].type);
|
||||
default:
|
||||
return (TYPE_UNKNOWN);
|
||||
case UNDEF:
|
||||
case CONSTANT:
|
||||
case FUNCTION:
|
||||
case REGISTER:
|
||||
case GLOB_VAR:
|
||||
case GLOB_VAR_IDX:
|
||||
assert(false);
|
||||
return TYPE_UNKNOWN;
|
||||
case LOCAL_VAR:
|
||||
return (pproc->localId.id_arr[ident.idNode.localIdx].type);
|
||||
case PARAM:
|
||||
return (pproc->args[ident.idNode.paramIdx].type);
|
||||
case STRING:
|
||||
return (TYPE_STR);
|
||||
case LONG_VAR:
|
||||
return (pproc->localId.id_arr[ident.idNode.longIdx].type);
|
||||
default:
|
||||
return (TYPE_UNKNOWN);
|
||||
} /* eos */
|
||||
return (TYPE_UNKNOWN);
|
||||
}
|
||||
@@ -507,177 +508,159 @@ hlType AstIdent::expType(Function *pproc) const
|
||||
Expr * HlTypeSupport::performLongRemoval (eReg regi, LOCAL_ID *locId, Expr *tree)
|
||||
{
|
||||
switch (tree->m_type) {
|
||||
case BOOLEAN_OP:
|
||||
case POST_INC: case POST_DEC:
|
||||
case PRE_INC: case PRE_DEC:
|
||||
case NEGATION: case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
case IDENTIFIER:
|
||||
return tree->performLongRemoval(regi,locId);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"performLongRemoval attemped on %d\n",tree->m_type);
|
||||
break;
|
||||
case BOOLEAN_OP:
|
||||
case POST_INC: case POST_DEC:
|
||||
case PRE_INC: case PRE_DEC:
|
||||
case NEGATION: case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
case IDENTIFIER:
|
||||
return tree->performLongRemoval(regi,locId);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"performLongRemoval attemped on %d\n",tree->m_type);
|
||||
break;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* Returns the string located in image, formatted in C format. */
|
||||
static std::string getString (int offset)
|
||||
static QString getString (int offset)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
ostringstream o;
|
||||
QString o;
|
||||
int strLen, i;
|
||||
|
||||
strLen = strSize (&prog.image()[offset], '\0');
|
||||
o << '"';
|
||||
o += '"';
|
||||
for (i = 0; i < strLen; i++)
|
||||
o<<cChar(prog.image()[offset+i]);
|
||||
o << "\"\0";
|
||||
return (o.str());
|
||||
o += cChar(prog.image()[offset+i]);
|
||||
o += "\"\0";
|
||||
return o;
|
||||
}
|
||||
string BinaryOperator::walkCondExpr(Function * pProc, int* numLoc) const
|
||||
QString BinaryOperator::walkCondExpr(Function * pProc, int* numLoc) const
|
||||
{
|
||||
std::ostringstream outStr;
|
||||
outStr << "(";
|
||||
if(m_op!=NOT)
|
||||
{
|
||||
outStr << lhs()->walkCondExpr(pProc, numLoc);
|
||||
}
|
||||
assert(rhs());
|
||||
outStr << condOpSym[m_op];
|
||||
outStr << rhs()->walkCondExpr(pProc, numLoc);
|
||||
outStr << ")";
|
||||
return outStr.str();
|
||||
|
||||
return QString("(%1%2%3)")
|
||||
.arg((m_op!=NOT) ? lhs()->walkCondExpr(pProc, numLoc) : "")
|
||||
.arg(condOpSym[m_op])
|
||||
.arg(rhs()->walkCondExpr(pProc, numLoc));
|
||||
}
|
||||
string AstIdent::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
QString AstIdent::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
{
|
||||
int16_t off; /* temporal - for OTHER */
|
||||
ID* id; /* Pointer to local identifier table */
|
||||
BWGLB_TYPE* bwGlb; /* Ptr to BWGLB_TYPE (global indexed var) */
|
||||
STKSYM * psym; /* Pointer to argument in the stack */
|
||||
std::ostringstream outStr,codeOut;
|
||||
QString codeContents;
|
||||
QString collectedContents;
|
||||
|
||||
QTextStream codeOut(&codeContents);
|
||||
QTextStream o(&collectedContents);
|
||||
|
||||
std::ostringstream o;
|
||||
switch (ident.idType)
|
||||
{
|
||||
case LOCAL_VAR:
|
||||
o << pProc->localId.id_arr[ident.idNode.localIdx].name;
|
||||
break;
|
||||
case LOCAL_VAR:
|
||||
o << pProc->localId.id_arr[ident.idNode.localIdx].name;
|
||||
break;
|
||||
|
||||
case PARAM:
|
||||
psym = &pProc->args[ident.idNode.paramIdx];
|
||||
if (psym->hasMacro)
|
||||
o << psym->macro<<"("<<psym->name<< ")";
|
||||
else
|
||||
o << psym->name;
|
||||
break;
|
||||
case STRING:
|
||||
o << getString (ident.idNode.strIdx);
|
||||
break;
|
||||
case PARAM:
|
||||
psym = &pProc->args[ident.idNode.paramIdx];
|
||||
if (psym->hasMacro)
|
||||
o << psym->macro<<"("<<psym->name<< ")";
|
||||
else
|
||||
o << psym->name;
|
||||
break;
|
||||
case STRING:
|
||||
o << getString (ident.idNode.strIdx);
|
||||
break;
|
||||
|
||||
case LONG_VAR:
|
||||
id = &pProc->localId.id_arr[ident.idNode.longIdx];
|
||||
if (id->name[0] != '\0') /* STK_FRAME & REG w/name*/
|
||||
o << id->name;
|
||||
else if (id->loc == REG_FRAME)
|
||||
{
|
||||
id->setLocalName(++(*numLoc));
|
||||
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; ";
|
||||
codeOut <<"/* "<<Machine_X86::regName(id->longId().h()) << ":" <<
|
||||
Machine_X86::regName(id->longId().l()) << " */\n";
|
||||
o << id->name;
|
||||
pProc->localId.propLongId (id->longId().l(),id->longId().h(), id->name.c_str());
|
||||
}
|
||||
else /* GLB_FRAME */
|
||||
{
|
||||
if (id->id.longGlb.regi == 0) /* not indexed */
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"]";
|
||||
else if (id->id.longGlb.regi == rBX)
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"][bx]";
|
||||
}
|
||||
break;
|
||||
case OTHER:
|
||||
off = ident.idNode.other.off;
|
||||
o << Machine_X86::regName(ident.idNode.other.seg)<< "[";
|
||||
o << Machine_X86::regName(ident.idNode.other.regi);
|
||||
if (off < 0)
|
||||
o << "-"<< hexStr (-off);
|
||||
else if (off>0)
|
||||
o << "+"<< hexStr (off);
|
||||
o << "]";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
return "";
|
||||
case LONG_VAR:
|
||||
id = &pProc->localId.id_arr[ident.idNode.longIdx];
|
||||
if (id->name[0] != '\0') /* STK_FRAME & REG w/name*/
|
||||
o << id->name;
|
||||
else if (id->loc == REG_FRAME)
|
||||
{
|
||||
id->setLocalName(++(*numLoc));
|
||||
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; ";
|
||||
codeOut <<"/* "<<Machine_X86::regName(id->longId().h()) << ":" <<
|
||||
Machine_X86::regName(id->longId().l()) << " */\n";
|
||||
o << id->name;
|
||||
pProc->localId.propLongId (id->longId().l(),id->longId().h(), id->name);
|
||||
}
|
||||
else /* GLB_FRAME */
|
||||
{
|
||||
if (id->id.longGlb.regi == 0) /* not indexed */
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"]";
|
||||
else if (id->id.longGlb.regi == rBX)
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"][bx]";
|
||||
}
|
||||
break;
|
||||
case OTHER:
|
||||
off = ident.idNode.other.off;
|
||||
o << Machine_X86::regName(ident.idNode.other.seg)<< "[";
|
||||
o << Machine_X86::regName(ident.idNode.other.regi);
|
||||
if (off < 0)
|
||||
o << "-"<< hexStr (-off);
|
||||
else if (off>0)
|
||||
o << "+"<< hexStr (off);
|
||||
o << "]";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
return "";
|
||||
|
||||
|
||||
} /* eos */
|
||||
outStr << o.str();
|
||||
cCode.appendDecl(codeOut.str());
|
||||
return outStr.str();
|
||||
cCode.appendDecl(codeContents);
|
||||
return collectedContents;
|
||||
|
||||
}
|
||||
string UnaryOperator::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
QString UnaryOperator::wrapUnary(Function *pProc, int *numLoc,QChar op) const
|
||||
{
|
||||
std::ostringstream outStr;
|
||||
bool needBracket=true;
|
||||
QString outStr = op;
|
||||
QString inner = unaryExp->walkCondExpr (pProc, numLoc);
|
||||
if (unaryExp->m_type == IDENTIFIER)
|
||||
outStr += inner;
|
||||
else
|
||||
outStr += "("+inner+')';
|
||||
return outStr;
|
||||
}
|
||||
|
||||
QString UnaryOperator::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
{
|
||||
QString outStr;
|
||||
switch(m_type)
|
||||
{
|
||||
case NEGATION:
|
||||
if (unaryExp->m_type == IDENTIFIER)
|
||||
{
|
||||
needBracket = false;
|
||||
outStr << "!";
|
||||
}
|
||||
else
|
||||
outStr << "! (";
|
||||
outStr << unaryExp->walkCondExpr (pProc, numLoc);
|
||||
if (needBracket == true)
|
||||
outStr << ")";
|
||||
break;
|
||||
case NEGATION:
|
||||
outStr+=wrapUnary(pProc,numLoc,'!');
|
||||
break;
|
||||
|
||||
case ADDRESSOF:
|
||||
if (unaryExp->m_type == IDENTIFIER)
|
||||
{
|
||||
needBracket = false;
|
||||
outStr << "&";
|
||||
}
|
||||
else
|
||||
outStr << "&(";
|
||||
outStr << unaryExp->walkCondExpr (pProc, numLoc);
|
||||
if (needBracket == true)
|
||||
outStr << ")";
|
||||
break;
|
||||
case ADDRESSOF:
|
||||
outStr+=wrapUnary(pProc,numLoc,'&');
|
||||
break;
|
||||
|
||||
case DEREFERENCE:
|
||||
outStr << "*";
|
||||
if (unaryExp->m_type == IDENTIFIER)
|
||||
needBracket = false;
|
||||
else
|
||||
outStr << "(";
|
||||
outStr << unaryExp->walkCondExpr (pProc, numLoc);
|
||||
if (needBracket == true)
|
||||
outStr << ")";
|
||||
break;
|
||||
case DEREFERENCE:
|
||||
outStr+=wrapUnary(pProc,numLoc,'*');
|
||||
break;
|
||||
|
||||
case POST_INC:
|
||||
outStr << unaryExp->walkCondExpr (pProc, numLoc) << "++";
|
||||
break;
|
||||
case POST_INC:
|
||||
outStr += unaryExp->walkCondExpr (pProc, numLoc) + "++";
|
||||
break;
|
||||
|
||||
case POST_DEC:
|
||||
outStr << unaryExp->walkCondExpr (pProc, numLoc) << "--";
|
||||
break;
|
||||
case POST_DEC:
|
||||
outStr += unaryExp->walkCondExpr (pProc, numLoc) + "--";
|
||||
break;
|
||||
|
||||
case PRE_INC:
|
||||
outStr << "++"<< unaryExp->walkCondExpr (pProc, numLoc);
|
||||
break;
|
||||
case PRE_INC:
|
||||
outStr += "++" + unaryExp->walkCondExpr (pProc, numLoc);
|
||||
break;
|
||||
|
||||
case PRE_DEC:
|
||||
outStr << "--"<< unaryExp->walkCondExpr (pProc, numLoc);
|
||||
break;
|
||||
case PRE_DEC:
|
||||
outStr += "--" + unaryExp->walkCondExpr (pProc, numLoc);
|
||||
break;
|
||||
}
|
||||
return outStr.str();
|
||||
return outStr;
|
||||
}
|
||||
|
||||
/* Walks the conditional expression tree and returns the result on a string */
|
||||
@@ -724,18 +707,18 @@ Expr *UnaryOperator::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *lo
|
||||
Expr *temp;
|
||||
|
||||
switch (m_type) {
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
temp = unaryExp->insertSubTreeReg( _expr, regi, locsym);
|
||||
if (nullptr!=temp)
|
||||
{
|
||||
unaryExp = temp;
|
||||
return this;
|
||||
}
|
||||
return nullptr;
|
||||
default:
|
||||
fprintf(stderr,"insertSubTreeReg attempt on unhandled type %d\n",m_type);
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
temp = unaryExp->insertSubTreeReg( _expr, regi, locsym);
|
||||
if (nullptr!=temp)
|
||||
{
|
||||
unaryExp = temp;
|
||||
return this;
|
||||
}
|
||||
return nullptr;
|
||||
default:
|
||||
fprintf(stderr,"insertSubTreeReg attempt on unhandled type %d\n",m_type);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -841,22 +824,22 @@ Expr *BinaryOperator::inverse() const
|
||||
BinaryOperator *res=reinterpret_cast<BinaryOperator *>(this->clone());
|
||||
switch (m_op)
|
||||
{
|
||||
case LESS_EQUAL: case LESS: case EQUAL:
|
||||
case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
|
||||
res->m_op = invCondOp[m_op];
|
||||
return res;
|
||||
case LESS_EQUAL: case LESS: case EQUAL:
|
||||
case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
|
||||
res->m_op = invCondOp[m_op];
|
||||
return res;
|
||||
|
||||
case AND: case OR: case XOR: case NOT: case ADD:
|
||||
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
|
||||
return UnaryOperator::Create(NEGATION, res);
|
||||
case AND: case OR: case XOR: case NOT: case ADD:
|
||||
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
|
||||
return UnaryOperator::Create(NEGATION, res);
|
||||
|
||||
case DBL_AND: case DBL_OR:
|
||||
res->m_op = invCondOp[m_op];
|
||||
res->m_lhs=m_lhs->inverse ();
|
||||
res->m_rhs=m_rhs->inverse ();
|
||||
return res;
|
||||
default:
|
||||
fprintf(stderr,"BinaryOperator::inverse attempt on unhandled op %d\n",m_op);
|
||||
case DBL_AND: case DBL_OR:
|
||||
res->m_op = invCondOp[m_op];
|
||||
res->m_lhs=m_lhs->inverse ();
|
||||
res->m_rhs=m_rhs->inverse ();
|
||||
return res;
|
||||
default:
|
||||
fprintf(stderr,"BinaryOperator::inverse attempt on unhandled op %d\n",m_op);
|
||||
} /* eos */
|
||||
assert(false);
|
||||
return res;
|
||||
@@ -877,8 +860,8 @@ Expr *AstIdent::performLongRemoval(eReg regi, LOCAL_ID *locId)
|
||||
eReg AstIdent::otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
|
||||
{
|
||||
ID *id = &locTbl->id_arr[idx];
|
||||
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
|
||||
(id->type == TYPE_LONG_UNSIGN)))
|
||||
if ((id->loc == REG_FRAME) and ((id->type == TYPE_LONG_SIGN) or
|
||||
(id->type == TYPE_LONG_UNSIGN)))
|
||||
{
|
||||
if (id->longId().h() == regi)
|
||||
return (id->longId().l());
|
||||
@@ -889,14 +872,12 @@ eReg AstIdent::otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
|
||||
}
|
||||
|
||||
|
||||
string Constant::walkCondExpr(Function *, int *) const
|
||||
QString Constant::walkCondExpr(Function *, int *) const
|
||||
{
|
||||
ostringstream o;
|
||||
if (kte.kte < 1000)
|
||||
o << kte.kte;
|
||||
return QString::number(kte.kte);
|
||||
else
|
||||
o << "0x"<<std::hex << kte.kte;
|
||||
return o.str();
|
||||
return "0x" + QString::number(kte.kte,16);
|
||||
}
|
||||
|
||||
int Constant::hlTypeSize(Function *) const
|
||||
@@ -909,17 +890,17 @@ hlType Constant::expType(Function *pproc) const
|
||||
return TYPE_CONST;
|
||||
}
|
||||
|
||||
string FuncNode::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
QString FuncNode::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
{
|
||||
return pProc->writeCall(call.proc,*call.args, numLoc);
|
||||
}
|
||||
|
||||
int FuncNode::hlTypeSize(Function *) const
|
||||
{
|
||||
return hlSize[call.proc->retVal.type];
|
||||
return hlSize[call.proc->getReturnType()];
|
||||
}
|
||||
|
||||
hlType FuncNode::expType(Function *) const
|
||||
{
|
||||
return call.proc->retVal.type;
|
||||
return call.proc->getReturnType();
|
||||
}
|
||||
|
||||
173
src/backend.cpp
173
src/backend.cpp
@@ -4,10 +4,20 @@
|
||||
* Purpose: Back-end module. Generates C code for each procedure.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "disassem.h"
|
||||
#include "project.h"
|
||||
#include "CallGraph.h"
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QDebug>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
|
||||
#include <fstream>
|
||||
@@ -15,19 +25,17 @@
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "dcc.h"
|
||||
#include "disassem.h"
|
||||
#include "project.h"
|
||||
#include "CallGraph.h"
|
||||
|
||||
using namespace boost;
|
||||
using namespace boost::adaptors;
|
||||
bundle cCode; /* Procedure declaration and code */
|
||||
using namespace std;
|
||||
|
||||
bundle cCode; /* Procedure declaration and code */
|
||||
|
||||
/* Returns a unique index to the next label */
|
||||
int getNextLabel()
|
||||
{
|
||||
static int labelIdx = 1; /* index of the next label */
|
||||
static int labelIdx = 1; /* index of the next label */
|
||||
return (labelIdx++);
|
||||
}
|
||||
|
||||
@@ -35,14 +43,14 @@ int getNextLabel()
|
||||
/* displays statistics on the subroutine */
|
||||
void Function::displayStats ()
|
||||
{
|
||||
printf("\nStatistics - Subroutine %s\n", name.c_str());
|
||||
printf ("Number of Icode instructions:\n");
|
||||
printf (" Low-level : %4d\n", stats.numLLIcode);
|
||||
if (! (flg & PROC_ASM))
|
||||
qDebug() << "\nStatistics - Subroutine" << name;
|
||||
qDebug() << "Number of Icode instructions:";
|
||||
qDebug() << " Low-level :" << stats.numLLIcode;
|
||||
if (not (flg & PROC_ASM))
|
||||
{
|
||||
printf (" High-level: %4d\n", stats.numHLIcode);
|
||||
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode *
|
||||
100.0) / stats.numLLIcode);
|
||||
qDebug() << " High-level:"<<stats.numHLIcode;
|
||||
qDebug() << QString(" Percentage reduction: %1%%").arg(100.0 - (stats.numHLIcode *
|
||||
100.0) / stats.numLLIcode,4,'f',2,QChar('0'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +62,8 @@ static void fixupLabels (PPROC pProc)
|
||||
* a unique label number for it. This label is placed in the associated
|
||||
* icode for the node (pProc->Icode). The procedure is done in sequential
|
||||
* order of dsfLast numbering. */
|
||||
{ int i; /* index into the dfsLast array */
|
||||
PBB *dfsLast; /* pointer to the dfsLast array */
|
||||
{ int i; /* index into the dfsLast array */
|
||||
PBB *dfsLast; /* pointer to the dfsLast array */
|
||||
|
||||
dfsLast = pProc->dfsLast;
|
||||
for (i = 0; i < pProc->numBBs; i++)
|
||||
@@ -74,10 +82,10 @@ char *cChar (uint8_t c)
|
||||
static char res[3];
|
||||
|
||||
switch (c) {
|
||||
case 0x8: /* backspace */
|
||||
case 0x8: /* backspace */
|
||||
sprintf (res, "\\b");
|
||||
break;
|
||||
case 0x9: /* horizontal tab */
|
||||
case 0x9: /* horizontal tab */
|
||||
sprintf (res, "\\t");
|
||||
break;
|
||||
case 0x0A: /* new line */
|
||||
@@ -89,7 +97,7 @@ char *cChar (uint8_t c)
|
||||
case 0x0D: /* carriage return */
|
||||
sprintf (res, "\\r");
|
||||
break;
|
||||
default: /* any other character*/
|
||||
default: /* any other character*/
|
||||
sprintf (res, "%c", c);
|
||||
}
|
||||
return (res);
|
||||
@@ -98,9 +106,9 @@ char *cChar (uint8_t c)
|
||||
|
||||
/* Prints the variable's name and initial contents on the file.
|
||||
* Note: to get to the value of the variable:
|
||||
* com file: prog.Image[operand]
|
||||
* exe file: prog.Image[operand+0x100] */
|
||||
static void printGlobVar (std::ostream &ostr,SYM * psym)
|
||||
* com file: prog.Image[operand]
|
||||
* exe file: prog.Image[operand+0x100] */
|
||||
static void printGlobVar (QTextStream &ostr,SYM * psym)
|
||||
{
|
||||
int j;
|
||||
PROG &prog(Project::get()->prog);
|
||||
@@ -116,17 +124,17 @@ static void printGlobVar (std::ostream &ostr,SYM * psym)
|
||||
break;
|
||||
case 4: if (psym->type == TYPE_PTR) /* pointer */
|
||||
ostr << "uint16_t *\t"<<psym->name<<" = "<<LH(prog.image()+relocOp)<<";\n";
|
||||
else /* char */
|
||||
else /* char */
|
||||
ostr << "char\t"<<psym->name<<"[4] = \""<<
|
||||
prog.image()[relocOp]<<prog.image()[relocOp+1]<<
|
||||
prog.image()[relocOp+2]<<prog.image()[relocOp+3]<<";\n";
|
||||
break;
|
||||
default:
|
||||
{
|
||||
ostringstream strContents;
|
||||
QString strContents;
|
||||
for (j=0; j < psym->size; j++)
|
||||
strContents << cChar(prog.image()[relocOp + j]);
|
||||
ostr << "char\t*"<<psym->name<<" = \""<<strContents.str()<<"\";\n";
|
||||
strContents += cChar(prog.image()[relocOp + j]);
|
||||
ostr << "char\t*"<<psym->name<<" = \""<<strContents<<"\";\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,7 +145,8 @@ static void printGlobVar (std::ostream &ostr,SYM * psym)
|
||||
* initialization. */
|
||||
void Project::writeGlobSymTable()
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
QString contents;
|
||||
QTextStream ostr(&contents);
|
||||
|
||||
if (symtab.empty())
|
||||
return;
|
||||
@@ -145,8 +154,8 @@ void Project::writeGlobSymTable()
|
||||
for (SYM &sym : symtab)
|
||||
{
|
||||
if (sym.duVal.isUSE_VAL()) /* first used */
|
||||
printGlobVar (ostr,&sym);
|
||||
else { /* first defined */
|
||||
printGlobVar (ostr,&sym);
|
||||
else { /* first defined */
|
||||
switch (sym.size) {
|
||||
case 1: ostr<<"uint8_t\t"; break;
|
||||
case 2: ostr<<"int\t"; break;
|
||||
@@ -161,19 +170,20 @@ void Project::writeGlobSymTable()
|
||||
}
|
||||
}
|
||||
ostr<< "\n";
|
||||
cCode.appendDecl( ostr.str() );
|
||||
ostr.flush();
|
||||
cCode.appendDecl( contents );
|
||||
}
|
||||
|
||||
|
||||
/* Writes the header information and global variables to the output C file
|
||||
* fp. */
|
||||
static void writeHeader (std::ostream &_ios, char *fileName)
|
||||
static void writeHeader (QIODevice &_ios, const std::string &fileName)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
/* Write header information */
|
||||
cCode.init();
|
||||
cCode.appendDecl( "/*\n");
|
||||
cCode.appendDecl( " * Input file\t: %s\n", fileName);
|
||||
cCode.appendDecl( " * Input file\t: %s\n", fileName.c_str());
|
||||
cCode.appendDecl( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
|
||||
cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n");
|
||||
|
||||
@@ -188,7 +198,7 @@ static void writeHeader (std::ostream &_ios, char *fileName)
|
||||
* to it. If so, a goto is emitted to this label; otherwise, a new label
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be forward on
|
||||
* the code; that is, the target code has not been traversed yet. */
|
||||
* the code; that is, the target code has not been traversed yet. */
|
||||
#if 0
|
||||
static void emitFwdGotoLabel (ICODE * pt, int indLevel)
|
||||
{
|
||||
@@ -204,10 +214,11 @@ static void emitFwdGotoLabel (ICODE * pt, int indLevel)
|
||||
|
||||
/* Writes the procedure's declaration (including arguments), local variables,
|
||||
* and invokes the procedure that writes the code of the given record *hli */
|
||||
void Function::codeGen (std::ostream &fs)
|
||||
void Function::codeGen (QIODevice &fs)
|
||||
{
|
||||
int numLoc;
|
||||
ostringstream ostr;
|
||||
QString ostr_contents;
|
||||
QTextStream ostr(&ostr_contents);
|
||||
//STKFRAME * args; /* Procedure arguments */
|
||||
//char buf[200], /* Procedure's definition */
|
||||
// arg[30]; /* One argument */
|
||||
@@ -215,31 +226,28 @@ void Function::codeGen (std::ostream &fs)
|
||||
|
||||
/* Write procedure/function header */
|
||||
cCode.init();
|
||||
if (flg & PROC_IS_FUNC) /* Function */
|
||||
ostr<< "\n"<<TypeContainer::typeName(retVal.type)<<" "<<name<<" (";
|
||||
if (getReturnType() != TYPE_UNKNOWN) /* Function */
|
||||
ostr << QString("\n%1 %2 (").arg(TypeContainer::typeName(getReturnType())).arg(name);
|
||||
else /* Procedure */
|
||||
ostr<< "\nvoid "<<name<<" (";
|
||||
ostr << "\nvoid "+name+" (";
|
||||
|
||||
/* Write arguments */
|
||||
struct validArg
|
||||
{
|
||||
bool operator()(STKSYM &s) { return s.invalid==false;}
|
||||
};
|
||||
auto valid_args = args | filtered(validArg());
|
||||
int count_valid = std::distance(valid_args.begin(),valid_args.end());
|
||||
for (STKSYM &arg : valid_args)
|
||||
QStringList parts;
|
||||
for (STKSYM &arg : (args | filtered(validArg())))
|
||||
{
|
||||
ostr<<hlTypes[arg.type]<<" "<<arg.name;
|
||||
if(--count_valid!=0)
|
||||
ostr<<", ";
|
||||
parts << QString("%1 %2").arg(hlTypes[arg.type]).arg(arg.name);
|
||||
}
|
||||
ostr<<")\n";
|
||||
ostr << parts.join(", ")+")\n";
|
||||
|
||||
/* Write comments */
|
||||
writeProcComments( ostr );
|
||||
|
||||
/* Write local variables */
|
||||
if (! (flg & PROC_ASM))
|
||||
if (not (flg & PROC_ASM))
|
||||
{
|
||||
numLoc = 0;
|
||||
for (ID &refId : localId )
|
||||
@@ -250,8 +258,8 @@ void Function::codeGen (std::ostream &fs)
|
||||
if (refId.loc == REG_FRAME)
|
||||
{
|
||||
/* Register variables are assigned to a local variable */
|
||||
if (((flg & SI_REGVAR) && (refId.id.regi == rSI)) ||
|
||||
((flg & DI_REGVAR) && (refId.id.regi == rDI)))
|
||||
if (((flg & SI_REGVAR) and (refId.id.regi == rSI)) or
|
||||
((flg & DI_REGVAR) and (refId.id.regi == rDI)))
|
||||
{
|
||||
refId.setLocalName(++numLoc);
|
||||
ostr << "int "<<refId.name<<";\n";
|
||||
@@ -267,14 +275,16 @@ void Function::codeGen (std::ostream &fs)
|
||||
}
|
||||
}
|
||||
}
|
||||
fs<<ostr.str();
|
||||
ostr.flush();
|
||||
fs.write(ostr_contents.toLatin1());
|
||||
|
||||
/* Write procedure's code */
|
||||
if (flg & PROC_ASM) /* generate assembler */
|
||||
if (flg & PROC_ASM) /* generate assembler */
|
||||
{
|
||||
Disassembler ds(3);
|
||||
ds.disassem(this);
|
||||
ds.disassem(this->shared_from_this());
|
||||
}
|
||||
else /* generate C */
|
||||
else /* generate C */
|
||||
{
|
||||
m_actual_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
|
||||
}
|
||||
@@ -284,36 +294,41 @@ void Function::codeGen (std::ostream &fs)
|
||||
freeBundle (&cCode);
|
||||
|
||||
/* Write Live register analysis information */
|
||||
if (option.verbose)
|
||||
if (option.verbose) {
|
||||
QString debug_contents;
|
||||
QTextStream debug_stream(&debug_contents);
|
||||
for (size_t i = 0; i < numBBs; i++)
|
||||
{
|
||||
pBB = m_dfsLast[i];
|
||||
if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */
|
||||
cout << "BB "<<i<<"\n";
|
||||
cout << " Start = "<<pBB->begin()->loc_ip;
|
||||
cout << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
|
||||
cout << " LiveUse = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->liveUse);
|
||||
cout << "\n Def = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->def);
|
||||
cout << "\n LiveOut = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->liveOut);
|
||||
cout << "\n LiveIn = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->liveIn);
|
||||
cout <<"\n\n";
|
||||
debug_stream << "BB "<<i<<"\n";
|
||||
debug_stream << " Start = "<<pBB->begin()->loc_ip;
|
||||
debug_stream << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
|
||||
debug_stream << " LiveUse = ";
|
||||
Machine_X86::writeRegVector(debug_stream,pBB->liveUse);
|
||||
debug_stream << "\n Def = ";
|
||||
Machine_X86::writeRegVector(debug_stream,pBB->def);
|
||||
debug_stream << "\n LiveOut = ";
|
||||
Machine_X86::writeRegVector(debug_stream,pBB->liveOut);
|
||||
debug_stream << "\n LiveIn = ";
|
||||
Machine_X86::writeRegVector(debug_stream,pBB->liveIn);
|
||||
debug_stream <<"\n\n";
|
||||
}
|
||||
debug_stream.flush();
|
||||
qDebug() << debug_contents.toLatin1();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Recursive procedure. Displays the procedure's code in depth-first order
|
||||
* of the call graph. */
|
||||
static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios)
|
||||
static void backBackEnd (CALL_GRAPH * pcallGraph, QIODevice &_ios)
|
||||
{
|
||||
|
||||
// IFace.Yield(); /* This is a good place to yield to other apps */
|
||||
// IFace.Yield(); /* This is a good place to yield to other apps */
|
||||
|
||||
/* Check if this procedure has been processed already */
|
||||
if ((pcallGraph->proc->flg & PROC_OUTPUT) ||
|
||||
if ((pcallGraph->proc->flg & PROC_OUTPUT) or
|
||||
(pcallGraph->proc->flg & PROC_ISLIB))
|
||||
return;
|
||||
pcallGraph->proc->flg |= PROC_OUTPUT;
|
||||
@@ -332,7 +347,7 @@ static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios)
|
||||
/* Generate statistics */
|
||||
if (option.Stats)
|
||||
pcallGraph->proc->displayStats ();
|
||||
if (! (pcallGraph->proc->flg & PROC_ASM))
|
||||
if (not (pcallGraph->proc->flg & PROC_ASM))
|
||||
{
|
||||
stats.totalLL += stats.numLLIcode;
|
||||
stats.totalHL += stats.numHLIcode;
|
||||
@@ -341,22 +356,20 @@ static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios)
|
||||
|
||||
|
||||
/* Invokes the necessary routines to produce code one procedure at a time. */
|
||||
void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
|
||||
void BackEnd(CALL_GRAPH * pcallGraph)
|
||||
{
|
||||
std::ofstream fs; /* Output C file */
|
||||
|
||||
/* Get output file name */
|
||||
std::string outNam(fileName);
|
||||
outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */
|
||||
QString outNam(Project::get()->output_name("b")); /* b for beta */
|
||||
QFile fs(outNam); /* Output C file */
|
||||
|
||||
/* Open output file */
|
||||
fs.open(outNam);
|
||||
if(!fs.is_open())
|
||||
fatalError (CANNOT_OPEN, outNam.c_str());
|
||||
printf ("dcc: Writing C beta file %s\n", outNam.c_str());
|
||||
if(not fs.open(QFile::WriteOnly|QFile::Text))
|
||||
fatalError (CANNOT_OPEN, outNam.toStdString().c_str());
|
||||
|
||||
qDebug()<<"dcc: Writing C beta file"<<outNam;
|
||||
|
||||
/* Header information */
|
||||
writeHeader (fs, option.filename);
|
||||
writeHeader (fs, option.filename.toStdString());
|
||||
|
||||
/* Initialize total Icode instructions statistics */
|
||||
stats.totalLL = 0;
|
||||
@@ -367,7 +380,7 @@ void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
|
||||
|
||||
/* Close output file */
|
||||
fs.close();
|
||||
printf ("dcc: Finished writing C beta file\n");
|
||||
qDebug() << "dcc: Finished writing C beta file";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <QtCore/QIODevice>
|
||||
#define deltaProcLines 20
|
||||
|
||||
using namespace std;
|
||||
@@ -21,26 +21,26 @@ using namespace std;
|
||||
* tab is removed and replaced by this label */
|
||||
void strTable::addLabelBundle (int idx, int label)
|
||||
{
|
||||
char s[16];
|
||||
sprintf (s, "l%d: ", label);
|
||||
if(at(idx).size()<4)
|
||||
at(idx)=s;
|
||||
QString &processedLine(at(idx));
|
||||
QString s = QString("l%1: ").arg(label);
|
||||
if(processedLine.size()<4)
|
||||
processedLine = s;
|
||||
else
|
||||
at(idx) = string(s)+at(idx).substr(4);
|
||||
processedLine = s+processedLine.mid(4);
|
||||
}
|
||||
|
||||
|
||||
/* Writes the contents of the string table on the file fp. */
|
||||
static void writeStrTab (std::ostream &ios, strTable &strTab)
|
||||
static void writeStrTab (QIODevice &ios, strTable &strTab)
|
||||
{
|
||||
for (size_t i = 0; i < strTab.size(); i++)
|
||||
ios << strTab[i];
|
||||
ios.write(strTab[i].toLatin1());
|
||||
}
|
||||
|
||||
|
||||
/* Writes the contents of the bundle (procedure code and declaration) to
|
||||
* a file. */
|
||||
void writeBundle (std::ostream &ios, bundle procCode)
|
||||
void writeBundle (QIODevice &ios, bundle procCode)
|
||||
{
|
||||
writeStrTab (ios, procCode.decl);
|
||||
writeStrTab (ios, procCode.code);
|
||||
@@ -70,7 +70,7 @@ void bundle::appendCode(const char *format,...)
|
||||
code.push_back(buf);
|
||||
va_end (args);
|
||||
}
|
||||
void bundle::appendCode(const std::string &s)
|
||||
void bundle::appendCode(const QString & s)
|
||||
{
|
||||
code.push_back(s);
|
||||
}
|
||||
@@ -85,7 +85,7 @@ void bundle::appendDecl(const char *format,...)
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void bundle::appendDecl(const std::string &v)
|
||||
void bundle::appendDecl(const QString &v)
|
||||
{
|
||||
decl.push_back(v);
|
||||
}
|
||||
|
||||
1224
src/chklib.cpp
1224
src/chklib.cpp
File diff suppressed because it is too large
Load Diff
51
src/chklib.h
Normal file
51
src/chklib.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef CHKLIB_H
|
||||
#define CHKLIB_H
|
||||
|
||||
#include "Command.h"
|
||||
#include "Enums.h"
|
||||
#include "perfhlib.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QString>
|
||||
#include <vector>
|
||||
|
||||
class Function;
|
||||
|
||||
// This will create a PatternLocator instance load it and pass it to project instance.
|
||||
struct LoadPatternLibrary : public Command {
|
||||
LoadPatternLibrary() : Command("Load patterns for the file",eProject) {}
|
||||
bool execute(CommandContext *ctx) override;
|
||||
};
|
||||
|
||||
class PatternLocator {
|
||||
std::vector<hlType> pArg; /* Points to the array of param types */
|
||||
QString pattern_id;
|
||||
int numFunc=0; /* Number of func names actually stored */
|
||||
int numArg=0; /* Number of param names actually stored */
|
||||
public:
|
||||
struct HT * ht =nullptr; //!< The hash table
|
||||
struct PH_FUNC_STRUCT * pFunc=nullptr; //!< Points to the array of func names
|
||||
|
||||
|
||||
PatternLocator(QString name) : pattern_id(name) {}
|
||||
~PatternLocator();
|
||||
|
||||
bool load();
|
||||
int searchPList(const char * name);
|
||||
|
||||
bool LibCheck(Function & pProc);
|
||||
private:
|
||||
bool readProtoFile();
|
||||
PerfectHash g_pattern_hasher;
|
||||
int numKeys=0; /* Number of hash table entries (keys) */
|
||||
int numVert=0; /* Number of vertices in the graph (also size of g[]) */
|
||||
unsigned PatLen=0; /* Size of the keys (pattern length) */
|
||||
unsigned SymLen=0; /* Max size of the symbols, including null */
|
||||
/* Pointers to start of T1, T2 */
|
||||
uint16_t * T1base = nullptr;
|
||||
uint16_t * T2base = nullptr;
|
||||
uint16_t * g = nullptr; /* g[] */
|
||||
|
||||
};
|
||||
extern bool checkStartup(struct STATE &state);
|
||||
#endif // CHKLIB_H
|
||||
@@ -7,11 +7,14 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
#include <QTextStream>
|
||||
using namespace std;
|
||||
#define intSize 40
|
||||
#define intSize 40
|
||||
|
||||
static const char *int21h[] =
|
||||
{
|
||||
@@ -128,27 +131,27 @@ static const char *int21h[] =
|
||||
|
||||
|
||||
static const char *intOthers[] = {
|
||||
"Exit", /* 0x20 */
|
||||
"", /* other table */
|
||||
"Terminate handler address", /* 0x22 */
|
||||
"Ctrl-C handler address", /* 0x23 */
|
||||
"Exit", /* 0x20 */
|
||||
"", /* other table */
|
||||
"Terminate handler address", /* 0x22 */
|
||||
"Ctrl-C handler address", /* 0x23 */
|
||||
"Critical-error handler address", /* 0x24 */
|
||||
"Absolute disk read", /* 0x25 */
|
||||
"Absolute disk write", /* 0x26 */
|
||||
"Terminate and stay resident", /* 0x27 */
|
||||
"Reserved", /* 0x28 */
|
||||
"Reserved", /* 0x29 */
|
||||
"Reserved", /* 0x2A */
|
||||
"Reserved", /* 0x2B */
|
||||
"Reserved", /* 0x2C */
|
||||
"Reserved", /* 0x2D */
|
||||
"Reserved" /* 0x2E */
|
||||
"Absolute disk read", /* 0x25 */
|
||||
"Absolute disk write", /* 0x26 */
|
||||
"Terminate and stay resident", /* 0x27 */
|
||||
"Reserved", /* 0x28 */
|
||||
"Reserved", /* 0x29 */
|
||||
"Reserved", /* 0x2A */
|
||||
"Reserved", /* 0x2B */
|
||||
"Reserved", /* 0x2C */
|
||||
"Reserved", /* 0x2D */
|
||||
"Reserved" /* 0x2E */
|
||||
};
|
||||
|
||||
|
||||
/* Writes the description of the current interrupt. Appends it to the
|
||||
* string s. */
|
||||
void LLInst::writeIntComment (std::ostringstream &s)
|
||||
void LLInst::writeIntComment (QTextStream &s)
|
||||
{
|
||||
uint32_t src_immed=src().getImm2();
|
||||
s<<"\t/* ";
|
||||
@@ -156,7 +159,7 @@ void LLInst::writeIntComment (std::ostringstream &s)
|
||||
{
|
||||
s <<int21h[m_dst.off];
|
||||
}
|
||||
else if (src_immed > 0x1F && src_immed < 0x2F)
|
||||
else if (src_immed > 0x1F and src_immed < 0x2F)
|
||||
{
|
||||
s <<intOthers[src_immed - 0x20];
|
||||
}
|
||||
@@ -186,16 +189,19 @@ void LLInst::writeIntComment (std::ostringstream &s)
|
||||
//, &cCode.decl
|
||||
void Function::writeProcComments()
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
writeProcComments(ostr);
|
||||
cCode.appendDecl(ostr.str());
|
||||
QString dest_str;
|
||||
{
|
||||
QTextStream ostr(&dest_str);
|
||||
writeProcComments(ostr);
|
||||
}
|
||||
cCode.appendDecl(dest_str);
|
||||
}
|
||||
|
||||
void Function::writeProcComments(std::ostream &ostr)
|
||||
void Function::writeProcComments(QTextStream &ostr)
|
||||
{
|
||||
int i;
|
||||
ID *id; /* Pointer to register argument identifier */
|
||||
STKSYM * psym; /* Pointer to register argument symbol */
|
||||
ID *id; /* Pointer to register argument identifier */
|
||||
STKSYM * psym; /* Pointer to register argument symbol */
|
||||
|
||||
/* About the parameters */
|
||||
if (this->cbParam)
|
||||
@@ -212,7 +218,7 @@ void Function::writeProcComments(std::ostream &ostr)
|
||||
id = &this->localId.id_arr[((RegisterNode *)psym->regs)->regiIdx];
|
||||
ostr << Machine_X86::regName(id->id.regi);
|
||||
}
|
||||
else /* long register */
|
||||
else /* long register */
|
||||
{
|
||||
id = &this->localId.id_arr[psym->regs->ident.idNode.longIdx];
|
||||
ostr << Machine_X86::regName(id->longId().h()) << ":";
|
||||
@@ -233,21 +239,24 @@ void Function::writeProcComments(std::ostream &ostr)
|
||||
if (this->flg & PROC_ASM)
|
||||
{
|
||||
ostr << " * Untranslatable routine. Assembler provided.\n";
|
||||
if (this->flg & PROC_IS_FUNC)
|
||||
switch (this->retVal.type) { // TODO: Functions return value in various regs
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
ostr << " * Return value in register al.\n";
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
ostr << " * Return value in register ax.\n";
|
||||
break;
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
ostr << " * Return value in registers dx:ax.\n";
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Unknown retval type %d",this->retVal.type);
|
||||
break;
|
||||
} /* eos */
|
||||
switch (getReturnType()) { // TODO: Functions return value in various regs
|
||||
case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN:
|
||||
ostr << " * Return value in register al.\n";
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
ostr << " * Return value in register ax.\n";
|
||||
break;
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
ostr << " * Return value in registers dx:ax.\n";
|
||||
break;
|
||||
case TYPE_UNKNOWN:
|
||||
// void return type
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Unknown retval type %d",getReturnType());
|
||||
break;
|
||||
} /* eos */
|
||||
}
|
||||
|
||||
/* Calling convention */
|
||||
|
||||
115
src/control.cpp
115
src/control.cpp
@@ -2,6 +2,10 @@
|
||||
* Description : Performs control flow analysis on the CFG
|
||||
* (C) Cristina Cifuentes
|
||||
********************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
@@ -10,15 +14,10 @@
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
//typedef struct list {
|
||||
// int nodeIdx;
|
||||
// struct list *next;
|
||||
//} nodeList;
|
||||
typedef std::list<int> nodeList; /* dfsLast index to the node */
|
||||
|
||||
#define ancestor(a,b) ((a->dfsLastNum < b->dfsLastNum) && (a->dfsFirstNum < b->dfsFirstNum))
|
||||
#define ancestor(a,b) ((a->dfsLastNum < b->dfsLastNum) and (a->dfsFirstNum < b->dfsFirstNum))
|
||||
/* there is a path on the DFST from a to b if the a was first visited in a
|
||||
* dfs, and a was later visited than b when doing the last visit of each
|
||||
* node. */
|
||||
@@ -48,7 +47,7 @@ static int commonDom (int currImmDom, int predImmDom, Function * pProc)
|
||||
if (predImmDom == NO_DOM) /* predecessor is the root */
|
||||
return (currImmDom);
|
||||
|
||||
while ((currImmDom != NO_DOM) && (predImmDom != NO_DOM) &&
|
||||
while ((currImmDom != NO_DOM) and (predImmDom != NO_DOM) and
|
||||
(currImmDom != predImmDom))
|
||||
{
|
||||
if (currImmDom < predImmDom)
|
||||
@@ -70,7 +69,7 @@ void Function::findImmedDom ()
|
||||
for (size_t currIdx = 0; currIdx < numBBs; currIdx++)
|
||||
{
|
||||
currNode = m_dfsLast[currIdx];
|
||||
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
|
||||
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
|
||||
continue;
|
||||
for (BB * inedge : currNode->inEdges)
|
||||
{
|
||||
@@ -121,7 +120,7 @@ static void findEndlessFollow (Function * pProc, nodeList &loopNodes, BB * head)
|
||||
for (TYPEADR_TYPE &typeaddr: pProc->m_dfsLast[loop_node]->edges)
|
||||
{
|
||||
int succ = typeaddr.BBptr->dfsLastNum;
|
||||
if ((! inList(loopNodes, succ)) && (succ < head->loopFollow))
|
||||
if ((not inList(loopNodes, succ)) and (succ < head->loopFollow))
|
||||
head->loopFollow = succ;
|
||||
}
|
||||
}
|
||||
@@ -135,7 +134,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
{
|
||||
int i, headDfsNum, intNodeType;
|
||||
nodeList loopNodes;
|
||||
int immedDom, /* dfsLast index to immediate dominator */
|
||||
int immedDom, /* dfsLast index to immediate dominator */
|
||||
thenDfs, elseDfs; /* dsfLast index for THEN and ELSE nodes */
|
||||
BB * pbb;
|
||||
|
||||
@@ -145,11 +144,11 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
insertList (loopNodes, headDfsNum);
|
||||
for (i = headDfsNum + 1; i < latchNode->dfsLastNum; i++)
|
||||
{
|
||||
if (pProc->m_dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */
|
||||
if (pProc->m_dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */
|
||||
continue;
|
||||
|
||||
immedDom = pProc->m_dfsLast[i]->immedDom;
|
||||
if (inList (loopNodes, immedDom) && inInt(pProc->m_dfsLast[i], intNodes))
|
||||
if (inList (loopNodes, immedDom) and inInt(pProc->m_dfsLast[i], intNodes))
|
||||
{
|
||||
insertList (loopNodes, i);
|
||||
if (pProc->m_dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/
|
||||
@@ -163,12 +162,12 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
/* Determine type of loop and follow node */
|
||||
intNodeType = head->nodeType;
|
||||
if (latchNode->nodeType == TWO_BRANCH)
|
||||
if ((intNodeType == TWO_BRANCH) || (latchNode == head))
|
||||
if ((latchNode == head) ||
|
||||
(inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) &&
|
||||
if ((intNodeType == TWO_BRANCH) or (latchNode == head))
|
||||
if ((latchNode == head) or
|
||||
(inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) and
|
||||
inList (loopNodes, head->edges[ELSE].BBptr->dfsLastNum)))
|
||||
{
|
||||
head->loopType = REPEAT_TYPE;
|
||||
head->loopType = eNodeHeaderType::REPEAT_TYPE;
|
||||
if (latchNode->edges[0].BBptr == head)
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
@@ -177,7 +176,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
}
|
||||
else
|
||||
{
|
||||
head->loopType = WHILE_TYPE;
|
||||
head->loopType = eNodeHeaderType::WHILE_TYPE;
|
||||
if (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum))
|
||||
head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
@@ -186,22 +185,22 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
}
|
||||
else /* head = anything besides 2-way, latch = 2-way */
|
||||
{
|
||||
head->loopType = REPEAT_TYPE;
|
||||
head->loopType = eNodeHeaderType::REPEAT_TYPE;
|
||||
if (latchNode->edges[THEN].BBptr == head)
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
|
||||
latchNode->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else /* latch = 1-way */
|
||||
else /* latch = 1-way */
|
||||
if (latchNode->nodeType == LOOP_NODE)
|
||||
{
|
||||
head->loopType = REPEAT_TYPE;
|
||||
head->loopType = eNodeHeaderType::REPEAT_TYPE;
|
||||
head->loopFollow = latchNode->edges[0].BBptr->dfsLastNum;
|
||||
}
|
||||
else if (intNodeType == TWO_BRANCH)
|
||||
{
|
||||
head->loopType = WHILE_TYPE;
|
||||
head->loopType = eNodeHeaderType::WHILE_TYPE;
|
||||
pbb = latchNode;
|
||||
thenDfs = head->edges[THEN].BBptr->dfsLastNum;
|
||||
elseDfs = head->edges[ELSE].BBptr->dfsLastNum;
|
||||
@@ -222,19 +221,19 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
* loop, so it is safer to consider it an endless loop */
|
||||
if (pbb->dfsLastNum <= head->dfsLastNum)
|
||||
{
|
||||
head->loopType = ENDLESS_TYPE;
|
||||
head->loopType = eNodeHeaderType::ENDLESS_TYPE;
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
break;
|
||||
}
|
||||
pbb = pProc->m_dfsLast[pbb->immedDom];
|
||||
}
|
||||
if (pbb->dfsLastNum > head->dfsLastNum)
|
||||
pProc->m_dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/
|
||||
pProc->m_dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/
|
||||
head->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->loopType = ENDLESS_TYPE;
|
||||
head->loopType = eNodeHeaderType::ENDLESS_TYPE;
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
}
|
||||
|
||||
@@ -267,12 +266,12 @@ static void findNodesInInt (queue &intNodes, int level, interval *Ii)
|
||||
void Function::structLoops(derSeq *derivedG)
|
||||
{
|
||||
interval *Ii;
|
||||
BB * intHead, /* interval header node */
|
||||
* pred, /* predecessor node */
|
||||
BB * intHead, /* interval header node */
|
||||
* pred, /* predecessor node */
|
||||
* latchNode;/* latching node (in case of loops) */
|
||||
size_t level = 0; /* derived sequence level */
|
||||
interval *initInt; /* initial interval */
|
||||
queue intNodes; /* list of interval nodes */
|
||||
size_t level = 0; /* derived sequence level */
|
||||
interval *initInt; /* initial interval */
|
||||
queue intNodes; /* list of interval nodes */
|
||||
|
||||
/* Structure loops */
|
||||
/* for all derived sequences Gi */
|
||||
@@ -299,9 +298,9 @@ void Function::structLoops(derSeq *derivedG)
|
||||
for (size_t i = 0; i < intHead->inEdges.size(); i++)
|
||||
{
|
||||
pred = intHead->inEdges[i];
|
||||
if (inInt(pred, intNodes) && isBackEdge(pred, intHead))
|
||||
if (inInt(pred, intNodes) and isBackEdge(pred, intHead))
|
||||
{
|
||||
if (! latchNode)
|
||||
if (nullptr == latchNode)
|
||||
latchNode = pred;
|
||||
else if (pred->dfsLastNum > latchNode->dfsLastNum)
|
||||
latchNode = pred;
|
||||
@@ -314,7 +313,7 @@ void Function::structLoops(derSeq *derivedG)
|
||||
/* Check latching node is at the same nesting level of case
|
||||
* statements (if any) and that the node doesn't belong to
|
||||
* another loop. */
|
||||
if ((latchNode->caseHead == intHead->caseHead) &&
|
||||
if ((latchNode->caseHead == intHead->caseHead) and
|
||||
(latchNode->loopHead == NO_NODE))
|
||||
{
|
||||
intHead->latchNode = latchNode->dfsLastNum;
|
||||
@@ -353,7 +352,7 @@ static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
|
||||
|
||||
pBB->traversed = DFS_CASE;
|
||||
current = pBB->dfsLastNum;
|
||||
if ((current != tail) && (pBB->nodeType != MULTI_BRANCH) && (inList (l, pBB->immedDom)))
|
||||
if ((current != tail) and (pBB->nodeType != MULTI_BRANCH) and (inList (l, pBB->immedDom)))
|
||||
{
|
||||
insertList (l, current);
|
||||
pBB->caseHead = head;
|
||||
@@ -370,7 +369,7 @@ static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
|
||||
* has a case node. */
|
||||
void Function::structCases()
|
||||
{
|
||||
int exitNode = NO_NODE; /* case exit node */
|
||||
int exitNode = NO_NODE; /* case exit node */
|
||||
nodeList caseNodes; /* temporary: list of nodes in case */
|
||||
|
||||
/* Linear scan of the nodes in reverse dfsLast order, searching for
|
||||
@@ -385,7 +384,7 @@ void Function::structCases()
|
||||
* the current header node, and is not a successor. */
|
||||
for (size_t j = i + 2; j < numBBs; j++)
|
||||
{
|
||||
if ((!successor(j, i, this)) && (m_dfsLast[j]->immedDom == i))
|
||||
if ((not successor(j, i, this)) and (m_dfsLast[j]->immedDom == i))
|
||||
{
|
||||
if (exitNode == NO_NODE)
|
||||
{
|
||||
@@ -429,24 +428,24 @@ static void flagNodes (nodeList &l, int f, Function * pProc)
|
||||
/* Structures if statements */
|
||||
void Function::structIfs ()
|
||||
{
|
||||
size_t followInEdges; /* Largest # in-edges so far */
|
||||
int curr, /* Index for linear scan of nodes */
|
||||
/*desc,*/ /* Index for descendant */
|
||||
follow; /* Possible follow node */
|
||||
nodeList domDesc, /* List of nodes dominated by curr */
|
||||
unresolved /* List of unresolved if nodes */
|
||||
size_t followInEdges; /* Largest # in-edges so far */
|
||||
int curr, /* Index for linear scan of nodes */
|
||||
/*desc,*/ /* Index for descendant */
|
||||
follow; /* Possible follow node */
|
||||
nodeList domDesc, /* List of nodes dominated by curr */
|
||||
unresolved /* List of unresolved if nodes */
|
||||
;
|
||||
BB * currNode, /* Pointer to current node */
|
||||
BB * currNode, /* Pointer to current node */
|
||||
* pbb;
|
||||
|
||||
/* Linear scan of nodes in reverse dfsLast order */
|
||||
for (curr = numBBs - 1; curr >= 0; curr--)
|
||||
{
|
||||
currNode = m_dfsLast[curr];
|
||||
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
|
||||
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
|
||||
continue;
|
||||
|
||||
if ((currNode->nodeType == TWO_BRANCH) && (!currNode->back().ll()->testFlags(JX_LOOP)))
|
||||
if ((currNode->nodeType == TWO_BRANCH) and (not currNode->back().ll()->testFlags(JX_LOOP)))
|
||||
{
|
||||
followInEdges = 0;
|
||||
follow = 0;
|
||||
@@ -468,10 +467,10 @@ void Function::structIfs ()
|
||||
|
||||
/* Determine follow according to number of descendants
|
||||
* immediately dominated by this node */
|
||||
if ((follow != 0) && (followInEdges > 1))
|
||||
if ((follow != 0) and (followInEdges > 1))
|
||||
{
|
||||
currNode->ifFollow = follow;
|
||||
if (!unresolved.empty())
|
||||
if (not unresolved.empty())
|
||||
flagNodes (unresolved, follow, this);
|
||||
}
|
||||
else
|
||||
@@ -617,33 +616,33 @@ void Function::compoundCond()
|
||||
|
||||
change = true; //assume change
|
||||
|
||||
/* Check (X || Y) case */
|
||||
if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) &&
|
||||
(thenBB->inEdges.size() == 1) && (thenBB->edges[ELSE].BBptr == elseBB))
|
||||
/* Check (X or Y) case */
|
||||
if ((thenBB->nodeType == TWO_BRANCH) and (thenBB->numHlIcodes == 1) and
|
||||
(thenBB->inEdges.size() == 1) and (thenBB->edges[ELSE].BBptr == elseBB))
|
||||
{
|
||||
if(Case_X_or_Y(pbb, thenBB, elseBB))
|
||||
--i;
|
||||
}
|
||||
|
||||
/* Check (!X && Y) case */
|
||||
else if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) &&
|
||||
(thenBB->inEdges.size() == 1) && (thenBB->edges[THEN].BBptr == elseBB))
|
||||
/* Check (not X and Y) case */
|
||||
else if ((thenBB->nodeType == TWO_BRANCH) and (thenBB->numHlIcodes == 1) and
|
||||
(thenBB->inEdges.size() == 1) and (thenBB->edges[THEN].BBptr == elseBB))
|
||||
{
|
||||
if(Case_notX_and_Y(pbb, thenBB, elseBB))
|
||||
--i;
|
||||
}
|
||||
|
||||
/* Check (X && Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) &&
|
||||
(elseBB->inEdges.size()==1) && (elseBB->edges[THEN].BBptr == thenBB))
|
||||
/* Check (X and Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) and (elseBB->numHlIcodes == 1) and
|
||||
(elseBB->inEdges.size()==1) and (elseBB->edges[THEN].BBptr == thenBB))
|
||||
{
|
||||
if(Case_X_and_Y(pbb, thenBB, elseBB ))
|
||||
--i;
|
||||
}
|
||||
|
||||
/* Check (!X || Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) &&
|
||||
(elseBB->inEdges.size() == 1) && (elseBB->edges[ELSE].BBptr == thenBB))
|
||||
/* Check (not X or Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) and (elseBB->numHlIcodes == 1) and
|
||||
(elseBB->inEdges.size() == 1) and (elseBB->edges[ELSE].BBptr == thenBB))
|
||||
{
|
||||
if(Case_notX_or_Y(pbb, thenBB, elseBB ))
|
||||
--i;
|
||||
|
||||
280
src/dataflow.cpp
280
src/dataflow.cpp
@@ -4,18 +4,22 @@
|
||||
* Purpose: Data flow analysis module.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdio>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
using namespace boost;
|
||||
using namespace boost::adaptors;
|
||||
struct ExpStack
|
||||
@@ -28,7 +32,7 @@ struct ExpStack
|
||||
void push(Expr *);
|
||||
Expr * pop();
|
||||
Expr * top() const {
|
||||
if(!expStk.empty())
|
||||
if(not expStk.empty())
|
||||
return expStk.back();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -143,10 +147,9 @@ void Function::elimCondCodes ()
|
||||
//auto reversed_instructions = pBB->range() | reversed;
|
||||
for (useAt = pBB->rbegin(); useAt != pBB->rend(); useAt++)
|
||||
{
|
||||
ICODE &useIcode(*useAt);
|
||||
llIcode useAtOp = llIcode(useAt->ll()->getOpcode());
|
||||
use = useAt->ll()->flagDU.u;
|
||||
if ((useAt->type != LOW_LEVEL) || ( ! useAt->valid() ) || ( 0 == use ))
|
||||
if ((useAt->type != LOW_LEVEL_ICODE) or ( not useAt->valid() ) or ( 0 == use ))
|
||||
continue;
|
||||
/* Find definition within the same basic block */
|
||||
defAt=useAt;
|
||||
@@ -159,8 +162,7 @@ void Function::elimCondCodes ()
|
||||
continue;
|
||||
notSup = false;
|
||||
LLOperand *dest_ll = defIcode.ll()->get(DST);
|
||||
LLOperand *src_ll = defIcode.ll()->get(SRC);
|
||||
if ((useAtOp >= iJB) && (useAtOp <= iJNS))
|
||||
if ((useAtOp >= iJB) and (useAtOp <= iJNS))
|
||||
{
|
||||
iICODE befDefAt = (++riICODE(defAt)).base();
|
||||
switch (defIcode.ll()->getOpcode())
|
||||
@@ -194,9 +196,9 @@ void Function::elimCondCodes ()
|
||||
notSup = true;
|
||||
std::cout << hex<<defIcode.loc_ip;
|
||||
reportError (JX_NOT_DEF, defIcode.ll()->getOpcode());
|
||||
flg |= PROC_ASM; /* generate asm */
|
||||
flg |= PROC_ASM; /* generate asm */
|
||||
}
|
||||
if (! notSup)
|
||||
if (not notSup)
|
||||
{
|
||||
assert(lhs);
|
||||
assert(rhs);
|
||||
@@ -221,14 +223,14 @@ void Function::elimCondCodes ()
|
||||
{
|
||||
ICODE &a(*defAt);
|
||||
ICODE &b(*useAt);
|
||||
reportError (NOT_DEF_USE,a.ll()->getOpcode(),b.ll()->getOpcode());
|
||||
flg |= PROC_ASM; /* generate asm */
|
||||
reportError (NOT_DEF_USE,a.ll()->label,a.ll()->getOpcode(),b.ll()->getOpcode());
|
||||
flg |= PROC_ASM; /* generate asm */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for extended basic block */
|
||||
if ((pBB->size() == 1) &&(useAtOp >= iJB) && (useAtOp <= iJNS))
|
||||
if ((pBB->size() == 1) and(useAtOp >= iJB) and (useAtOp <= iJNS))
|
||||
{
|
||||
ICODE & _prev(pBB->back()); /* For extended basic blocks - previous icode inst */
|
||||
if (_prev.hl()->opcode == HLI_JCOND)
|
||||
@@ -267,10 +269,10 @@ void Function::genLiveKtes ()
|
||||
def.reset();
|
||||
pbb = m_dfsLast[i];
|
||||
if (pbb->flg & INVALID_BB)
|
||||
continue; // skip invalid BBs
|
||||
continue; // skip invalid BBs
|
||||
for(ICODE &insn : *pbb)
|
||||
{
|
||||
if ((insn.type == HIGH_LEVEL) && ( insn.valid() ))
|
||||
if ((insn.type == HIGH_LEVEL_ICODE) and ( insn.valid() ))
|
||||
{
|
||||
liveUse |= (insn.du.use - def);
|
||||
def |= insn.du.def;
|
||||
@@ -293,9 +295,9 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
Function * pcallee; /* invoked subroutine */
|
||||
//ICODE *ticode /* icode that invokes a subroutine */
|
||||
;
|
||||
LivenessSet prevLiveOut, /* previous live out */
|
||||
prevLiveIn; /* previous live in */
|
||||
bool change; /* is there change in the live sets?*/
|
||||
LivenessSet prevLiveOut, /* previous live out */
|
||||
prevLiveIn; /* previous live in */
|
||||
bool change; /* is there change in the live sets?*/
|
||||
|
||||
/* liveOut for this procedure */
|
||||
liveOut = in_liveOut;
|
||||
@@ -320,12 +322,12 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
pbb->liveOut = in_liveOut;
|
||||
|
||||
/* Get return expression of function */
|
||||
if (flg & PROC_IS_FUNC)
|
||||
if (getReturnType()!=TYPE_UNKNOWN)
|
||||
{
|
||||
auto picode = pbb->rbegin(); /* icode of function return */
|
||||
if (picode->hl()->opcode == HLI_RET)
|
||||
{
|
||||
picode->hlU()->expr(AstIdent::idID(&retVal, &localId, (++pbb->rbegin()).base()));
|
||||
picode->hlU()->expr(AstIdent::idID(&type->retVal, &localId, (++pbb->rbegin()).base()));
|
||||
picode->du.use = in_liveOut;
|
||||
}
|
||||
}
|
||||
@@ -344,7 +346,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
pcallee = ticode.hl()->call.proc;
|
||||
|
||||
/* user/runtime routine */
|
||||
if (! (pcallee->flg & PROC_ISLIB))
|
||||
if (not (pcallee->flg & PROC_ISLIB))
|
||||
{
|
||||
if (pcallee->liveAnal == false) /* hasn't been processed */
|
||||
pcallee->dataFlow (pbb->liveOut);
|
||||
@@ -352,7 +354,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
}
|
||||
else /* library routine */
|
||||
{
|
||||
if ( (pcallee->flg & PROC_IS_FUNC) && /* returns a value */
|
||||
if ( (pcallee->getReturnType()!=TYPE_UNKNOWN) and /* returns a value */
|
||||
(pcallee->liveOut & pbb->edges[0].BBptr->liveIn).any()
|
||||
)
|
||||
pbb->liveOut = pcallee->liveOut;
|
||||
@@ -360,10 +362,11 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
pbb->liveOut.reset();
|
||||
}
|
||||
|
||||
if ((! (pcallee->flg & PROC_ISLIB)) || ( pbb->liveOut.any() ))
|
||||
if ((not (pcallee->flg & PROC_ISLIB)) or ( pbb->liveOut.any() ))
|
||||
{
|
||||
switch (pcallee->retVal.type) {
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
switch (pcallee->getReturnType()) {
|
||||
case TYPE_LONG_SIGN:
|
||||
case TYPE_LONG_UNSIGN:
|
||||
ticode.du1.setDef(rAX).addDef(rDX);
|
||||
//TODO: use Calling convention to properly set regs here
|
||||
break;
|
||||
@@ -387,7 +390,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
pbb->liveIn = LivenessSet(pbb->liveUse + (pbb->liveOut - pbb->def));
|
||||
|
||||
/* Check if live sets have been modified */
|
||||
if ((prevLiveIn != pbb->liveIn) || (prevLiveOut != pbb->liveOut))
|
||||
if ((prevLiveIn != pbb->liveIn) or (prevLiveOut != pbb->liveOut))
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
@@ -414,9 +417,9 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
* register */
|
||||
bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
|
||||
{
|
||||
if ((regi == rDI) && (flg & DI_REGVAR))
|
||||
if ((regi == rDI) and (flg & DI_REGVAR))
|
||||
return true;
|
||||
if ((regi == rSI) && (flg & SI_REGVAR))
|
||||
if ((regi == rSI) and (flg & SI_REGVAR))
|
||||
return true;
|
||||
if (distance(start_at,end())>1) /* several instructions */
|
||||
{
|
||||
@@ -445,7 +448,7 @@ bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
|
||||
if (not ticode->du.def.testRegAndSubregs(regi) and liveOut.testRegAndSubregs(regi) )
|
||||
start_at->du.lastDefRegi.addReg(regi);
|
||||
}
|
||||
else /* only 1 instruction in this basic block */
|
||||
else /* only 1 instruction in this basic block */
|
||||
{
|
||||
/* Check if last definition of this register */
|
||||
if ( liveOut.testRegAndSubregs(regi) )
|
||||
@@ -459,7 +462,7 @@ bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
|
||||
* on optimized code. */
|
||||
void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
|
||||
{
|
||||
if (!((picode.hl()->opcode == HLI_CALL) && (picode.hl()->call.proc->flg & PROC_IS_FUNC)))
|
||||
if (not ((picode.hl()->opcode == HLI_CALL) and (picode.hl()->call.proc->getReturnType()!=TYPE_UNKNOWN)))
|
||||
return;
|
||||
|
||||
BB *tbb = this->edges[0].BBptr;
|
||||
@@ -477,7 +480,7 @@ void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
|
||||
/* if not used in this basic block, check if the
|
||||
* register is live out, if so, make it the last
|
||||
* definition of this register */
|
||||
if ( picode.du1.used(defRegIdx) && tbb->liveOut.testRegAndSubregs(regi))
|
||||
if ( picode.du1.used(defRegIdx) and tbb->liveOut.testRegAndSubregs(regi))
|
||||
picode.du.lastDefRegi.addReg(regi);
|
||||
}
|
||||
|
||||
@@ -486,15 +489,15 @@ void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
|
||||
* thus remove it. Also check that this is not a return
|
||||
* from a library function (routines such as printf
|
||||
* return an integer, which is normally not taken into
|
||||
* account by the programmer). */
|
||||
* account by the programmer). */
|
||||
void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode)
|
||||
{
|
||||
if (picode->valid() and not picode->du1.used(defRegIdx) and
|
||||
(not picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
|
||||
(not ((picode->hl()->opcode == HLI_CALL) &&
|
||||
(not picode->du.lastDefRegi.testRegAndSubregs(regi)) and
|
||||
(not ((picode->hl()->opcode == HLI_CALL) and
|
||||
(picode->hl()->call.proc->flg & PROC_ISLIB))))
|
||||
{
|
||||
if (! (this->liveOut.testRegAndSubregs(regi))) /* not liveOut */
|
||||
if (not (this->liveOut.testRegAndSubregs(regi))) /* not liveOut */
|
||||
{
|
||||
bool res = picode->removeDefRegi (regi, defRegIdx+1,&Parent->localId);
|
||||
if (res == true)
|
||||
@@ -509,7 +512,7 @@ void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode)
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* liveOut */
|
||||
else /* liveOut */
|
||||
picode->du.lastDefRegi.addReg(regi);
|
||||
}
|
||||
}
|
||||
@@ -542,7 +545,7 @@ void BB::genDU1()
|
||||
defRegIdx++;
|
||||
|
||||
/* Check if all defined registers have been processed */
|
||||
if ((defRegIdx >= picode->du1.getNumRegsDef()) || (defRegIdx == MAX_REGS_DEF))
|
||||
if ((defRegIdx >= picode->du1.getNumRegsDef()) or (defRegIdx == MAX_REGS_DEF))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -576,7 +579,7 @@ void LOCAL_ID::forwardSubs (Expr *lhs, Expr *rhs, iICODE picode, iICODE ticode,
|
||||
return;
|
||||
|
||||
/* Insert on rhs of ticode, if possible */
|
||||
res = Expr::insertSubTreeReg (ticode->hlU()->asgn.rhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this);
|
||||
res = Expr::insertSubTreeReg (ticode->hlU()->asgn.m_rhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this);
|
||||
if (res)
|
||||
{
|
||||
picode->invalidate();
|
||||
@@ -590,7 +593,7 @@ void LOCAL_ID::forwardSubs (Expr *lhs, Expr *rhs, iICODE picode, iICODE ticode,
|
||||
{
|
||||
eReg inserted = id_arr[lhs_reg->regiIdx].id.regi;
|
||||
eReg lhsReg = id_arr[op->regiIdx].id.regi;
|
||||
if((lhsReg==inserted)||Machine_X86::isSubRegisterOf(lhsReg,inserted))
|
||||
if((lhsReg==inserted) or Machine_X86::isSubRegisterOf(lhsReg,inserted))
|
||||
{
|
||||
// Do not replace ax = XYZ; given ax = H << P; with H << P =
|
||||
return;
|
||||
@@ -615,7 +618,7 @@ static void forwardSubsLong (int longIdx, Expr *_exp, iICODE picode, iICODE tico
|
||||
return;
|
||||
|
||||
/* Insert on rhs of ticode, if possible */
|
||||
res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.rhs, longIdx);
|
||||
res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.m_rhs, longIdx);
|
||||
if (res)
|
||||
{
|
||||
picode->invalidate();
|
||||
@@ -634,7 +637,7 @@ static void forwardSubsLong (int longIdx, Expr *_exp, iICODE picode, iICODE tico
|
||||
}
|
||||
|
||||
/* Returns whether the elements of the expression rhs are all x-clear from
|
||||
* instruction f up to instruction t. */
|
||||
* instruction f up to instruction t. */
|
||||
bool UnaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs)
|
||||
{
|
||||
if(nullptr==unaryExp)
|
||||
@@ -646,7 +649,7 @@ bool BinaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCA
|
||||
{
|
||||
if(nullptr==m_rhs)
|
||||
return false;
|
||||
if ( ! m_rhs->xClear (range_to_check, lastBBinst, locs) )
|
||||
if ( not m_rhs->xClear (range_to_check, lastBBinst, locs) )
|
||||
return false;
|
||||
if(nullptr==m_lhs)
|
||||
return false;
|
||||
@@ -669,9 +672,7 @@ int C_CallingConvention::processCArg (Function * callee, Function * pProc, ICODE
|
||||
Expr *_exp;
|
||||
bool res;
|
||||
int size_of_arg=0;
|
||||
PROG &prog(Project::get()->prog);
|
||||
|
||||
|
||||
Project &proj(*Project::get());
|
||||
/* if (numArgs == 0)
|
||||
return; */
|
||||
assert(pProc==g_exp_stk.func);
|
||||
@@ -691,8 +692,8 @@ int C_CallingConvention::processCArg (Function * callee, Function * pProc, ICODE
|
||||
}
|
||||
else {
|
||||
if(numArgs<callee->args.size()) {
|
||||
if(prog.addressingMode=='l') {
|
||||
if((callee->args[numArgs].type==TYPE_STR)||(callee->args[numArgs].type==TYPE_PTR)) {
|
||||
if(proj.getLoaderMetadata().compiler_memory_model==eLarge) {
|
||||
if((callee->args[numArgs].type==TYPE_STR) or (callee->args[numArgs].type==TYPE_PTR)) {
|
||||
RegisterNode *rn = dynamic_cast<RegisterNode *>(g_exp_stk.top());
|
||||
AstIdent *idn = dynamic_cast<AstIdent *>(g_exp_stk.top());
|
||||
if(rn) {
|
||||
@@ -719,7 +720,7 @@ int C_CallingConvention::processCArg (Function * callee, Function * pProc, ICODE
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* user function */
|
||||
else /* user function */
|
||||
{
|
||||
if (callee->args.numArgs > 0)
|
||||
{
|
||||
@@ -758,11 +759,11 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
||||
if(isLong)
|
||||
{
|
||||
forwardSubsLong (lhs_ident->ident.idNode.longIdx,
|
||||
p_hl.asgn.rhs, picode,ticode,
|
||||
p_hl.asgn.m_rhs, picode,ticode,
|
||||
&numHlIcodes);
|
||||
}
|
||||
else
|
||||
this->forwardSubs (lhs_ident, p_hl.asgn.rhs, picode, ticode, numHlIcodes);
|
||||
this->forwardSubs (lhs_ident, p_hl.asgn.m_rhs, picode, ticode, numHlIcodes);
|
||||
break;
|
||||
|
||||
case HLI_JCOND: case HLI_PUSH: case HLI_RET:
|
||||
@@ -770,7 +771,7 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
||||
{
|
||||
assert(lhs_ident);
|
||||
res = Expr::insertSubTreeLongReg (
|
||||
p_hl.asgn.rhs,
|
||||
p_hl.asgn.m_rhs,
|
||||
t_hl.exp.v,
|
||||
lhs_ident->ident.idNode.longIdx);
|
||||
}
|
||||
@@ -780,7 +781,7 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
||||
assert(lhs_reg);
|
||||
res = Expr::insertSubTreeReg (
|
||||
t_hl.exp.v,
|
||||
p_hl.asgn.rhs,
|
||||
p_hl.asgn.m_rhs,
|
||||
id_arr[lhs_reg->regiIdx].id.regi,
|
||||
this);
|
||||
}
|
||||
@@ -817,9 +818,9 @@ void C_CallingConvention::processHLI(Function *func,Expr *_exp, iICODE picode) {
|
||||
numArgs++;
|
||||
}
|
||||
}
|
||||
else if ((cb == 0) && picode->ll()->testFlags(REST_STK))
|
||||
else if ((cb == 0) and picode->ll()->testFlags(REST_STK))
|
||||
{
|
||||
while (! g_exp_stk.empty())
|
||||
while (not g_exp_stk.empty())
|
||||
{
|
||||
k+=processCArg (pp, func, &(*picode), numArgs);
|
||||
numArgs++;
|
||||
@@ -834,19 +835,19 @@ void Pascal_CallingConvention::processHLI(Function *func,Expr *_exp, iICODE pico
|
||||
int k;
|
||||
pp = picode->hl()->call.proc;
|
||||
|
||||
cb = pp->cbParam; /* fixed # arguments */
|
||||
cb = pp->cbParam; /* fixed # arguments */
|
||||
k = 0;
|
||||
numArgs = 0;
|
||||
while(k<cb)
|
||||
{
|
||||
_exp = g_exp_stk.pop();
|
||||
if (pp->flg & PROC_ISLIB) /* library function */
|
||||
if (pp->flg & PROC_ISLIB) /* library function */
|
||||
{
|
||||
if (pp->args.numArgs > 0)
|
||||
_exp = func->adjustActArgType(_exp, pp->args[numArgs].type);
|
||||
res = picode->newStkArg (_exp, (llIcode)picode->ll()->getOpcode(), func);
|
||||
}
|
||||
else /* user function */
|
||||
else /* user function */
|
||||
{
|
||||
if (pp->args.numArgs >0)
|
||||
{
|
||||
@@ -875,18 +876,19 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
{
|
||||
bool res;
|
||||
|
||||
ID *_retVal; // function return value
|
||||
Expr *_exp; // expression pointer - for HLI_POP and HLI_CALL */
|
||||
//Expr *lhs; // exp ptr for return value of a HLI_CALL */
|
||||
iICODE ticode; // Target icode */
|
||||
ID *_retVal; // function return value
|
||||
Expr *_exp; // expression pointer - for HLI_POP and HLI_CALL
|
||||
//Expr *lhs; // exp ptr for return value of a HLI_CALL
|
||||
iICODE ticode; // Target icode
|
||||
HLTYPE *ti_hl=nullptr;
|
||||
uint8_t regi;
|
||||
numHlIcodes = 0;
|
||||
assert(&fnc->localId==&locals);
|
||||
// register(s) to be forward substituted */
|
||||
auto valid_and_highlevel = instructions | filtered(ICODE::TypeAndValidFilter<HIGH_LEVEL>());
|
||||
// register(s) to be forward substituted
|
||||
auto valid_and_highlevel = instructions | filtered(ICODE::TypeAndValidFilter<HIGH_LEVEL_ICODE>());
|
||||
for (auto picode = valid_and_highlevel.begin(); picode != valid_and_highlevel.end(); picode++)
|
||||
{
|
||||
ICODE &_ic(*picode);
|
||||
HLTYPE &_icHl(*picode->hlU());
|
||||
numHlIcodes++;
|
||||
if (picode->du1.getNumRegsDef() == 1) /* uint8_t/uint16_t regs */
|
||||
@@ -908,12 +910,12 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
* icode expression */
|
||||
|
||||
ticode = picode->du1.idx[0].uses.front();
|
||||
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
|
||||
((ticode->hl()->opcode != HLI_CALL) &&
|
||||
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) and
|
||||
((ticode->hl()->opcode != HLI_CALL) and
|
||||
(ticode->hl()->opcode != HLI_RET)))
|
||||
continue;
|
||||
|
||||
if (_icHl.asgn.rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]),
|
||||
if (_icHl.asgn.m_rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]),
|
||||
end(), locals))
|
||||
{
|
||||
locals.processTargetIcode(picode.base(), numHlIcodes, ticode,false);
|
||||
@@ -927,8 +929,8 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
// call F() <- somehow this is marked as user of POP ?
|
||||
ticode = picode->du1.idx[0].uses.front();
|
||||
ti_hl = ticode->hlU();
|
||||
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
|
||||
((ti_hl->opcode != HLI_CALL) &&
|
||||
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) and
|
||||
((ti_hl->opcode != HLI_CALL) and
|
||||
(ti_hl->opcode != HLI_RET)))
|
||||
continue;
|
||||
|
||||
@@ -958,7 +960,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
newRegArg (pProc, picode, ticode);
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
break; */
|
||||
break; */
|
||||
default:
|
||||
fprintf(stderr,"unhandled BB::findBBExps target opcode %d\n",ticode->hl()->opcode);
|
||||
|
||||
@@ -968,14 +970,14 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
case HLI_CALL:
|
||||
ticode = picode->du1.idx[0].uses.front();
|
||||
ti_hl = ticode->hlU();
|
||||
_retVal = &_icHl.call.proc->retVal;
|
||||
_retVal = &_icHl.call.proc->type->retVal;
|
||||
switch (ti_hl->opcode)
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
assert(ti_hl->asgn.rhs);
|
||||
assert(ti_hl->asgn.m_rhs);
|
||||
_exp = _icHl.call.toAst();
|
||||
res = Expr::insertSubTreeReg (ti_hl->asgn.rhs,_exp, _retVal->id.regi, &locals);
|
||||
if (! res)
|
||||
res = Expr::insertSubTreeReg (ti_hl->asgn.m_rhs,_exp, _retVal->id.regi, &locals);
|
||||
if (not res)
|
||||
Expr::insertSubTreeReg (ti_hl->asgn.m_lhs, _exp,_retVal->id.regi, &locals);
|
||||
//TODO: HERE missing: 2 regs
|
||||
picode->invalidate();
|
||||
@@ -991,12 +993,12 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
case HLI_JCOND:
|
||||
_exp = _icHl.call.toAst();
|
||||
res = Expr::insertSubTreeReg (ti_hl->exp.v, _exp, _retVal->id.regi, &locals);
|
||||
if (res) /* was substituted */
|
||||
if (res) /* was substituted */
|
||||
{
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
}
|
||||
else /* cannot substitute function */
|
||||
else /* cannot substitute function */
|
||||
{
|
||||
auto lhs = AstIdent::idID(_retVal,&locals,picode.base());
|
||||
picode->setAsgn(lhs, _exp);
|
||||
@@ -1022,13 +1024,12 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
switch (_icHl.opcode)
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
/* Replace rhs of current icode into target
|
||||
* icode expression */
|
||||
/* Replace rhs of current icode into target icode expression */
|
||||
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
|
||||
{
|
||||
ticode = picode->du1.idx[0].uses.front();
|
||||
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
|
||||
((ticode->hl()->opcode != HLI_CALL) &&
|
||||
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) and
|
||||
((ticode->hl()->opcode != HLI_CALL) and
|
||||
(ticode->hl()->opcode != HLI_RET)))
|
||||
continue;
|
||||
locals.processTargetIcode(picode.base(), numHlIcodes, ticode,true);
|
||||
@@ -1039,18 +1040,19 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
|
||||
{
|
||||
ticode = picode->du1.idx[0].uses.front();
|
||||
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
|
||||
((ticode->hl()->opcode != HLI_CALL) &&
|
||||
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) and
|
||||
((ticode->hl()->opcode != HLI_CALL) and
|
||||
(ticode->hl()->opcode != HLI_RET)))
|
||||
continue;
|
||||
|
||||
_exp = g_exp_stk.pop(); /* pop last exp pushed */
|
||||
switch (ticode->hl()->opcode) {
|
||||
case HLI_ASSIGN:
|
||||
forwardSubsLong (dynamic_cast<AstIdent *>(_icHl.expr())->ident.idNode.longIdx,
|
||||
forwardSubsLong (static_cast<AstIdent *>(_icHl.expr())->ident.idNode.longIdx,
|
||||
_exp, picode.base(), ticode, &numHlIcodes);
|
||||
break;
|
||||
case HLI_JCOND: case HLI_PUSH:
|
||||
case HLI_JCOND:
|
||||
case HLI_PUSH:
|
||||
res = Expr::insertSubTreeLongReg (_exp,
|
||||
ticode->hlU()->exp.v,
|
||||
dynamic_cast<AstIdent *>(_icHl.asgn.lhs())->ident.idNode.longIdx);
|
||||
@@ -1060,7 +1062,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
numHlIcodes--;
|
||||
}
|
||||
break;
|
||||
case HLI_CALL: /*** missing ***/
|
||||
case HLI_CALL: /*** missing ***/
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"BB::findBBExps Unhandled target op %d\n",ticode->hl()->opcode);
|
||||
@@ -1078,7 +1080,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
AstIdent::Long(&locals, DST,
|
||||
ticode,HIGH_FIRST, picode.base(),
|
||||
eDEF, *(++iICODE(ticode))->ll()));
|
||||
ticode->hlU()->asgn.rhs = _exp;
|
||||
ticode->hlU()->asgn.m_rhs = _exp;
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
break;
|
||||
@@ -1092,16 +1094,16 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
|
||||
case HLI_JCOND:
|
||||
_exp = _icHl.call.toAst();
|
||||
_retVal = &picode->hl()->call.proc->retVal;
|
||||
_retVal = &picode->hl()->call.proc->type->retVal;
|
||||
res = Expr::insertSubTreeLongReg (_exp,
|
||||
ticode->hlU()->exp.v,
|
||||
locals.newLongReg ( _retVal->type, _retVal->longId(), picode.base()));
|
||||
if (res) /* was substituted */
|
||||
if (res) /* was substituted */
|
||||
{
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
}
|
||||
else /* cannot substitute function */
|
||||
else /* cannot substitute function */
|
||||
{
|
||||
auto lhs = locals.createId(_retVal,picode.base());
|
||||
picode->setAsgn(lhs, _exp);
|
||||
@@ -1117,6 +1119,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
} /* eos */
|
||||
}
|
||||
}
|
||||
|
||||
/* HLI_PUSH doesn't define any registers, only uses registers.
|
||||
* Push the associated expression to the register on the local
|
||||
* expression stack */
|
||||
@@ -1142,7 +1145,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
if ( not _icHl.call.proc->isLibrary() and (not picode->du1.used(0)) and (picode->du1.getNumRegsDef() > 0))
|
||||
{
|
||||
_exp = new FuncNode(_icHl.call.proc, _icHl.call.args);
|
||||
auto lhs = AstIdent::idID (&_icHl.call.proc->retVal, &locals, picode.base());
|
||||
auto lhs = AstIdent::idID (&_icHl.call.proc->type->retVal, &locals, picode.base());
|
||||
picode->setAsgn(lhs, _exp);
|
||||
}
|
||||
}
|
||||
@@ -1179,89 +1182,90 @@ void Function::preprocessReturnDU(LivenessSet &_liveOut)
|
||||
if(not _liveOut.any())
|
||||
return;
|
||||
}
|
||||
flg |= PROC_IS_FUNC;
|
||||
isAx = _liveOut.testReg(rAX);
|
||||
isBx = _liveOut.testReg(rBX);
|
||||
isCx = _liveOut.testReg(rCX);
|
||||
isDx = _liveOut.testReg(rDX);
|
||||
bool isAL = !isAx && _liveOut.testReg(rAL);
|
||||
bool isAH = !isAx && _liveOut.testReg(rAH);
|
||||
bool isBL = !isBx && _liveOut.testReg(rBL);
|
||||
bool isBH = !isBx && _liveOut.testReg(rBH);
|
||||
bool isCL = !isCx && _liveOut.testReg(rCL);
|
||||
bool isCH = !isCx && _liveOut.testReg(rCH);
|
||||
bool isDL = !isDx && _liveOut.testReg(rDL);
|
||||
bool isDH = !isDx && _liveOut.testReg(rDH);
|
||||
if(isAL && isAH)
|
||||
bool isAL = not isAx and _liveOut.testReg(rAL);
|
||||
bool isAH = not isAx and _liveOut.testReg(rAH);
|
||||
bool isBL = not isBx and _liveOut.testReg(rBL);
|
||||
bool isBH = not isBx and _liveOut.testReg(rBH);
|
||||
bool isCL = not isCx and _liveOut.testReg(rCL);
|
||||
bool isCH = not isCx and _liveOut.testReg(rCH);
|
||||
bool isDL = not isDx and _liveOut.testReg(rDL);
|
||||
bool isDH = not isDx and _liveOut.testReg(rDH);
|
||||
if(isAL and isAH)
|
||||
{
|
||||
isAx = true;
|
||||
isAH=isAL=false;
|
||||
}
|
||||
if(isDL && isDH)
|
||||
if(isDL and isDH)
|
||||
{
|
||||
isDx = true;
|
||||
isDH=isDL=false;
|
||||
}
|
||||
if(isBL && isBH)
|
||||
if(isBL and isBH)
|
||||
{
|
||||
isBx = true;
|
||||
isBH=isBL=false;
|
||||
}
|
||||
if(isCL && isCH)
|
||||
if(isCL and isCH)
|
||||
{
|
||||
isCx = true;
|
||||
isCH=isCL=false;
|
||||
}
|
||||
|
||||
if (isAx && isDx) /* long or pointer */
|
||||
if (isAx and isDx) /* long or pointer */
|
||||
{
|
||||
retVal.type = TYPE_LONG_SIGN;
|
||||
retVal.loc = REG_FRAME;
|
||||
retVal.longId() = LONGID_TYPE(rDX,rAX);
|
||||
type->setReturnType(TYPE_LONG_SIGN);
|
||||
type->m_call_conv->calculateStackLayout(this);
|
||||
/*idx = */localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), Icode.begin());
|
||||
localId.propLongId (rAX, rDX, "\0");
|
||||
localId.propLongId (rAX, rDX, "");
|
||||
}
|
||||
else if (isAx || isBx || isCx || isDx) /* uint16_t */
|
||||
else if (isAx or isBx or isCx or isDx) /* uint16_t */
|
||||
{
|
||||
retVal.type = TYPE_WORD_SIGN;
|
||||
retVal.loc = REG_FRAME;
|
||||
eReg selected_reg;
|
||||
if (isAx)
|
||||
retVal.id.regi = rAX;
|
||||
selected_reg = rAX;
|
||||
else if (isBx)
|
||||
retVal.id.regi = rBX;
|
||||
selected_reg = rBX;
|
||||
else if (isCx)
|
||||
retVal.id.regi = rCX;
|
||||
selected_reg = rCX;
|
||||
else
|
||||
retVal.id.regi = rDX;
|
||||
/*idx = */localId.newByteWordReg(TYPE_WORD_SIGN,retVal.id.regi);
|
||||
selected_reg = rDX;
|
||||
type->setReturnType(TYPE_WORD_SIGN);
|
||||
type->m_call_conv->calculateStackLayout(this);
|
||||
/*idx = */localId.newByteWordReg(TYPE_WORD_SIGN,selected_reg);
|
||||
}
|
||||
else if(isAL||isBL||isCL||isDL)
|
||||
else if(isAL or isBL or isCL or isDL)
|
||||
{
|
||||
retVal.type = TYPE_BYTE_SIGN;
|
||||
retVal.loc = REG_FRAME;
|
||||
eReg selected_reg;
|
||||
if (isAL)
|
||||
retVal.id.regi = rAL;
|
||||
selected_reg = rAL;
|
||||
else if (isBL)
|
||||
retVal.id.regi = rBL;
|
||||
selected_reg = rBL;
|
||||
else if (isCL)
|
||||
retVal.id.regi = rCL;
|
||||
selected_reg = rCL;
|
||||
else
|
||||
retVal.id.regi = rDL;
|
||||
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi);
|
||||
selected_reg = rDL;
|
||||
type->setReturnType(TYPE_BYTE_SIGN);
|
||||
type->m_call_conv->calculateStackLayout(this);
|
||||
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,selected_reg);
|
||||
}
|
||||
else if(isAH||isBH||isCH||isDH)
|
||||
else if(isAH or isBH or isCH or isDH)
|
||||
{
|
||||
retVal.type = TYPE_BYTE_SIGN;
|
||||
retVal.loc = REG_FRAME;
|
||||
eReg selected_reg;
|
||||
if (isAH)
|
||||
retVal.id.regi = rAH;
|
||||
selected_reg = rAH;
|
||||
else if (isBH)
|
||||
retVal.id.regi = rBH;
|
||||
selected_reg = rBH;
|
||||
else if (isCH)
|
||||
retVal.id.regi = rCH;
|
||||
selected_reg = rCH;
|
||||
else
|
||||
retVal.id.regi = rDH;
|
||||
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi);
|
||||
selected_reg = rDH;
|
||||
type->setReturnType(TYPE_BYTE_SIGN);
|
||||
type->m_call_conv->calculateStackLayout(this);
|
||||
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,selected_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1284,10 +1288,10 @@ void Function::dataFlow(LivenessSet &_liveOut)
|
||||
liveAnal = true;
|
||||
elimCondCodes();
|
||||
genLiveKtes();
|
||||
liveRegAnalysis (_liveOut); /* calls dataFlow() recursively */
|
||||
if (! (flg & PROC_ASM)) /* can generate C for pProc */
|
||||
liveRegAnalysis (_liveOut); /* calls dataFlow() recursively */
|
||||
if (not (flg & PROC_ASM)) /* can generate C for pProc */
|
||||
{
|
||||
genDU1 (); /* generate def/use level 1 chain */
|
||||
findExps (); /* forward substitution algorithm */
|
||||
genDU1 (); /* generate def/use level 1 chain */
|
||||
findExps (); /* forward substitution algorithm */
|
||||
}
|
||||
}
|
||||
|
||||
279
src/dcc.cpp
279
src/dcc.cpp
@@ -4,124 +4,123 @@
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include <cstring>
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "project.h"
|
||||
#include "CallGraph.h"
|
||||
#include "DccFrontend.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QtCore/QFile>
|
||||
#include "ui/DccMainWindow.h"
|
||||
|
||||
/* Global variables - extern to other modules */
|
||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
extern SYMTAB symtab; /* Global symbol table */
|
||||
extern STATS stats; /* cfg statistics */
|
||||
//PROG prog; /* programs fields */
|
||||
extern OPTION option; /* Command line options */
|
||||
//Function * pProcList; /* List of procedures, topologically sort */
|
||||
//Function * pLastProc; /* Pointer to last node in procedure list */
|
||||
//FunctionListType pProcList;
|
||||
//CALL_GRAPH *callGraph; /* Call graph of the program */
|
||||
extern QString asm1_name, asm2_name; /* Assembler output filenames */
|
||||
extern SYMTAB symtab; /* Global symbol table */
|
||||
extern STATS stats; /* cfg statistics */
|
||||
extern OPTION option; /* Command line options */
|
||||
|
||||
static char *initargs(int argc, char *argv[]);
|
||||
static void displayTotalStats(void);
|
||||
#include <llvm/Support/raw_os_ostream.h>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
#include <llvm/Support/TargetSelect.h>
|
||||
#include <llvm/Support/TargetRegistry.h>
|
||||
#include <llvm/Support/PrettyStackTrace.h>
|
||||
#include <llvm/Support/Signals.h>
|
||||
#include <llvm/Support/Host.h>
|
||||
#include <llvm/Target/TargetMachine.h>
|
||||
#include <llvm/Target/TargetInstrInfo.h>
|
||||
#include <llvm/MC/MCAsmInfo.h>
|
||||
#include <llvm/CodeGen/MachineInstrBuilder.h>
|
||||
|
||||
#include <llvm/TableGen/Main.h>
|
||||
#include <llvm/TableGen/TableGenBackend.h>
|
||||
#include <llvm/TableGen/Record.h>
|
||||
/****************************************************************************
|
||||
* main
|
||||
***************************************************************************/
|
||||
#include <iostream>
|
||||
using namespace llvm;
|
||||
bool TVisitor(raw_ostream &OS, RecordKeeper &Records)
|
||||
{
|
||||
Record *rec = Records.getDef("ADD8i8");
|
||||
if(rec)
|
||||
{
|
||||
if(not rec->getTemplateArgs().empty())
|
||||
std::cout << "Has template args\n";
|
||||
auto classes(rec->getSuperClasses());
|
||||
for(auto val : rec->getSuperClasses())
|
||||
std::cout << "Super "<<val->getName()<<"\n";
|
||||
|
||||
// DagInit * in = rec->getValueAsDag(val.getName());
|
||||
// in->dump();
|
||||
for(const RecordVal &val : rec->getValues())
|
||||
{
|
||||
// val.dump();
|
||||
}
|
||||
rec->dump();
|
||||
|
||||
void setupOptions(QCoreApplication &app) {
|
||||
//[-a1a2cmsi]
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("dcc");
|
||||
parser.addHelpOption();
|
||||
//parser.addVersionOption();
|
||||
//QCommandLineOption showProgressOption("p", QCoreApplication::translate("main", "Show progress during copy"));
|
||||
QCommandLineOption boolOpts[] {
|
||||
QCommandLineOption {"v", QCoreApplication::translate("main", "verbose")},
|
||||
QCommandLineOption {"V", QCoreApplication::translate("main", "very verbose")},
|
||||
QCommandLineOption {"c", QCoreApplication::translate("main", "Follow register indirect calls")},
|
||||
QCommandLineOption {"m", QCoreApplication::translate("main", "Print memory maps of program")},
|
||||
QCommandLineOption {"s", QCoreApplication::translate("main", "Print stats")}
|
||||
};
|
||||
for(QCommandLineOption &o : boolOpts) {
|
||||
parser.addOption(o);
|
||||
}
|
||||
// rec = Records.getDef("CCR");
|
||||
// if(rec)
|
||||
// rec->dump();
|
||||
for(auto val : Records.getDefs())
|
||||
{
|
||||
//std::cout<< "Def "<<val.first<<"\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int testTblGen(int argc, char **argv)
|
||||
{
|
||||
using namespace llvm;
|
||||
sys::PrintStackTraceOnErrorSignal();
|
||||
PrettyStackTraceProgram(argc,argv);
|
||||
cl::ParseCommandLineOptions(argc,argv);
|
||||
return llvm::TableGenMain(argv[0],TVisitor);
|
||||
InitializeNativeTarget();
|
||||
Triple TheTriple;
|
||||
std::string def = sys::getDefaultTargetTriple();
|
||||
std::string MCPU="i386";
|
||||
std::string MARCH="x86";
|
||||
InitializeAllTargetInfos();
|
||||
InitializeAllTargetMCs();
|
||||
InitializeAllAsmPrinters();
|
||||
InitializeAllAsmParsers();
|
||||
InitializeAllDisassemblers();
|
||||
std::string TargetTriple("i386-pc-linux-gnu");
|
||||
TheTriple = Triple(Triple::normalize(TargetTriple));
|
||||
MCOperand op=llvm::MCOperand::CreateImm(11);
|
||||
MCAsmInfo info;
|
||||
raw_os_ostream wrap(std::cerr);
|
||||
op.print(wrap,&info);
|
||||
wrap.flush();
|
||||
std::cerr<<"\n";
|
||||
std::string lookuperr;
|
||||
TargetRegistry::printRegisteredTargetsForVersion();
|
||||
const Target *t = TargetRegistry::lookupTarget(MARCH,TheTriple,lookuperr);
|
||||
TargetOptions opts;
|
||||
std::string Features;
|
||||
opts.PrintMachineCode=1;
|
||||
TargetMachine *tm = t->createTargetMachine(TheTriple.getTriple(),MCPU,Features,opts);
|
||||
std::cerr<<tm->getInstrInfo()->getName(97)<<"\n";
|
||||
const MCInstrDesc &ds(tm->getInstrInfo()->get(97));
|
||||
const MCOperandInfo *op1=ds.OpInfo;
|
||||
uint16_t impl_def = ds.getImplicitDefs()[0];
|
||||
std::cerr<<lookuperr<<"\n";
|
||||
QCommandLineOption assembly("a", QCoreApplication::translate("main", "Produce assembly"),"assembly_level");
|
||||
QCommandLineOption targetFileOption(QStringList() << "o" << "output",
|
||||
QCoreApplication::translate("main", "Place output into <file>."),
|
||||
QCoreApplication::translate("main", "file"));
|
||||
QCommandLineOption entryPointOption(QStringList() << "E",
|
||||
QCoreApplication::translate("main", "Custom entry point as hex"),
|
||||
QCoreApplication::translate("main", "offset"),
|
||||
"0"
|
||||
);
|
||||
parser.addOption(targetFileOption);
|
||||
parser.addOption(assembly);
|
||||
parser.addOption(entryPointOption);
|
||||
//parser.addOption(forceOption);
|
||||
// Process the actual command line arguments given by the user
|
||||
parser.addPositionalArgument("source", QCoreApplication::translate("main", "Dos Executable file to decompile."));
|
||||
parser.process(app);
|
||||
|
||||
exit(0);
|
||||
const QStringList args = parser.positionalArguments();
|
||||
if(args.empty()) {
|
||||
parser.showHelp();
|
||||
}
|
||||
// source is args.at(0), destination is args.at(1)
|
||||
option.verbose = parser.isSet(boolOpts[0]);
|
||||
option.VeryVerbose = parser.isSet(boolOpts[1]);
|
||||
if(parser.isSet(assembly)) {
|
||||
option.asm1 = parser.value(assembly).toInt()==1;
|
||||
option.asm2 = parser.value(assembly).toInt()==2;
|
||||
}
|
||||
option.Map = parser.isSet(boolOpts[3]);
|
||||
option.Stats = parser.isSet(boolOpts[4]);
|
||||
option.Interact = false;
|
||||
option.Calls = parser.isSet(boolOpts[2]);
|
||||
option.filename = args.first();
|
||||
option.CustomEntryPoint = parser.value(entryPointOption).toUInt(0,16);
|
||||
if(parser.isSet(targetFileOption))
|
||||
asm1_name = asm2_name = parser.value(targetFileOption);
|
||||
else if(option.asm1 or option.asm2) {
|
||||
asm1_name = option.filename+".a1";
|
||||
asm2_name = option.filename+".a2";
|
||||
}
|
||||
|
||||
}
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Extract switches and filename */
|
||||
strcpy(option.filename, initargs(argc, argv));
|
||||
QCoreApplication::setApplicationName("dcc");
|
||||
QCoreApplication::setApplicationVersion("0.2");
|
||||
if(argc==1) {
|
||||
QApplication app(argc,argv);
|
||||
DccMainWindow win;
|
||||
win.show();
|
||||
return app.exec();
|
||||
|
||||
}
|
||||
QCoreApplication app(argc,argv);
|
||||
|
||||
setupOptions(app);
|
||||
|
||||
Project *proj = Project::get();
|
||||
/* Front end reads in EXE or COM file, parses it into I-code while
|
||||
* building the call graph and attaching appropriate bits of code for
|
||||
* each procedure.
|
||||
*/
|
||||
DccFrontend fe(option.filename);
|
||||
proj->create(option.filename);
|
||||
|
||||
DccFrontend fe(&app);
|
||||
proj->addLoadCommands(option.filename);
|
||||
proj->processAllCommands();
|
||||
if(proj->m_error_state) {
|
||||
proj->dumpAllErrors();
|
||||
return -1;
|
||||
}
|
||||
if (option.verbose)
|
||||
proj->prog.displayLoadInfo();
|
||||
|
||||
if(false==fe.FrontEnd ())
|
||||
return -1;
|
||||
if(option.asm1)
|
||||
@@ -138,98 +137,16 @@ int main(int argc, char **argv)
|
||||
* analysis, data flow etc. and outputs it to output file ready for
|
||||
* re-compilation.
|
||||
*/
|
||||
BackEnd(asm1_name ? asm1_name:option.filename, Project::get()->callGraph);
|
||||
BackEnd(proj->callGraph);
|
||||
|
||||
Project::get()->callGraph->write();
|
||||
proj->callGraph->write();
|
||||
|
||||
if (option.Stats)
|
||||
displayTotalStats();
|
||||
|
||||
/*
|
||||
freeDataStructures(pProcList);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* initargs - Extract command line arguments
|
||||
***************************************************************************/
|
||||
static char *initargs(int argc, char *argv[])
|
||||
{
|
||||
char *pc;
|
||||
|
||||
while (--argc > 0 && (*++argv)[0] == '-')
|
||||
{
|
||||
for (pc = argv[0]+1; *pc; pc++)
|
||||
switch (*pc)
|
||||
{
|
||||
case 'a': /* Print assembler listing */
|
||||
if (*(pc+1) == '2')
|
||||
option.asm2 = true;
|
||||
else
|
||||
option.asm1 = true;
|
||||
if (*(pc+1) == '1' || *(pc+1) == '2')
|
||||
pc++;
|
||||
break;
|
||||
case 'c':
|
||||
option.Calls = true;
|
||||
break;
|
||||
case 'i':
|
||||
option.Interact = true;
|
||||
break;
|
||||
case 'm': /* Print memory map */
|
||||
option.Map = true;
|
||||
break;
|
||||
case 's': /* Print Stats */
|
||||
option.Stats = true;
|
||||
break;
|
||||
case 'V': /* Very verbose => verbose */
|
||||
option.VeryVerbose = true;
|
||||
case 'v':
|
||||
option.verbose = true; /* Make everything verbose */
|
||||
break;
|
||||
case 'o': /* assembler output file */
|
||||
if (*(pc+1)) {
|
||||
asm1_name = asm2_name = pc+1;
|
||||
goto NextArg;
|
||||
}
|
||||
else if (--argc > 0) {
|
||||
asm1_name = asm2_name = *++argv;
|
||||
goto NextArg;
|
||||
}
|
||||
default:
|
||||
fatalError(INVALID_ARG, *pc);
|
||||
return *argv;
|
||||
}
|
||||
NextArg:;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
if (option.asm1 || option.asm2)
|
||||
{
|
||||
if (! asm1_name)
|
||||
{
|
||||
asm1_name = strcpy((char*)malloc(strlen(*argv)+4), *argv);
|
||||
pc = strrchr(asm1_name, '.');
|
||||
if (pc > strrchr(asm1_name, '/'))
|
||||
{
|
||||
*pc = '\0';
|
||||
}
|
||||
asm2_name = (char*)malloc(strlen(asm1_name)+4) ;
|
||||
strcat(strcpy(asm2_name, asm1_name), ".a2");
|
||||
unlink(asm2_name);
|
||||
strcat(asm1_name, ".a1");
|
||||
}
|
||||
unlink(asm1_name); /* Remove asm output files */
|
||||
}
|
||||
return *argv; /* filename of the program to decompile */
|
||||
}
|
||||
|
||||
fatalError(USAGE);
|
||||
return *argv; // does not reach this.
|
||||
}
|
||||
|
||||
static void
|
||||
displayTotalStats ()
|
||||
/* Displays final statistics for the complete program */
|
||||
|
||||
35
src/dcc_interface.cpp
Normal file
35
src/dcc_interface.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "dcc_interface.h"
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
struct DccImpl : public IDcc {
|
||||
PtrFunction m_current_func;
|
||||
// IDcc interface
|
||||
public:
|
||||
bool load(QString name)
|
||||
{
|
||||
option.filename = name;
|
||||
Project::get()->create(name);
|
||||
return Project::get()->addLoadCommands(name);
|
||||
}
|
||||
void SetCurFunc_by_Name(QString v)
|
||||
{
|
||||
PtrFunction p(Project::get()->findByName(v));
|
||||
if(p!=nullptr)
|
||||
m_current_func = p;
|
||||
}
|
||||
QDir installDir() {
|
||||
return QDir(".");
|
||||
}
|
||||
QDir dataDir(QString kind) { // return directory containing decompilation helper data -> signatures/includes/etc.
|
||||
QDir res(installDir());
|
||||
res.cd(kind);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
IDcc* IDcc::get() {
|
||||
static IDcc *v=0;
|
||||
if(nullptr == v)
|
||||
v = new DccImpl;
|
||||
return v;
|
||||
}
|
||||
774
src/disassem.cpp
774
src/disassem.cpp
@@ -2,6 +2,15 @@
|
||||
* dcc project disassembler
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann
|
||||
****************************************************************************/
|
||||
#include "disassem.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "symtab.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QDebug>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@@ -9,11 +18,8 @@
|
||||
#include <iomanip>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "src/ui/StructuredTextTarget.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "symtab.h"
|
||||
#include "disassem.h"
|
||||
#include "project.h"
|
||||
// Note: for the time being, there is no interactive disassembler
|
||||
// for unix
|
||||
|
||||
@@ -23,7 +29,7 @@ using namespace std;
|
||||
#define POS_LAB 15 /* Position of label */
|
||||
#define POS_OPC 20 /* Position of opcode */
|
||||
#define POS_OPR 25 /* Position of operand */
|
||||
#define WID_PTR 10 /* Width of the "xword ptr" lingo */
|
||||
#define WID_PTR 10 /* Width of the "xword ptr" lingo */
|
||||
#define POS_OPR2 POS_OPR+WID_PTR /* Position of operand after "xword ptr" */
|
||||
#define POS_CMT 54 /* Position of comment */
|
||||
|
||||
@@ -70,8 +76,8 @@ static const char *szFlops3C[] =
|
||||
|
||||
static const char *szPtr[2] = { "word ptr ", "byte ptr " };
|
||||
|
||||
static void formatRM(ostringstream &p, const LLOperand &pm);
|
||||
static ostringstream &strDst(ostringstream &os, uint32_t flg, const LLOperand &pm);
|
||||
static void formatRM(QTextStream & p, const LLOperand &pm);
|
||||
static QTextStream & strDst(QTextStream & os, uint32_t flg, const LLOperand &pm);
|
||||
|
||||
static char *strHex(uint32_t d);
|
||||
//static int checkScanned(uint32_t pcCur);
|
||||
@@ -81,12 +87,12 @@ bool callArg(uint16_t off, char *temp); /* Check for procedure name */
|
||||
|
||||
//static FILE *dis_g_fp;
|
||||
static CIcodeRec pc;
|
||||
static int cb, j, numIcode, allocIcode;
|
||||
static int cb, numIcode, allocIcode;
|
||||
static map<int,int> pl;
|
||||
static uint32_t nextInst;
|
||||
static bool fImpure;
|
||||
//static bool fImpure;
|
||||
//static int g_lab;
|
||||
static Function * pProc; /* Points to current proc struct */
|
||||
static PtrFunction pProc; /* Points to current proc struct */
|
||||
|
||||
struct POSSTACK_ENTRY
|
||||
{
|
||||
@@ -102,12 +108,12 @@ static vector<POSSTACK_ENTRY> posStack; /* position stack */
|
||||
|
||||
#define printfd(x) printf(x)
|
||||
#define dis_newline() printf("\n")
|
||||
#define dis_show() // Nothing to do unless using Curses
|
||||
#define dis_show() // Nothing to do unless using Curses
|
||||
|
||||
|
||||
void LLInst::findJumpTargets(CIcodeRec &_pc)
|
||||
{
|
||||
if (testFlags(I) && ! testFlags(JMP_ICODE) && isJmpInst())
|
||||
if (srcIsImmed() and not testFlags(JMP_ICODE) and isJmpInst())
|
||||
{
|
||||
/* Replace the immediate operand with an icode index */
|
||||
iICODE labTgt=_pc.labelSrch(src().getImm2());
|
||||
@@ -128,12 +134,12 @@ void LLInst::findJumpTargets(CIcodeRec &_pc)
|
||||
}
|
||||
/*****************************************************************************
|
||||
* disassem - Prints a disassembled listing of a procedure.
|
||||
* pass == 1 generates output on file .a1
|
||||
* pass == 2 generates output on file .a2
|
||||
* pass == 3 generates output on file .b
|
||||
* pass == 1 generates output on file .a1
|
||||
* pass == 2 generates output on file .a2
|
||||
* pass == 3 generates output on file .b
|
||||
****************************************************************************/
|
||||
|
||||
void Disassembler::disassem(Function * ppProc)
|
||||
void Disassembler::disassem(PtrFunction ppProc)
|
||||
{
|
||||
|
||||
|
||||
@@ -150,11 +156,11 @@ void Disassembler::disassem(Function * ppProc)
|
||||
if (pass != 3)
|
||||
{
|
||||
auto p = (pass == 1)? asm1_name: asm2_name;
|
||||
m_fp.open(p,ios_base::app);
|
||||
if (!m_fp.is_open())
|
||||
{
|
||||
fatalError(CANNOT_OPEN, p);
|
||||
m_disassembly_target = new QFile(p);
|
||||
if(!m_disassembly_target->open(QFile::WriteOnly|QFile::Text|QFile::Append)) {
|
||||
fatalError(CANNOT_OPEN, p.toStdString().c_str());
|
||||
}
|
||||
m_fp.setDevice(m_disassembly_target);
|
||||
}
|
||||
/* Create temporary code array */
|
||||
// Mike: needs objectising!
|
||||
@@ -177,7 +183,7 @@ void Disassembler::disassem(Function * ppProc)
|
||||
/* Write procedure header */
|
||||
if (pass != 3)
|
||||
{
|
||||
std::string near_far=(pProc->flg & PROC_FAR)? "FAR": "NEAR";
|
||||
const char * near_far=(pProc->flg & PROC_FAR)? "FAR": "NEAR";
|
||||
m_fp << "\t\t"<<pProc->name<<" PROC "<< near_far<<"\n";
|
||||
}
|
||||
|
||||
@@ -192,7 +198,10 @@ void Disassembler::disassem(Function * ppProc)
|
||||
if (pass != 3)
|
||||
{
|
||||
m_fp << "\n\t\t"<<pProc->name<<" ENDP\n\n";
|
||||
m_fp.close();
|
||||
m_fp.setDevice(nullptr);
|
||||
m_disassembly_target->close();
|
||||
delete m_disassembly_target;
|
||||
|
||||
}
|
||||
|
||||
pc.clear();
|
||||
@@ -205,345 +214,7 @@ void Disassembler::disassem(Function * ppProc)
|
||||
****************************************************************************/
|
||||
void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
ostringstream oper_stream;
|
||||
ostringstream hex_bytes;
|
||||
ostringstream result_stream;
|
||||
ostringstream opcode_with_mods;
|
||||
ostringstream operands_s;
|
||||
oper_stream << uppercase;
|
||||
hex_bytes << uppercase;
|
||||
/* Disassembly stage 1 --
|
||||
* Do not try to display NO_CODE entries or synthetic instructions,
|
||||
* other than JMPs, that have been introduced for def/use analysis. */
|
||||
if ((option.asm1) &&
|
||||
( inst.testFlags(NO_CODE) ||
|
||||
(inst.testFlags(SYNTHETIC) && (inst.getOpcode() != iJMP))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (inst.testFlags(NO_CODE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (inst.testFlags(TARGET | CASE))
|
||||
{
|
||||
if (pass == 3)
|
||||
cCode.appendCode("\n"); /* Print to c code buffer */
|
||||
else
|
||||
m_fp<< "\n"; /* No, print to the stream */
|
||||
}
|
||||
|
||||
/* Find next instruction label and print hex bytes */
|
||||
if (inst.testFlags(SYNTHETIC))
|
||||
nextInst = inst.label;
|
||||
else
|
||||
{
|
||||
cb = (uint32_t) inst.numBytes;
|
||||
nextInst = inst.label + cb;
|
||||
|
||||
/* Output hexa code in program image */
|
||||
if (pass != 3)
|
||||
{
|
||||
for (j = 0; j < cb; j++)
|
||||
{
|
||||
hex_bytes << hex << setw(2) << setfill('0') << uint16_t(prog.image()[inst.label + j]);
|
||||
}
|
||||
hex_bytes << ' ';
|
||||
}
|
||||
}
|
||||
oper_stream << setw(POS_LAB) << left<< hex_bytes.str();
|
||||
/* Check if there is a symbol here */
|
||||
selectTable(Label);
|
||||
oper_stream << setw(5)<<left; // align for the labels
|
||||
{
|
||||
ostringstream lab_contents;
|
||||
if (readVal(lab_contents, inst.label, nullptr))
|
||||
{
|
||||
lab_contents << ':'; /* Also removes the null */
|
||||
}
|
||||
else if (inst.testFlags(TARGET)) /* Symbols override Lnn labels */
|
||||
{
|
||||
/* Print label */
|
||||
if (pl.count(loc_ip)==0)
|
||||
{
|
||||
pl[loc_ip] = ++g_lab;
|
||||
}
|
||||
lab_contents<< "L"<<pl[loc_ip]<<':';
|
||||
}
|
||||
oper_stream<< lab_contents.str();
|
||||
}
|
||||
if ((inst.getOpcode()==iSIGNEX )&& inst.testFlags(B))
|
||||
{
|
||||
inst.setOpcode(iCBW);
|
||||
}
|
||||
opcode_with_mods<<Machine_X86::opcodeName(inst.getOpcode());
|
||||
|
||||
switch ( inst.getOpcode() )
|
||||
{
|
||||
case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR:
|
||||
case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG:
|
||||
strDst(operands_s,inst.getFlag(), inst.m_dst);
|
||||
inst.strSrc(operands_s);
|
||||
break;
|
||||
|
||||
case iESC:
|
||||
inst.flops(operands_s);
|
||||
break;
|
||||
|
||||
case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
|
||||
case iROR:
|
||||
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
|
||||
if(inst.testFlags(I))
|
||||
inst.strSrc(operands_s);
|
||||
else
|
||||
operands_s<<", cl";
|
||||
break;
|
||||
|
||||
case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
|
||||
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
|
||||
break;
|
||||
|
||||
case iPUSH:
|
||||
if (inst.testFlags(I))
|
||||
{
|
||||
operands_s<<strHex(inst.src().getImm2());
|
||||
}
|
||||
else
|
||||
{
|
||||
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
|
||||
}
|
||||
break;
|
||||
|
||||
case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD:
|
||||
if (inst.testFlags(I))
|
||||
{
|
||||
strDst(operands_s,inst.getFlag(), inst.m_dst) <<", ";
|
||||
formatRM(operands_s, inst.src());
|
||||
inst.strSrc(operands_s);
|
||||
}
|
||||
else
|
||||
strDst(operands_s,inst.getFlag() | I, inst.src());
|
||||
break;
|
||||
|
||||
case iLDS: case iLES: case iBOUND:
|
||||
strDst(operands_s,inst.getFlag(), inst.m_dst)<<", dword ptr";
|
||||
inst.strSrc(operands_s,true);
|
||||
break;
|
||||
|
||||
case iJB: case iJBE: case iJAE: case iJA:
|
||||
case iJL: case iJLE: case iJGE: case iJG:
|
||||
case iJE: case iJNE: case iJS: case iJNS:
|
||||
case iJO: case iJNO: case iJP: case iJNP:
|
||||
case iJCXZ:case iLOOP: case iLOOPE:case iLOOPNE:
|
||||
case iJMP: case iJMPF:
|
||||
|
||||
/* Check if there is a symbol here */
|
||||
{
|
||||
ICODE *lab=pc.GetIcode(inst.src().getImm2());
|
||||
selectTable(Label);
|
||||
if ((inst.src().getImm2() < (uint32_t)numIcode) && /* Ensure in range */
|
||||
readVal(operands_s, lab->ll()->label, nullptr))
|
||||
{
|
||||
break; /* Symbolic label. Done */
|
||||
}
|
||||
}
|
||||
|
||||
if (inst.testFlags(NO_LABEL))
|
||||
{
|
||||
//strcpy(p + WID_PTR, strHex(pIcode->ll()->immed.op));
|
||||
operands_s<<strHex(inst.src().getImm2());
|
||||
}
|
||||
else if (inst.testFlags(I) )
|
||||
{
|
||||
j = inst.src().getImm2();
|
||||
if (pl.count(j)==0) /* Forward jump */
|
||||
{
|
||||
pl[j] = ++g_lab;
|
||||
}
|
||||
if (inst.getOpcode() == iJMPF)
|
||||
{
|
||||
operands_s<<" far ptr ";
|
||||
}
|
||||
operands_s<<"L"<<pl[j];
|
||||
}
|
||||
else if (inst.getOpcode() == iJMPF)
|
||||
{
|
||||
operands_s<<"dword ptr";
|
||||
inst.strSrc(operands_s,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
strDst(operands_s,I, inst.src());
|
||||
}
|
||||
break;
|
||||
|
||||
case iCALL: case iCALLF:
|
||||
if (inst.testFlags(I))
|
||||
{
|
||||
if((inst.getOpcode() == iCALL))
|
||||
operands_s<< "near";
|
||||
else
|
||||
operands_s<< " far";
|
||||
operands_s<<" ptr "<<(inst.src().proc.proc)->name;
|
||||
}
|
||||
else if (inst.getOpcode() == iCALLF)
|
||||
{
|
||||
operands_s<<"dword ptr ";
|
||||
inst.strSrc(operands_s,true);
|
||||
}
|
||||
else
|
||||
strDst(operands_s,I, inst.src());
|
||||
break;
|
||||
|
||||
case iENTER:
|
||||
operands_s<<strHex(inst.m_dst.off) << ", " << strHex(inst.src().getImm2());
|
||||
break;
|
||||
|
||||
case iRET: case iRETF: case iINT:
|
||||
if (inst.testFlags(I))
|
||||
{
|
||||
operands_s<<strHex(inst.src().getImm2());
|
||||
}
|
||||
break;
|
||||
|
||||
case iCMPS: case iREPNE_CMPS: case iREPE_CMPS:
|
||||
case iSCAS: case iREPNE_SCAS: case iREPE_SCAS:
|
||||
case iSTOS: case iREP_STOS:
|
||||
case iLODS: case iREP_LODS:
|
||||
case iMOVS: case iREP_MOVS:
|
||||
case iINS: case iREP_INS:
|
||||
case iOUTS: case iREP_OUTS:
|
||||
if (inst.src().segOver)
|
||||
{
|
||||
bool is_dx_src=(inst.getOpcode() == iOUTS || inst.getOpcode() == iREP_OUTS);
|
||||
if(is_dx_src)
|
||||
operands_s<<"dx, "<<szPtr[inst.getFlag() & B];
|
||||
else
|
||||
operands_s<<szPtr[inst.getFlag() & B];
|
||||
if (inst.getOpcode() == iLODS ||
|
||||
inst.getOpcode() == iREP_LODS ||
|
||||
inst.getOpcode() == iOUTS ||
|
||||
inst.getOpcode() == iREP_OUTS)
|
||||
{
|
||||
operands_s<<Machine_X86::regName(inst.src().segOver); // szWreg[src.segOver-rAX]
|
||||
}
|
||||
else
|
||||
{
|
||||
operands_s<<"es:[di], "<<Machine_X86::regName(inst.src().segOver);
|
||||
}
|
||||
operands_s<<":[si]";
|
||||
}
|
||||
else
|
||||
{
|
||||
(inst.getFlag() & B)? opcode_with_mods<< "B": opcode_with_mods<< "W";
|
||||
}
|
||||
break;
|
||||
|
||||
case iXLAT:
|
||||
if (inst.src().segOver)
|
||||
{
|
||||
operands_s<<" "<<szPtr[1];
|
||||
operands_s<<Machine_X86::regName(inst.src().segOver)<<":[bx]";
|
||||
}
|
||||
break;
|
||||
|
||||
case iIN:
|
||||
(inst.getFlag() & B)? operands_s<<"al, " : operands_s<< "ax, ";
|
||||
(inst.testFlags(I))? operands_s << strHex(inst.src().getImm2()) : operands_s<< "dx";
|
||||
break;
|
||||
|
||||
case iOUT:
|
||||
{
|
||||
std::string d1=((inst.testFlags(I))? strHex(inst.src().getImm2()): "dx");
|
||||
std::string d2=((inst.getFlag() & B) ? ", al": ", ax");
|
||||
operands_s<<d1 << d2;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
oper_stream << setw(15) << left <<opcode_with_mods.str();
|
||||
oper_stream << operands_s.str();
|
||||
/* Comments */
|
||||
if (inst.testFlags(SYNTHETIC))
|
||||
{
|
||||
fImpure = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = inst.label, fImpure = 0; j > 0 && j < (int)nextInst; j++)
|
||||
{
|
||||
fImpure |= BITMAP(j, BM_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
result_stream << setw(54) << left << oper_stream.str();
|
||||
/* Check for user supplied comment */
|
||||
selectTable(Comment);
|
||||
ostringstream cbuf;
|
||||
if (readVal(cbuf, inst.label, nullptr))
|
||||
{
|
||||
result_stream <<"; "<<cbuf.str();
|
||||
}
|
||||
else if (fImpure || (inst.testFlags(SWITCH | CASE | SEG_IMMED | IMPURE | SYNTHETIC | TERMINATES)))
|
||||
{
|
||||
if (inst.testFlags(CASE))
|
||||
{
|
||||
result_stream << ";Case l"<< inst.caseEntry;
|
||||
}
|
||||
if (inst.testFlags(SWITCH))
|
||||
{
|
||||
result_stream << ";Switch ";
|
||||
}
|
||||
if (fImpure)
|
||||
{
|
||||
result_stream << ";Accessed as data ";
|
||||
}
|
||||
if (inst.testFlags(IMPURE))
|
||||
{
|
||||
result_stream << ";Impure operand ";
|
||||
}
|
||||
if (inst.testFlags(SEG_IMMED))
|
||||
{
|
||||
result_stream << ";Segment constant";
|
||||
}
|
||||
if (inst.testFlags(TERMINATES))
|
||||
{
|
||||
result_stream << ";Exit to DOS";
|
||||
}
|
||||
}
|
||||
|
||||
/* Comment on iINT icodes */
|
||||
if (inst.getOpcode() == iINT)
|
||||
inst.writeIntComment(result_stream);
|
||||
|
||||
/* Display output line */
|
||||
if(pass==3)
|
||||
{
|
||||
/* output to .b code buffer */
|
||||
if (inst.testFlags(SYNTHETIC))
|
||||
result_stream<<";Synthetic inst";
|
||||
if (pass == 3) /* output to .b code buffer */
|
||||
cCode.appendCode("%s\n", result_stream.str().c_str());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[12];
|
||||
/* output to .a1 or .a2 file */
|
||||
if (not inst.testFlags(SYNTHETIC) )
|
||||
{
|
||||
sprintf(buf,"%03d %06X",loc_ip, inst.label);
|
||||
}
|
||||
else /* SYNTHETIC instruction */
|
||||
{
|
||||
sprintf(buf,"%03d ",loc_ip);
|
||||
result_stream<<";Synthetic inst";
|
||||
}
|
||||
m_fp<<buf<< " " << result_stream.str() << "\n";
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -551,7 +222,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
/****************************************************************************
|
||||
* formatRM
|
||||
***************************************************************************/
|
||||
static void formatRM(std::ostringstream &p, const LLOperand &pm)
|
||||
static void formatRM(QTextStream &p, const LLOperand &pm)
|
||||
{
|
||||
//char seg[4];
|
||||
|
||||
@@ -588,7 +259,7 @@ static void formatRM(std::ostringstream &p, const LLOperand &pm)
|
||||
/*****************************************************************************
|
||||
* strDst
|
||||
****************************************************************************/
|
||||
static ostringstream & strDst(ostringstream &os,uint32_t flg, const LLOperand &pm)
|
||||
static QTextStream & strDst(QTextStream &os,uint32_t flg, const LLOperand &pm)
|
||||
{
|
||||
/* Immediates to memory require size descriptor */
|
||||
//os << setw(WID_PTR);
|
||||
@@ -602,19 +273,19 @@ static ostringstream & strDst(ostringstream &os,uint32_t flg, const LLOperand &p
|
||||
/****************************************************************************
|
||||
* strSrc *
|
||||
****************************************************************************/
|
||||
ostringstream &LLInst::strSrc(ostringstream &os,bool skip_comma)
|
||||
{
|
||||
if(false==skip_comma)
|
||||
os<<", ";
|
||||
if (testFlags(I))
|
||||
os<<strHex(src().getImm2());
|
||||
else if (testFlags(IM_SRC)) /* level 2 */
|
||||
os<<"dx:ax";
|
||||
else
|
||||
formatRM(os, src());
|
||||
//QTextStream &LLInst::strSrc(QTextStream &os,bool skip_comma)
|
||||
//{
|
||||
// if(false==skip_comma)
|
||||
// os<<", ";
|
||||
// if (srcIsImmed())
|
||||
// os<<strHex(src().getImm2());
|
||||
// else if (testFlags(IM_SRC)) /* level 2 */
|
||||
// os<<"dx:ax";
|
||||
// else
|
||||
// formatRM(os, src());
|
||||
|
||||
return os;
|
||||
}
|
||||
// return os;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
@@ -633,14 +304,18 @@ static char *strHex(uint32_t d)
|
||||
/****************************************************************************
|
||||
* interactDis - interactive disassembler *
|
||||
****************************************************************************/
|
||||
void interactDis(Function * /*initProc*/, int /*initIC*/)
|
||||
void interactDis(const PtrFunction & initProc, int initIC)
|
||||
{
|
||||
printf("Sorry - interactive disasassembler option not available for Unix\n");
|
||||
QString procname = "UNKNOWN";
|
||||
if(initProc)
|
||||
procname = initProc->name;
|
||||
|
||||
qDebug() << "Wanted to start interactive disasassembler for "<<procname<<":"<<initIC;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle the floating point opcodes (icode iESC) */
|
||||
void LLInst::flops(std::ostringstream &out)
|
||||
void LLInst::flops(QTextStream &out)
|
||||
{
|
||||
//char bf[30];
|
||||
uint8_t op = (uint8_t)src().getImm2();
|
||||
@@ -652,38 +327,38 @@ void LLInst::flops(std::ostringstream &out)
|
||||
{
|
||||
/* The mod/rm mod bits are not set to 11 (i.e. register). This is the normal floating point opcode */
|
||||
out<<Machine_X86::floatOpName(op)<<' ';
|
||||
out <<setw(10);
|
||||
if ((op == 0x29) || (op == 0x1F))
|
||||
out.setFieldWidth(10);
|
||||
if ((op == 0x29) or (op == 0x1F))
|
||||
{
|
||||
out << "tbyte ptr ";
|
||||
}
|
||||
else switch (op & 0x30)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x10:
|
||||
out << "dword ptr ";
|
||||
case 0x00:
|
||||
case 0x10:
|
||||
out << "dword ptr ";
|
||||
break;
|
||||
case 0x20:
|
||||
out << "qword ptr ";
|
||||
break;
|
||||
case 0x30:
|
||||
switch (op)
|
||||
{
|
||||
case 0x3C: /* FBLD */
|
||||
case 0x3E: /* FBSTP */
|
||||
out << "tbyte ptr ";
|
||||
break;
|
||||
case 0x20:
|
||||
case 0x3D: /* FILD 64 bit */
|
||||
case 0x3F: /* FISTP 64 bit */
|
||||
out << "qword ptr ";
|
||||
break;
|
||||
case 0x30:
|
||||
switch (op)
|
||||
{
|
||||
case 0x3C: /* FBLD */
|
||||
case 0x3E: /* FBSTP */
|
||||
out << "tbyte ptr ";
|
||||
break;
|
||||
case 0x3D: /* FILD 64 bit */
|
||||
case 0x3F: /* FISTP 64 bit */
|
||||
out << "qword ptr ";
|
||||
break;
|
||||
|
||||
default:
|
||||
out << "uint16_t ptr ";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
out << "uint16_t ptr ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out.setFieldWidth(0);
|
||||
formatRM(out, m_dst);
|
||||
}
|
||||
else
|
||||
@@ -696,46 +371,271 @@ void LLInst::flops(std::ostringstream &out)
|
||||
int destRegIdx=m_dst.regi - rAX;
|
||||
switch (op)
|
||||
{
|
||||
case 0x0C:
|
||||
out << szFlops0C[destRegIdx];
|
||||
break;
|
||||
case 0x0D:
|
||||
out << szFlops0D[destRegIdx];
|
||||
break;
|
||||
case 0x0E:
|
||||
out << szFlops0E[destRegIdx];
|
||||
break;
|
||||
case 0x0F:
|
||||
out << szFlops0F[destRegIdx];
|
||||
break;
|
||||
case 0x15:
|
||||
out << szFlops15[destRegIdx];
|
||||
break;
|
||||
case 0x1C:
|
||||
out << szFlops1C[destRegIdx];
|
||||
break;
|
||||
case 0x33:
|
||||
out << szFlops33[destRegIdx];
|
||||
break;
|
||||
case 0x3C:
|
||||
out << szFlops3C[destRegIdx];
|
||||
break;
|
||||
default:
|
||||
out << Machine_X86::floatOpName(0x40+op);
|
||||
if ((op >= 0x20) && (op <= 0x27))
|
||||
{
|
||||
/* This is the ST(i), ST form. */
|
||||
out << "ST("<<destRegIdx - rAX<<"),ST";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ST, ST(i) */
|
||||
out << "ST,ST("<<destRegIdx;
|
||||
}
|
||||
case 0x0C:
|
||||
out << szFlops0C[destRegIdx];
|
||||
break;
|
||||
case 0x0D:
|
||||
out << szFlops0D[destRegIdx];
|
||||
break;
|
||||
case 0x0E:
|
||||
out << szFlops0E[destRegIdx];
|
||||
break;
|
||||
case 0x0F:
|
||||
out << szFlops0F[destRegIdx];
|
||||
break;
|
||||
case 0x15:
|
||||
out << szFlops15[destRegIdx];
|
||||
break;
|
||||
case 0x1C:
|
||||
out << szFlops1C[destRegIdx];
|
||||
break;
|
||||
case 0x33:
|
||||
out << szFlops33[destRegIdx];
|
||||
break;
|
||||
case 0x3C:
|
||||
out << szFlops3C[destRegIdx];
|
||||
break;
|
||||
default:
|
||||
out << Machine_X86::floatOpName(0x40+op);
|
||||
if ((op >= 0x20) and (op <= 0x27))
|
||||
{
|
||||
/* This is the ST(i), ST form. */
|
||||
out << "ST("<<destRegIdx - rAX<<"),ST";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ST, ST(i) */
|
||||
out << "ST,ST("<<destRegIdx;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
struct AsmFormatter {
|
||||
IStructuredTextTarget * target;
|
||||
int operand_count;
|
||||
void visitOperand(const LLOperand &pm) {
|
||||
if(not pm.isSet())
|
||||
return;
|
||||
if(operand_count>0) {
|
||||
target->prtt(", ");
|
||||
}
|
||||
operand_count++;
|
||||
if (pm.immed and not pm.isReg()) {
|
||||
//target->addTaggedString(XT_Keyword,szPtr[flg&B]);
|
||||
target->addTaggedString(XT_Number,strHex(pm.getImm2()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pm.segOver)
|
||||
{
|
||||
target->prtt(Machine_X86::regName(pm.segOver)+':');
|
||||
}
|
||||
|
||||
if (pm.regi == rUNDEF)
|
||||
{
|
||||
target->prtt(QString("[")+strHex((uint32_t)pm.off)+"]");
|
||||
}
|
||||
else if (pm.isReg())
|
||||
{
|
||||
target->prtt(Machine_X86::regName(pm.regi));
|
||||
}
|
||||
|
||||
else if (pm.off)
|
||||
{
|
||||
if (pm.off < 0)
|
||||
{
|
||||
target->prtt("["+Machine_X86::regName(pm.regi)+"-"+strHex((uint32_t)(- pm.off))+"]");
|
||||
}
|
||||
else
|
||||
{
|
||||
target->prtt("["+Machine_X86::regName(pm.regi)+"+"+strHex((uint32_t)(pm.off))+"]");
|
||||
}
|
||||
}
|
||||
else
|
||||
target->prtt("["+Machine_X86::regName(pm.regi)+"]");
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
|
||||
AsmFormatter formatter {out};
|
||||
const LLInst &inst(*insn);
|
||||
QString opcode = Machine_X86::opcodeName(insn->getOpcode());
|
||||
out->addSpace(4);
|
||||
out->addTaggedString(XT_Number,QString("%1").arg(insn->label,8,16,QChar('0').toUpper()));
|
||||
out->addSpace(4);
|
||||
|
||||
out->addTaggedString(XT_Keyword,Machine_X86::opcodeName(insn->getOpcode()),insn);
|
||||
out->addSpace(2);
|
||||
|
||||
switch(insn->getOpcode()) {
|
||||
case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR:
|
||||
case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG:
|
||||
|
||||
case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
|
||||
case iROR:
|
||||
formatter.visitOperand(insn->dst());
|
||||
formatter.visitOperand(insn->src());
|
||||
break;
|
||||
|
||||
case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
|
||||
formatter.visitOperand(insn->dst());
|
||||
break;
|
||||
case iPUSH:
|
||||
formatter.visitOperand(insn->dst());
|
||||
break;
|
||||
|
||||
case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD:
|
||||
if (inst.srcIsImmed())
|
||||
{
|
||||
formatter.visitOperand(insn->dst());
|
||||
formatter.visitOperand(insn->src());
|
||||
}
|
||||
else
|
||||
formatter.visitOperand(insn->dst());
|
||||
break;
|
||||
case iLDS: case iLES: case iBOUND:
|
||||
formatter.visitOperand(insn->dst());
|
||||
formatter.visitOperand(insn->src());
|
||||
break;
|
||||
case iJB: case iJBE: case iJAE: case iJA:
|
||||
case iJL: case iJLE: case iJGE: case iJG:
|
||||
case iJE: case iJNE: case iJS: case iJNS:
|
||||
case iJO: case iJNO: case iJP: case iJNP:
|
||||
case iJCXZ:case iLOOP: case iLOOPE:case iLOOPNE:
|
||||
case iJMP: case iJMPF:
|
||||
|
||||
/* Check if there is a symbol here */
|
||||
{
|
||||
// ICODE *lab=pc.GetIcode(inst.src().getImm2());
|
||||
// selectTable(Label);
|
||||
// if ((inst.src().getImm2() < (uint32_t)numIcode) and /* Ensure in range */
|
||||
// readVal(operands_s, lab->ll()->label, nullptr))
|
||||
// {
|
||||
// break; /* Symbolic label. Done */
|
||||
// }
|
||||
}
|
||||
if (inst.testFlags(NO_LABEL))
|
||||
{
|
||||
//strcpy(p + WID_PTR, strHex(pIcode->ll()->immed.op));
|
||||
out->addTaggedString(XT_AsmLabel,strHex(inst.src().getImm2()));
|
||||
}
|
||||
else if (inst.srcIsImmed() )
|
||||
{
|
||||
int64_t tgt_addr = inst.src().getImm2();
|
||||
if (inst.getOpcode() == iJMPF)
|
||||
{
|
||||
out->addTaggedString(XT_Keyword," far ptr ");
|
||||
}
|
||||
out->addTaggedString(XT_AsmLabel,QString("L_%1").arg(strHex(tgt_addr)));
|
||||
}
|
||||
else if (inst.getOpcode() == iJMPF)
|
||||
{
|
||||
out->addTaggedString(XT_Keyword,"dword ptr");
|
||||
formatter.visitOperand(inst.src());
|
||||
}
|
||||
else
|
||||
{
|
||||
formatter.visitOperand(inst.src());
|
||||
}
|
||||
|
||||
break;
|
||||
case iCALL: case iCALLF:
|
||||
if (inst.srcIsImmed())
|
||||
{
|
||||
out->addTaggedString(XT_Keyword,QString("%1 ptr ").arg((inst.getOpcode() == iCALL) ? "near" : "far"));
|
||||
out->addTaggedString(XT_AsmLabel,(inst.src().proc.proc)->name);
|
||||
}
|
||||
else if (inst.getOpcode() == iCALLF)
|
||||
{
|
||||
out->addTaggedString(XT_Keyword,"dword ptr ");
|
||||
formatter.visitOperand(inst.src());
|
||||
}
|
||||
else
|
||||
formatter.visitOperand(inst.src());
|
||||
break;
|
||||
|
||||
case iENTER:
|
||||
formatter.visitOperand(inst.dst());
|
||||
formatter.visitOperand(inst.src());
|
||||
break;
|
||||
|
||||
case iRET:
|
||||
case iRETF:
|
||||
case iINT:
|
||||
formatter.visitOperand(inst.src());
|
||||
break;
|
||||
|
||||
case iCMPS: case iREPNE_CMPS: case iREPE_CMPS:
|
||||
case iSCAS: case iREPNE_SCAS: case iREPE_SCAS:
|
||||
case iSTOS: case iREP_STOS:
|
||||
case iLODS: case iREP_LODS:
|
||||
case iMOVS: case iREP_MOVS:
|
||||
case iINS: case iREP_INS:
|
||||
case iOUTS: case iREP_OUTS:
|
||||
if (inst.src().segOver)
|
||||
{
|
||||
bool is_dx_src=(inst.getOpcode() == iOUTS or inst.getOpcode() == iREP_OUTS);
|
||||
if(is_dx_src)
|
||||
{
|
||||
out->addTaggedString(XT_Symbol,"dx");
|
||||
out->prtt(", ");
|
||||
out->addTaggedString(XT_Keyword,szPtr[inst.getFlag() & B]);
|
||||
out->addSpace(2);
|
||||
}
|
||||
else
|
||||
out->addTaggedString(XT_Keyword,szPtr[inst.getFlag() & B]);
|
||||
if (inst.getOpcode() == iLODS or
|
||||
inst.getOpcode() == iREP_LODS or
|
||||
inst.getOpcode() == iOUTS or
|
||||
inst.getOpcode() == iREP_OUTS)
|
||||
{
|
||||
out->addTaggedString(XT_Symbol,Machine_X86::regName(inst.src().segOver)); // szWreg[src.segOver-rAX]
|
||||
}
|
||||
else
|
||||
{
|
||||
out->addTaggedString(XT_Symbol,"es:[di]");
|
||||
out->prtt(", ");
|
||||
out->addTaggedString(XT_Symbol,Machine_X86::regName(inst.src().segOver));
|
||||
}
|
||||
out->addTaggedString(XT_Symbol,":[si]");
|
||||
}
|
||||
else
|
||||
{
|
||||
out->delChars(2); // TODO: this is wonky way of adding instruction suffix
|
||||
if(inst.getFlag() & B)
|
||||
out->addTaggedString(XT_Keyword,"B");
|
||||
else
|
||||
out->addTaggedString(XT_Keyword,"W");
|
||||
out->addSpace(2);
|
||||
}
|
||||
break;
|
||||
case iXLAT:
|
||||
if (inst.src().segOver)
|
||||
{
|
||||
out->addTaggedString(XT_Keyword,QString(" ") + szPtr[1]);
|
||||
out->addTaggedString(XT_Symbol,Machine_X86::regName(inst.src().segOver)+":[bx]");
|
||||
}
|
||||
break;
|
||||
|
||||
case iIN:
|
||||
out->addTaggedString(XT_Symbol, (inst.getFlag() & B)? "al" : "ax");
|
||||
out->prtt(", ");
|
||||
formatter.visitOperand(inst.src());
|
||||
break;
|
||||
|
||||
case iOUT:
|
||||
{
|
||||
formatter.visitOperand(inst.src());
|
||||
if(inst.srcIsImmed())
|
||||
out->addTaggedString(XT_Number, strHex(inst.src().getImm2()));
|
||||
else
|
||||
out->addTaggedString(XT_Symbol, "dx");
|
||||
out->prtt(", ");
|
||||
out->addTaggedString(XT_Symbol, (inst.getFlag() & B)? "al" : "ax");
|
||||
}
|
||||
}
|
||||
out->addEOL();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
{IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"},
|
||||
{DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"},
|
||||
{JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"},
|
||||
{NOT_DEF_USE ,"Def - use not supported. Def op = %d, use op = %d.\n"},
|
||||
{NOT_DEF_USE ,"%x: Def - use not supported. Def op = %d, use op = %d.\n"},
|
||||
{REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"},
|
||||
{WHILE_FAIL ,"Failed to construct while() condition.\n"},
|
||||
};
|
||||
|
||||
@@ -9,18 +9,15 @@
|
||||
* *
|
||||
\* * * * * * * * * * * * */
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include <memory.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef PATLEN
|
||||
#define PATLEN 23
|
||||
#define WILD 0xF4
|
||||
#endif
|
||||
|
||||
#ifndef bool
|
||||
#define bool unsigned char
|
||||
#define uint8_t unsigned char
|
||||
#endif
|
||||
|
||||
static int pc; /* Indexes into pat[] */
|
||||
|
||||
/* prototypes */
|
||||
@@ -193,7 +190,7 @@ void fixWildCards(uint8_t pat[])
|
||||
op = pat[pc++];
|
||||
if (pc >= PATLEN) return;
|
||||
|
||||
quad = (uint8_t) (op & 0xC0); /* Quadrant of the opcode map */
|
||||
quad = (uint8_t) (op & 0xC0); /* Quadrant of the opcode map */
|
||||
if (quad == 0)
|
||||
{
|
||||
/* Arithmetic group 00-3F */
|
||||
@@ -410,7 +407,7 @@ void fixWildCards(uint8_t pat[])
|
||||
|
||||
case 0xCD: /* int nn */
|
||||
intArg = pat[pc++];
|
||||
if ((intArg >= 0x34) && (intArg <= 0x3B))
|
||||
if ((intArg >= 0x34) and (intArg <= 0x3B))
|
||||
{
|
||||
/* Borland/Microsoft FP emulations */
|
||||
if (ModRM(pat)) return;
|
||||
|
||||
@@ -82,7 +82,7 @@ bool DccFrontend::FrontEnd ()
|
||||
|
||||
if (option.asm1)
|
||||
{
|
||||
printf("dcc: writing assembler file %s\n", asm1_name);
|
||||
printf("dcc: writing assembler file %s\n", asm1_name.c_str());
|
||||
}
|
||||
|
||||
/* Search through code looking for impure references and flag them */
|
||||
|
||||
@@ -1,24 +1,32 @@
|
||||
/*****************************************************************************
|
||||
* dcc project CFG related functions
|
||||
* dcc project CFG related functions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "graph.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <boost/range/rbegin.hpp>
|
||||
#include <boost/range/rend.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "graph.h"
|
||||
#include "project.h"
|
||||
#include <string.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
extern Project g_proj;
|
||||
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
|
||||
//static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
//static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
|
||||
|
||||
void Function::addOutEdgesForConditionalJump(BB * pBB,int next_ip, LLInst *ll)
|
||||
{
|
||||
pBB->addOutEdge(next_ip);
|
||||
/* This is checking for jumps off into nowhere */
|
||||
if ( not ll->testFlags(NO_LABEL) )
|
||||
pBB->addOutEdge(ll->src().getImm2());
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* createCFG - Create the basic control flow graph
|
||||
****************************************************************************/
|
||||
@@ -38,7 +46,7 @@ void Function::createCFG()
|
||||
|
||||
BB * psBB;
|
||||
BB * pBB;
|
||||
iICODE pIcode = Icode.begin();
|
||||
iICODE pIcode = Icode.begin();
|
||||
|
||||
stats.numBBbef = stats.numBBaft = 0;
|
||||
rICODE current_range=make_iterator_range(pIcode,++iICODE(pIcode));
|
||||
@@ -68,16 +76,13 @@ void Function::createCFG()
|
||||
case iJO: case iJNO: case iJP: case iJNP:
|
||||
case iJCXZ:
|
||||
pBB = BB::Create(current_range, TWO_BRANCH, this);
|
||||
CondJumps:
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
/* This is checking for jumps off into nowhere */
|
||||
if ( not ll->testFlags(NO_LABEL) )
|
||||
pBB->addOutEdge(ll->src().getImm2());
|
||||
addOutEdgesForConditionalJump(pBB,nextIcode->loc_ip, ll);
|
||||
break;
|
||||
|
||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||
pBB = BB::Create(current_range, LOOP_NODE, this);
|
||||
goto CondJumps;
|
||||
addOutEdgesForConditionalJump(pBB,nextIcode->loc_ip, ll);
|
||||
break;
|
||||
|
||||
case iJMPF: case iJMP:
|
||||
if (ll->testFlags(SWITCH))
|
||||
@@ -87,7 +92,7 @@ CondJumps:
|
||||
pBB->addOutEdge(elem);
|
||||
hasCase = true;
|
||||
}
|
||||
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
|
||||
else if (ll->srcIsImmed() and not ll->testFlags(NO_LABEL)) //TODO: WHY NO_LABEL TESTIT
|
||||
{
|
||||
pBB = BB::Create(current_range, ONE_BRANCH, this);
|
||||
pBB->addOutEdge(ll->src().getImm2());
|
||||
@@ -100,7 +105,7 @@ CondJumps:
|
||||
{
|
||||
Function * p = ll->src().proc.proc;
|
||||
pBB = BB::Create(current_range, CALL_NODE, this);
|
||||
if (p && not ((p->flg) & TERMINATES) )
|
||||
if (p and not ((p->flg) & TERMINATES) )
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
break;
|
||||
}
|
||||
@@ -132,6 +137,8 @@ CondJumps:
|
||||
// end iterator will be updated by expression in for statement
|
||||
current_range=make_iterator_range(nextIcode,nextIcode);
|
||||
}
|
||||
if (nextIcode == Icode.end())
|
||||
break;
|
||||
}
|
||||
for (auto pr : m_ip_to_bb)
|
||||
{
|
||||
@@ -146,7 +153,7 @@ CondJumps:
|
||||
}
|
||||
auto iter2=m_ip_to_bb.find(ip);
|
||||
if(iter2==m_ip_to_bb.end())
|
||||
fatalError(NO_BB, ip, name.c_str());
|
||||
fatalError(NO_BB, ip, qPrintable(name));
|
||||
psBB = iter2->second;
|
||||
elem.BBptr = psBB;
|
||||
psBB->inEdges.push_back((BB *)nullptr);
|
||||
@@ -197,13 +204,13 @@ void Function::freeCFG()
|
||||
void Function::compressCFG()
|
||||
{
|
||||
BB *pNxt;
|
||||
int ip, first=0, last;
|
||||
int ip, first=0, last;
|
||||
|
||||
/* First pass over BB list removes redundant jumps of the form
|
||||
* (Un)Conditional -> Unconditional jump */
|
||||
for (BB *pBB : m_actual_cfg) //m_cfg
|
||||
{
|
||||
if(pBB->inEdges.empty() || (pBB->nodeType != ONE_BRANCH && pBB->nodeType != TWO_BRANCH))
|
||||
if(pBB->inEdges.empty() or (pBB->nodeType != ONE_BRANCH and pBB->nodeType != TWO_BRANCH))
|
||||
continue;
|
||||
for (TYPEADR_TYPE &edgeRef : pBB->edges)
|
||||
{
|
||||
@@ -233,7 +240,7 @@ void Function::compressCFG()
|
||||
{
|
||||
if (pBB->inEdges.empty())
|
||||
{
|
||||
if (entry_node) /* Init it misses out on */
|
||||
if (entry_node) /* Init it misses out on */
|
||||
pBB->index = UN_INIT;
|
||||
else
|
||||
{
|
||||
@@ -265,7 +272,7 @@ BB *BB::rmJMP(int marker, BB * pBB)
|
||||
{
|
||||
marker += (int)DFS_JMP;
|
||||
|
||||
while (pBB->nodeType == ONE_BRANCH && pBB->size() == 1)
|
||||
while (pBB->nodeType == ONE_BRANCH and pBB->size() == 1)
|
||||
{
|
||||
if (pBB->traversed != marker)
|
||||
{
|
||||
@@ -292,7 +299,7 @@ BB *BB::rmJMP(int marker, BB * pBB)
|
||||
do {
|
||||
pBB = pBB->edges[0].BBptr;
|
||||
pBB->inEdges.pop_back(); // was --numInedges
|
||||
if (! pBB->inEdges.empty())
|
||||
if (not pBB->inEdges.empty())
|
||||
{
|
||||
pBB->front().ll()->setFlags(NO_CODE);
|
||||
pBB->front().invalidate();
|
||||
@@ -313,12 +320,12 @@ BB *BB::rmJMP(int marker, BB * pBB)
|
||||
****************************************************************************/
|
||||
void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
{
|
||||
BB * pChild;
|
||||
if (!this)
|
||||
BB * pChild;
|
||||
if (nullptr==this)
|
||||
{
|
||||
printf("mergeFallThrough on empty BB!\n");
|
||||
}
|
||||
while (nodeType == FALL_NODE || nodeType == ONE_BRANCH)
|
||||
while (nodeType == FALL_NODE or nodeType == ONE_BRANCH)
|
||||
{
|
||||
pChild = edges[0].BBptr;
|
||||
/* Jump to next instruction can always be removed */
|
||||
@@ -366,7 +373,7 @@ void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
****************************************************************************/
|
||||
void BB::dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last)
|
||||
{
|
||||
BB * pChild;
|
||||
BB * pChild;
|
||||
traversed = DFS_NUM;
|
||||
dfsFirstNum = (*first)++;
|
||||
|
||||
|
||||
186
src/hlicode.cpp
186
src/hlicode.cpp
@@ -4,17 +4,17 @@
|
||||
* Date: September-October 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#include "dcc.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "dcc.h"
|
||||
using namespace std;
|
||||
|
||||
static char buf[lineSize]; /* Line buffer for hl icode output */
|
||||
|
||||
|
||||
|
||||
/* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
|
||||
void HLTYPE::setAsgn(Expr *lhs, Expr *rhs)
|
||||
{
|
||||
@@ -24,12 +24,12 @@ void HLTYPE::setAsgn(Expr *lhs, Expr *rhs)
|
||||
}
|
||||
void ICODE::checkHlCall()
|
||||
{
|
||||
//assert((ll()->immed.proc.cb != 0)||ll()->immed.proc.proc!=0);
|
||||
//assert((ll()->immed.proc.cb != 0) or ll()->immed.proc.proc!=0);
|
||||
}
|
||||
/* Places the new HLI_CALL high-level operand in the high-level icode array */
|
||||
void ICODE::newCallHl()
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
type = HIGH_LEVEL_ICODE;
|
||||
hlU()->setCall(ll()->src().proc.proc);
|
||||
|
||||
if (ll()->src().proc.cb != 0)
|
||||
@@ -48,7 +48,7 @@ void ICODE::newCallHl()
|
||||
* array */
|
||||
void ICODE::setUnary(hlIcode op, Expr *_exp)
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
type = HIGH_LEVEL_ICODE;
|
||||
hlU()->set(op,_exp);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ void ICODE::setUnary(hlIcode op, Expr *_exp)
|
||||
/* Places the new HLI_JCOND high-level operand in the high-level icode array */
|
||||
void ICODE::setJCond(Expr *cexp)
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
type = HIGH_LEVEL_ICODE;
|
||||
hlU()->set(HLI_JCOND,cexp);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
|
||||
for ( ; numDefs > 0; numDefs--)
|
||||
{
|
||||
|
||||
if (du1.used(numDefs-1)||(du.lastDefRegi.testReg(regi)))
|
||||
if (du1.used(numDefs-1) or (du.lastDefRegi.testReg(regi)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -320,7 +320,7 @@ void Function::highLevelGen()
|
||||
LLOperand *src_ll = ll->get(SRC);
|
||||
if ( ll->testFlags(NOT_HLL) )
|
||||
pIcode->invalidate();
|
||||
if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() )
|
||||
if ((pIcode->type != LOW_LEVEL_ICODE) or not pIcode->valid() )
|
||||
continue;
|
||||
_flg = ll->getFlag();
|
||||
if (not ll->testFlags(IM_OPS)) /* not processing IM_OPS yet */
|
||||
@@ -328,11 +328,11 @@ void Function::highLevelGen()
|
||||
{
|
||||
if ( not ll->testFlags(NO_SRC) ) /* if there is src op */
|
||||
rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
|
||||
if(ll->m_dst.isSet() || (ll->getOpcode()==iMOD))
|
||||
if(ll->m_dst.isSet() or (ll->getOpcode()==iMOD))
|
||||
lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
|
||||
}
|
||||
if(ll->getOpcode()==iPUSH) {
|
||||
if(ll->testFlags(I)) {
|
||||
if(ll->srcIsImmed()) {
|
||||
lhs = new Constant(src_ll->opz,src_ll->byteWidth());
|
||||
}
|
||||
// lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
|
||||
@@ -353,7 +353,7 @@ void Function::highLevelGen()
|
||||
|
||||
case iCALL:
|
||||
case iCALLF:
|
||||
pIcode->type = HIGH_LEVEL;
|
||||
pIcode->type = HIGH_LEVEL_ICODE;
|
||||
pIcode->hl( ll->createCall() );
|
||||
break;
|
||||
|
||||
@@ -399,7 +399,8 @@ void Function::highLevelGen()
|
||||
}
|
||||
break;
|
||||
|
||||
case iMOV: pIcode->setAsgn(lhs, rhs);
|
||||
case iMOV:
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMUL:
|
||||
@@ -432,7 +433,8 @@ void Function::highLevelGen()
|
||||
break;
|
||||
|
||||
case iRET:
|
||||
case iRETF: pIcode->setUnary(HLI_RET, nullptr);
|
||||
case iRETF:
|
||||
pIcode->setUnary(HLI_RET, nullptr);
|
||||
break;
|
||||
|
||||
case iSHL:
|
||||
@@ -461,6 +463,8 @@ void Function::highLevelGen()
|
||||
rhs = new BinaryOperator(XOR,lhs, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
//TODO: default: // mostly to silence static analyzer warnings ?
|
||||
// delete rhs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,82 +481,68 @@ void Function::highLevelGen()
|
||||
|
||||
/* Returns the string that represents the procedure call of tproc (ie. with
|
||||
* actual parameters) */
|
||||
std::string Function::writeCall (Function * tproc, STKFRAME & args, int *numLoc)
|
||||
QString Function::writeCall (Function * tproc, STKFRAME & args, int *numLoc)
|
||||
{
|
||||
//string condExp;
|
||||
ostringstream ostr;
|
||||
ostr<<tproc->name<<" (";
|
||||
QString ostr;
|
||||
ostr+=tproc->name+" (";
|
||||
for(const STKSYM &sym : args)
|
||||
{
|
||||
if(sym.actual)
|
||||
ostr << sym.actual->walkCondExpr (this, numLoc);
|
||||
ostr += sym.actual->walkCondExpr(this, numLoc);
|
||||
else
|
||||
ostr << "";
|
||||
ostr += "";
|
||||
if((&sym)!=&(args.back()))
|
||||
ostr << ", ";
|
||||
ostr += ", ";
|
||||
}
|
||||
ostr << ")";
|
||||
return ostr.str();
|
||||
ostr += ")";
|
||||
return ostr;
|
||||
}
|
||||
|
||||
|
||||
/* Displays the output of a HLI_JCOND icode. */
|
||||
const char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
|
||||
QString writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
|
||||
{
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
strcat (buf, "if ");
|
||||
if(h.opcode==HLI_INVALID)
|
||||
{
|
||||
return "if (*HLI_INVALID*) {\n";
|
||||
}
|
||||
|
||||
assert(h.expr());
|
||||
Expr *inverted=h.expr()->inverse();
|
||||
//inverseCondOp (&h.exp);
|
||||
std::string e = inverted->walkCondExpr (pProc, numLoc);
|
||||
QString inverted_form = inverted->walkCondExpr (pProc, numLoc);
|
||||
delete inverted;
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, " {\n");
|
||||
return (buf);
|
||||
|
||||
return QString("if %1 {\n").arg(inverted_form);
|
||||
}
|
||||
|
||||
|
||||
/* Displays the inverse output of a HLI_JCOND icode. This is used in the case
|
||||
* when the THEN clause of an if..then..else is empty. The clause is
|
||||
* negated and the ELSE clause is used instead. */
|
||||
const char *writeJcondInv(HLTYPE h, Function * pProc, int *numLoc)
|
||||
* negated and the ELSE clause is used instead. */
|
||||
QString writeJcondInv(HLTYPE h, Function * pProc, int *numLoc)
|
||||
{
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
strcat (buf, "if ");
|
||||
std::string e;
|
||||
QString _form;
|
||||
|
||||
if(h.expr()==nullptr)
|
||||
e = "( *failed condition recovery* )";
|
||||
_form = "( *failed condition recovery* )";
|
||||
else
|
||||
e = h.expr()->walkCondExpr (pProc, numLoc);
|
||||
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, " {\n");
|
||||
return (buf);
|
||||
_form = h.expr()->walkCondExpr (pProc, numLoc);
|
||||
return QString("if %1 {\n").arg(_form);
|
||||
}
|
||||
|
||||
string AssignType::writeOut(Function *pProc, int *numLoc) const
|
||||
QString AssignType::writeOut(Function *pProc, int *numLoc) const
|
||||
{
|
||||
ostringstream ostr;
|
||||
ostr << m_lhs->walkCondExpr (pProc, numLoc);
|
||||
ostr << " = ";
|
||||
ostr << rhs->walkCondExpr (pProc, numLoc);
|
||||
ostr << ";\n";
|
||||
return ostr.str();
|
||||
return QString("%1 = %2;\n")
|
||||
.arg(m_lhs->walkCondExpr (pProc, numLoc))
|
||||
.arg(m_rhs->walkCondExpr (pProc, numLoc));
|
||||
}
|
||||
string CallType::writeOut(Function *pProc, int *numLoc) const
|
||||
QString CallType::writeOut(Function *pProc, int *numLoc) const
|
||||
{
|
||||
ostringstream ostr;
|
||||
ostr << pProc->writeCall (proc, *args, numLoc);
|
||||
ostr << ";\n";
|
||||
return ostr.str();
|
||||
return pProc->writeCall (proc, *args, numLoc) + ";\n";
|
||||
}
|
||||
string ExpType::writeOut(Function *pProc, int *numLoc) const
|
||||
QString ExpType::writeOut(Function *pProc, int *numLoc) const
|
||||
{
|
||||
if(v==nullptr)
|
||||
return "";
|
||||
@@ -567,44 +557,40 @@ void HLTYPE::set(Expr *l, Expr *r)
|
||||
//assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
|
||||
assert(dynamic_cast<UnaryOperator *>(l));
|
||||
asgn.m_lhs=l;
|
||||
asgn.rhs=r;
|
||||
asgn.m_rhs=r;
|
||||
}
|
||||
/* Returns a string with the contents of the current high-level icode.
|
||||
* Note: this routine does not output the contens of HLI_JCOND icodes. This is
|
||||
* done in a separate routine to be able to support the removal of
|
||||
* empty THEN clauses on an if..then..else. */
|
||||
string HLTYPE::write1HlIcode (Function * pProc, int *numLoc) const
|
||||
/** Returns a string with the contents of the current high-level icode.
|
||||
* \note this routine does not output the contens of HLI_JCOND icodes. This is
|
||||
* done in a separate routine to be able to support the removal of
|
||||
* empty THEN clauses on an if..then..else.
|
||||
*/
|
||||
QString HLTYPE::write1HlIcode (Function * pProc, int *numLoc) const
|
||||
{
|
||||
string e;
|
||||
ostringstream ostr;
|
||||
const HlTypeSupport *p = get();
|
||||
switch (opcode)
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_CALL:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_RET:
|
||||
e = p->writeOut(pProc,numLoc);
|
||||
if (! e.empty())
|
||||
ostr << "return (" << e << ");\n";
|
||||
break;
|
||||
case HLI_POP:
|
||||
ostr << "HLI_POP ";
|
||||
ostr << p->writeOut(pProc,numLoc);
|
||||
ostr << "\n";
|
||||
break;
|
||||
case HLI_PUSH:
|
||||
ostr << "HLI_PUSH ";
|
||||
ostr << p->writeOut(pProc,numLoc);
|
||||
ostr << "\n";
|
||||
break;
|
||||
case HLI_JCOND: //Handled elsewhere
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr," HLTYPE::write1HlIcode - Unhandled opcode %d\n",opcode);
|
||||
case HLI_ASSIGN:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_CALL:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_RET:
|
||||
{
|
||||
QString e;
|
||||
e = p->writeOut(pProc,numLoc);
|
||||
if (not e.isEmpty())
|
||||
return QString("return (%1);\n").arg(e);
|
||||
break;
|
||||
}
|
||||
return ostr.str();
|
||||
case HLI_POP:
|
||||
return QString("HLI_POP %1\n").arg(p->writeOut(pProc,numLoc));
|
||||
case HLI_PUSH:
|
||||
return QString("HLI_PUSH %1\n").arg(p->writeOut(pProc,numLoc));
|
||||
case HLI_JCOND: //Handled elsewhere
|
||||
break;
|
||||
default:
|
||||
qCritical() << " HLTYPE::write1HlIcode - Unhandled opcode" << opcode;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -619,16 +605,22 @@ void ICODE::writeDU()
|
||||
{
|
||||
int my_idx = loc_ip;
|
||||
{
|
||||
ostringstream ostr;
|
||||
Machine_X86::writeRegVector(ostr,du.def);
|
||||
if (!ostr.str().empty())
|
||||
printf ("Def (reg) = %s\n", ostr.str().c_str());
|
||||
QString ostr_contents;
|
||||
{
|
||||
QTextStream ostr(&ostr_contents);
|
||||
Machine_X86::writeRegVector(ostr,du.def);
|
||||
}
|
||||
if (not ostr_contents.isEmpty())
|
||||
qDebug() << QString("Def (reg) = %1\n").arg(ostr_contents);
|
||||
}
|
||||
{
|
||||
ostringstream ostr;
|
||||
Machine_X86::writeRegVector(ostr,du.use);
|
||||
if (!ostr.str().empty())
|
||||
printf ("Use (reg) = %s\n", ostr.str().c_str());
|
||||
QString ostr_contents;
|
||||
{
|
||||
QTextStream ostr(&ostr_contents);
|
||||
Machine_X86::writeRegVector(ostr,du.use);
|
||||
}
|
||||
if (not ostr_contents.isEmpty())
|
||||
qDebug() << QString("Use (reg) = %1\n").arg(ostr_contents);
|
||||
}
|
||||
|
||||
/* Print du1 chain */
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
// Object oriented icode code for dcc
|
||||
// (C) 1997 Mike Van Emmerik
|
||||
#include "icode.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "dcc.h"
|
||||
#include "types.h" // Common types like uint8_t, etc
|
||||
#include "ast.h" // Some icode types depend on these
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "types.h" // Common types like uint8_t, etc
|
||||
#include "ast.h" // Some icode types depend on these
|
||||
#include "icode.h"
|
||||
|
||||
|
||||
ICODE::TypeFilter<HIGH_LEVEL> ICODE::select_high_level;
|
||||
ICODE::TypeAndValidFilter<HIGH_LEVEL> ICODE::select_valid_high_level;
|
||||
ICODE::TypeFilter<HIGH_LEVEL_ICODE> ICODE::select_high_level;
|
||||
ICODE::TypeAndValidFilter<HIGH_LEVEL_ICODE> ICODE::select_valid_high_level;
|
||||
CIcodeRec::CIcodeRec()
|
||||
{
|
||||
}
|
||||
|
||||
/* Copies the icode that is pointed to by pIcode to the icode array.
|
||||
* If there is need to allocate extra memory, it is done so, and
|
||||
* the alloc variable is adjusted. */
|
||||
ICODE * CIcodeRec::addIcode(ICODE *pIcode)
|
||||
/* Copies the icode that is pointed to by pIcode to the icode array. */
|
||||
ICODE * CIcodeRec::addIcode(const ICODE *pIcode)
|
||||
{
|
||||
push_back(*pIcode);
|
||||
back().loc_ip = size()-1;
|
||||
@@ -67,6 +65,15 @@ extern bundle cCode;
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be backpatched
|
||||
* onto code in cCode.code */
|
||||
void LLInst::clrFlags(uint32_t flag)
|
||||
{
|
||||
if(getOpcode()==iMOD)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
flg &= ~flag;
|
||||
}
|
||||
|
||||
void LLInst::emitGotoLabel (int indLevel)
|
||||
{
|
||||
if ( not testFlags(HLL_LABEL) ) /* node hasn't got a lab */
|
||||
@@ -75,8 +82,7 @@ void LLInst::emitGotoLabel (int indLevel)
|
||||
hllLabNum = getNextLabel();
|
||||
setFlags(HLL_LABEL);
|
||||
|
||||
/* Node has been traversed already, so backpatch this label into
|
||||
* the code */
|
||||
/* Node has been traversed already, so backpatch this label into the code */
|
||||
cCode.code.addLabelBundle (codeIdx, hllLabNum);
|
||||
}
|
||||
cCode.appendCode( "%sgoto L%ld;\n", indentStr(indLevel), hllLabNum);
|
||||
@@ -87,9 +93,9 @@ void LLInst::emitGotoLabel (int indLevel)
|
||||
|
||||
bool LLOperand::isReg() const
|
||||
{
|
||||
return (regi>=rAX) && (regi<=rTMP);
|
||||
return (regi>=rAX) and (regi<=rTMP);
|
||||
}
|
||||
void LLOperand::addProcInformation(int param_count, CConv::Type call_conv)
|
||||
void LLOperand::addProcInformation(int param_count, CConv::CC_Type call_conv)
|
||||
{
|
||||
proc.proc->cbParam = (int16_t)param_count;
|
||||
proc.cb = param_count;
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include <llvm/Support/PatternMatch.h>
|
||||
#include <boost/iterator/filter_iterator.hpp>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
//#include <llvm/Config/llvm-config.h>
|
||||
//#if( (LLVM_VERSION_MAJOR==3 ) and (LLVM_VERSION_MINOR>3) )
|
||||
//#include <llvm/IR/PatternMatch.h>
|
||||
//#else
|
||||
//#include <llvm/Support/PatternMatch.h>
|
||||
//#endif
|
||||
#include "idiom.h"
|
||||
#include "idiom1.h"
|
||||
#include "epilogue_idioms.h"
|
||||
@@ -17,6 +19,11 @@
|
||||
#include "shift_idioms.h"
|
||||
#include "arith_idioms.h"
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <boost/iterator/filter_iterator.hpp>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
/*****************************************************************************
|
||||
* JmpInst - Returns true if opcode is a conditional or unconditional jump
|
||||
****************************************************************************/
|
||||
@@ -117,11 +124,10 @@ void Function::findIdioms()
|
||||
/* Check for library functions that return a long register.
|
||||
* Propagate this result */
|
||||
if (pIcode->ll()->src().proc.proc != nullptr)
|
||||
if ((pIcode->ll()->src().proc.proc->flg & PROC_ISLIB) &&
|
||||
(pIcode->ll()->src().proc.proc->flg & PROC_IS_FUNC))
|
||||
if ( pIcode->ll()->src().proc.proc->flg & PROC_ISLIB )
|
||||
{
|
||||
if ((pIcode->ll()->src().proc.proc->retVal.type==TYPE_LONG_SIGN)
|
||||
|| (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN))
|
||||
if ((pIcode->ll()->src().proc.proc->getReturnType()==TYPE_LONG_SIGN)
|
||||
or (pIcode->ll()->src().proc.proc->getReturnType() == TYPE_LONG_UNSIGN))
|
||||
localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), pIcode/*ip*/);
|
||||
}
|
||||
|
||||
@@ -181,7 +187,7 @@ void Function::findIdioms()
|
||||
(pIcode++)->invalidate();
|
||||
break;
|
||||
|
||||
case iENTER: /* ENTER is equivalent to init PUSH bp */
|
||||
case iENTER: /* ENTER is equivalent to init PUSH bp */
|
||||
if (pIcode == Icode.begin()) //ip == 0
|
||||
{
|
||||
flg |= (PROC_HLL | PROC_IS_HLL);
|
||||
@@ -204,10 +210,10 @@ void Function::findIdioms()
|
||||
}
|
||||
|
||||
/* Check if number of parameter bytes match their calling convention */
|
||||
if ((flg & PROC_HLL) && (!args.empty()))
|
||||
if ((flg & PROC_HLL) and (not args.empty()))
|
||||
{
|
||||
args.m_minOff += (flg & PROC_FAR ? 4 : 2);
|
||||
delta = args.maxOff - args.m_minOff;
|
||||
delta = args.m_maxOff - args.m_minOff;
|
||||
if (cbParam != delta)
|
||||
{
|
||||
cbParam = delta;
|
||||
@@ -231,7 +237,7 @@ void Function::bindIcodeOff()
|
||||
for(ICODE &c : Icode) // TODO: use filtered here
|
||||
{
|
||||
LLInst *ll=c.ll();
|
||||
if (ll->testFlags(I) && ll->isJmpInst())
|
||||
if (ll->srcIsImmed() and ll->isJmpInst())
|
||||
{
|
||||
iICODE loc=Icode.labelSrch(ll->src().getImm2());
|
||||
if (loc!=Icode.end())
|
||||
@@ -248,10 +254,10 @@ void Function::bindIcodeOff()
|
||||
LLInst *ll=icode.ll();
|
||||
if (not ll->isJmpInst())
|
||||
continue;
|
||||
if (ll->testFlags(I) )
|
||||
if (ll->srcIsImmed())
|
||||
{
|
||||
uint32_t found;
|
||||
if (! Icode.labelSrch(ll->src().getImm2(), found))
|
||||
if (not Icode.labelSrch(ll->src().getImm2(), found))
|
||||
ll->setFlags( NO_LABEL );
|
||||
else
|
||||
ll->replaceSrc(LLOperand::CreateImm2(found));
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#include "dcc.h"
|
||||
#include "arith_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -75,17 +80,17 @@ int Idiom6::action()
|
||||
/*****************************************************************************
|
||||
* idiom 18: Post-increment or post-decrement in a conditional jump
|
||||
* Used
|
||||
* 0 MOV reg, var (including register variables)
|
||||
* 1 INC var or DEC var <------------------------- input point
|
||||
* 2 CMP var, Y
|
||||
* 3 JX label
|
||||
* => HLI_JCOND (var++ X Y)
|
||||
* Eg: MOV ax, si
|
||||
* INC si
|
||||
* CMP ax, 8
|
||||
* JL labX
|
||||
* => HLI_JCOND (si++ < 8)
|
||||
* Found in Borland Turbo C. Intrinsic to C languages.
|
||||
* 0 MOV reg, var (including register variables)
|
||||
* 1 INC var or DEC var <------------------------- input point
|
||||
* 2 CMP var, Y
|
||||
* 3 JX label
|
||||
* => HLI_JCOND (var++ X Y)
|
||||
* Eg: MOV ax, si
|
||||
* INC si
|
||||
* CMP ax, 8
|
||||
* JL labX
|
||||
* => HLI_JCOND (si++ < 8)
|
||||
* Found in Borland Turbo C. Intrinsic to C languages.
|
||||
****************************************************************************/
|
||||
bool Idiom18::match(iICODE picode)
|
||||
{
|
||||
@@ -101,37 +106,38 @@ bool Idiom18::match(iICODE picode)
|
||||
m_idiom_type=-1;
|
||||
m_is_dec = m_icodes[1]->ll()->match(iDEC);
|
||||
|
||||
uint8_t regi; /* register of the MOV */
|
||||
uint8_t regi; /* register of the MOV */
|
||||
if(not m_icodes[0]->ll()->matchWithRegDst(iMOV) )
|
||||
return false;
|
||||
regi = m_icodes[0]->ll()->m_dst.regi;
|
||||
if( not ( m_icodes[2]->ll()->match(iCMP,regi) &&
|
||||
if( not ( m_icodes[2]->ll()->match(iCMP,regi) and
|
||||
m_icodes[3]->ll()->conditionalJump() ) )
|
||||
return false;
|
||||
// Simple matching finished, select apropriate matcher based on dst type
|
||||
/* Get variable */
|
||||
if (m_icodes[1]->ll()->m_dst.regi == 0) /* global variable */
|
||||
if (m_icodes[1]->ll()->m_dst.regi == 0) /* global variable */
|
||||
{
|
||||
/* not supported yet */
|
||||
m_idiom_type = 0;
|
||||
}
|
||||
else if ( m_icodes[1]->ll()->m_dst.isReg() ) /* register */
|
||||
else if ( m_icodes[1]->ll()->m_dst.isReg() ) /* register */
|
||||
{
|
||||
m_idiom_type = 1;
|
||||
// if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR))
|
||||
// if ((m_icodes[1]->ll()->dst.regi == rSI) and (m_func->flg & SI_REGVAR))
|
||||
// m_idiom_type = 1;
|
||||
// else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR))
|
||||
// else if ((m_icodes[1]->ll()->dst.regi == rDI) and (m_func->flg & DI_REGVAR))
|
||||
// m_idiom_type = 1;
|
||||
}
|
||||
else if (m_icodes[1]->ll()->m_dst.off) /* local variable */
|
||||
else if (m_icodes[1]->ll()->m_dst.off) /* local variable */
|
||||
m_idiom_type = 2;
|
||||
else /* indexed */
|
||||
else /* indexed */
|
||||
{
|
||||
m_idiom_type=3;
|
||||
/* not supported yet */
|
||||
ICODE &ic(*picode);
|
||||
const Function *my_proc(ic.getParent()->getParent());
|
||||
printf("Unsupported idiom18 type at %x in %s:%x : indexed\n",ic.loc_ip,my_proc->name.c_str(),my_proc->procEntry);
|
||||
qWarning() << "Unsupported idiom18 type at"<< QString::number(ic.loc_ip,16)
|
||||
<< "in"<< my_proc->name <<':'<< QString::number(my_proc->procEntry,16) << "- indexed";
|
||||
}
|
||||
|
||||
switch(m_idiom_type)
|
||||
@@ -181,13 +187,13 @@ int Idiom18::action() // action length
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom 19: pre-increment or pre-decrement in conditional jump, comparing against 0.
|
||||
* [INC | DEC] var (including register vars)
|
||||
* JX lab JX lab
|
||||
* => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0)
|
||||
* Eg: INC [bp+4]
|
||||
* [INC | DEC] var (including register vars)
|
||||
* JX lab JX lab
|
||||
* => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0)
|
||||
* Eg: INC [bp+4]
|
||||
* JG lab2
|
||||
* => HLI_JCOND (++[bp+4] > 0)
|
||||
* Found in Borland Turbo C. Intrinsic to C language.
|
||||
* => HLI_JCOND (++[bp+4] > 0)
|
||||
* Found in Borland Turbo C. Intrinsic to C language.
|
||||
****************************************************************************/
|
||||
bool Idiom19::match(iICODE picode)
|
||||
{
|
||||
@@ -200,19 +206,19 @@ bool Idiom19::match(iICODE picode)
|
||||
m_is_dec = m_icodes[0]->ll()->match(iDEC);
|
||||
if ( not m_icodes[1]->ll()->conditionalJump() )
|
||||
return false;
|
||||
if (m_icodes[0]->ll()->m_dst.regi == 0) /* global variable */
|
||||
if (m_icodes[0]->ll()->m_dst.regi == 0) /* global variable */
|
||||
/* not supported yet */ ;
|
||||
else if ( m_icodes[0]->ll()->m_dst.isReg() ) /* register */
|
||||
{
|
||||
// if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
|
||||
// ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
|
||||
// if (((picode->ll()->dst.regi == rSI) and (pproc->flg & SI_REGVAR)) or
|
||||
// ((picode->ll()->dst.regi == rDI) and (pproc->flg & DI_REGVAR)))
|
||||
return true;
|
||||
}
|
||||
else if (m_icodes[0]->ll()->m_dst.off) /* stack variable */
|
||||
else if (m_icodes[0]->ll()->m_dst.off) /* stack variable */
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else /* indexed */
|
||||
else /* indexed */
|
||||
{
|
||||
fprintf(stderr,"idiom19 : Untested type [indexed]\n");
|
||||
return true;
|
||||
@@ -235,23 +241,23 @@ int Idiom19::action()
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom20: Pre increment/decrement in conditional expression (compares
|
||||
* against a register, variable or constant different than 0).
|
||||
* INC var or DEC var (including register vars)
|
||||
* MOV reg, var MOV reg, var
|
||||
* CMP reg, Y CMP reg, Y
|
||||
* JX lab JX lab
|
||||
* => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
|
||||
* Eg: INC si (si is a register variable)
|
||||
* MOV ax, si
|
||||
* CMP ax, 2
|
||||
* JL lab4
|
||||
* => HLI_JCOND (++si < 2)
|
||||
* Found in Turbo C. Intrinsic to C language.
|
||||
* against a register, variable or constant different than 0).
|
||||
* INC var or DEC var (including register vars)
|
||||
* MOV reg, var MOV reg, var
|
||||
* CMP reg, Y CMP reg, Y
|
||||
* JX lab JX lab
|
||||
* => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
|
||||
* Eg: INC si (si is a register variable)
|
||||
* MOV ax, si
|
||||
* CMP ax, 2
|
||||
* JL lab4
|
||||
* => HLI_JCOND (++si < 2)
|
||||
* Found in Turbo C. Intrinsic to C language.
|
||||
****************************************************************************/
|
||||
bool Idiom20::match(iICODE picode)
|
||||
{
|
||||
uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
|
||||
uint8_t regi; /* register of the MOV */
|
||||
uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
|
||||
uint8_t regi; /* register of the MOV */
|
||||
if(std::distance(picode,m_end)<4)
|
||||
return false;
|
||||
for(int i=0; i<4; ++i)
|
||||
@@ -264,21 +270,21 @@ bool Idiom20::match(iICODE picode)
|
||||
|
||||
const LLOperand &ll_dest(m_icodes[0]->ll()->m_dst);
|
||||
/* Get variable */
|
||||
if (ll_dest.regi == 0) /* global variable */
|
||||
if (ll_dest.regi == 0) /* global variable */
|
||||
{
|
||||
/* not supported yet */ ;
|
||||
}
|
||||
else if ( ll_dest.isReg() ) /* register */
|
||||
else if ( ll_dest.isReg() ) /* register */
|
||||
{
|
||||
type = 1;
|
||||
// if ((ll_dest.regi == rSI) && (m_func->flg & SI_REGVAR))
|
||||
// if ((ll_dest.regi == rSI) and (m_func->flg & SI_REGVAR))
|
||||
// type = 1;
|
||||
// else if ((ll_dest.regi == rDI) && (m_func->flg & DI_REGVAR))
|
||||
// else if ((ll_dest.regi == rDI) and (m_func->flg & DI_REGVAR))
|
||||
// type = 1;
|
||||
}
|
||||
else if (ll_dest.off) /* local variable */
|
||||
else if (ll_dest.off) /* local variable */
|
||||
type = 2;
|
||||
else /* indexed */
|
||||
else /* indexed */
|
||||
{
|
||||
printf("idiom20 : Untested type [indexed]\n");
|
||||
type = 3;
|
||||
@@ -286,7 +292,7 @@ bool Idiom20::match(iICODE picode)
|
||||
}
|
||||
regi = m_icodes[1]->ll()->m_dst.regi;
|
||||
const LLOperand &mov_src(m_icodes[1]->ll()->src());
|
||||
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) && m_icodes[3]->ll()->conditionalJump())
|
||||
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) and m_icodes[3]->ll()->conditionalJump())
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "call_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
/*****************************************************************************
|
||||
* idiom3 - C calling convention.
|
||||
@@ -8,9 +11,9 @@ using namespace std;
|
||||
* Eg: CALL proc_X
|
||||
* ADD SP, 6
|
||||
* => pProc->cbParam = immed
|
||||
* Special case: when the call is at the end of the procedure,
|
||||
* sometimes the stack gets restored by a MOV sp, bp.
|
||||
* Need to flag the procedure in these cases.
|
||||
* Special case: when the call is at the end of the procedure,
|
||||
* sometimes the stack gets restored by a MOV sp, bp.
|
||||
* Need to flag the procedure in these cases.
|
||||
* Used by compilers to restore the stack when invoking a procedure using
|
||||
* the C calling convention.
|
||||
****************************************************************************/
|
||||
@@ -22,7 +25,7 @@ bool Idiom3::match(iICODE picode)
|
||||
/* Match ADD SP, immed */
|
||||
for(int i=0; i<2; ++i)
|
||||
m_icodes[i] = picode++;
|
||||
if ( m_icodes[1]->ll()->testFlags(I) && m_icodes[1]->ll()->match(iADD,rSP))
|
||||
if ( m_icodes[1]->ll()->srcIsImmed() and m_icodes[1]->ll()->match(iADD,rSP))
|
||||
{
|
||||
m_param_count = m_icodes[1]->ll()->src().getImm2();
|
||||
return true;
|
||||
@@ -36,7 +39,7 @@ bool Idiom3::match(iICODE picode)
|
||||
}
|
||||
int Idiom3::action()
|
||||
{
|
||||
if (m_icodes[0]->ll()->testFlags(I) )
|
||||
if (m_icodes[0]->ll()->srcIsImmed())
|
||||
{
|
||||
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::C);
|
||||
}
|
||||
@@ -78,10 +81,10 @@ bool Idiom17::match(iICODE picode)
|
||||
{
|
||||
int i=0;
|
||||
regi = m_icodes[1]->ll()->m_dst.regi;
|
||||
if ((regi >= rAX) && (regi <= rBX))
|
||||
if ((regi >= rAX) and (regi <= rBX))
|
||||
i++;
|
||||
|
||||
while (picode != m_end && picode->ll()->match(iPOP))
|
||||
while (picode != m_end and picode->ll()->match(iPOP))
|
||||
{
|
||||
if (picode->ll()->m_dst.regi != regi)
|
||||
break;
|
||||
@@ -94,7 +97,7 @@ bool Idiom17::match(iICODE picode)
|
||||
}
|
||||
int Idiom17::action()
|
||||
{
|
||||
if (m_icodes[0]->ll()->testFlags(I))
|
||||
if (m_icodes[0]->ll()->srcIsImmed())
|
||||
{
|
||||
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::C);
|
||||
for(size_t idx=1; idx<m_icodes.size(); ++idx)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "epilogue_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* popStkVars - checks for
|
||||
* [POP DI]
|
||||
@@ -14,9 +16,9 @@ void EpilogIdiom::popStkVars(iICODE pIcode)
|
||||
/* Match [POP DI] */
|
||||
if (pIcode->ll()->match(iPOP))
|
||||
{
|
||||
if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
|
||||
if ((m_func->flg & DI_REGVAR) and pIcode->ll()->match(rDI))
|
||||
m_icodes.push_front(pIcode);
|
||||
else if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
|
||||
else if ((m_func->flg & SI_REGVAR) and pIcode->ll()->match(rSI))
|
||||
m_icodes.push_front(pIcode);
|
||||
}
|
||||
++pIcode;
|
||||
@@ -25,9 +27,9 @@ void EpilogIdiom::popStkVars(iICODE pIcode)
|
||||
/* Match [POP SI] */
|
||||
if (pIcode->ll()->match(iPOP))
|
||||
{
|
||||
if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
|
||||
if ((m_func->flg & SI_REGVAR) and pIcode->ll()->match(rSI))
|
||||
m_icodes.push_front(pIcode);
|
||||
else if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
|
||||
else if ((m_func->flg & DI_REGVAR) and pIcode->ll()->match(rDI))
|
||||
m_icodes.push_front(pIcode);
|
||||
}
|
||||
}
|
||||
@@ -46,7 +48,7 @@ bool Idiom2::match(iICODE pIcode)
|
||||
iICODE nicode;
|
||||
if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0
|
||||
return false;
|
||||
if ( pIcode->ll()->testFlags(I) || (not pIcode->ll()->match(rSP,rBP)) )
|
||||
if ( pIcode->ll()->srcIsImmed() or (not pIcode->ll()->match(rSP,rBP)) )
|
||||
return false;
|
||||
if(distance(pIcode,m_end)<3)
|
||||
return false;
|
||||
@@ -55,21 +57,21 @@ bool Idiom2::match(iICODE pIcode)
|
||||
m_icodes.push_back(pIcode);
|
||||
/* Get next icode, skip over holes in the icode array */
|
||||
nicode = ++iICODE(pIcode);
|
||||
while (nicode->ll()->testFlags(NO_CODE) && (nicode != m_end))
|
||||
while (nicode->ll()->testFlags(NO_CODE) and (nicode != m_end))
|
||||
{
|
||||
nicode++;
|
||||
}
|
||||
if(nicode == m_end)
|
||||
return false;
|
||||
|
||||
if (nicode->ll()->match(iPOP,rBP) && ! (nicode->ll()->testFlags(I | TARGET | CASE)) )
|
||||
//TODO: strange test here - 'I' means instruction has immediate source operand
|
||||
if (nicode->ll()->match(iPOP,rBP) and not (nicode->ll()->testFlags(I | TARGET | CASE)) )
|
||||
{
|
||||
m_icodes.push_back(nicode++); // Matched POP BP
|
||||
|
||||
/* Match RET(F) */
|
||||
if ( nicode != m_end &&
|
||||
!(nicode->ll()->testFlags(I | TARGET | CASE)) &&
|
||||
(nicode->ll()->match(iRET) || nicode->ll()->match(iRETF))
|
||||
if ( nicode != m_end and
|
||||
not (nicode->ll()->testFlags(I | TARGET | CASE)) and
|
||||
nicode->ll()->matchAny({iRET,iRETF})
|
||||
)
|
||||
{
|
||||
m_icodes.push_back(nicode); // Matched RET
|
||||
@@ -93,15 +95,15 @@ int Idiom2::action()
|
||||
* RET(F) immed
|
||||
* ==> pProc->cbParam = immed
|
||||
* sets CALL_PASCAL flag
|
||||
* - Second version: check for optional pop of stack vars
|
||||
* - Second version: check for optional pop of stack vars
|
||||
* [POP DI]
|
||||
* [POP SI]
|
||||
* POP BP
|
||||
* RET(F) [immed]
|
||||
* - Third version: pop stack vars
|
||||
* [POP DI]
|
||||
* [POP SI]
|
||||
* RET(F) [immed]
|
||||
* - Third version: pop stack vars
|
||||
* [POP DI]
|
||||
* [POP SI]
|
||||
* RET(F) [immed]
|
||||
****************************************************************************/
|
||||
bool Idiom4::match(iICODE pIcode)
|
||||
{
|
||||
@@ -118,7 +120,7 @@ bool Idiom4::match(iICODE pIcode)
|
||||
{
|
||||
iICODE prev1 = --iICODE(pIcode);
|
||||
/* Check for POP BP */
|
||||
if (prev1->ll()->match(iPOP,rBP) && not prev1->ll()->testFlags(I) )
|
||||
if (prev1->ll()->match(iPOP,rBP) and not prev1->ll()->srcIsImmed() )
|
||||
m_icodes.push_back(prev1);
|
||||
else if(prev1!=m_func->Icode.begin())
|
||||
{
|
||||
@@ -129,7 +131,7 @@ bool Idiom4::match(iICODE pIcode)
|
||||
}
|
||||
|
||||
/* Check for RET(F) immed */
|
||||
if (pIcode->ll()->testFlags(I) )
|
||||
if (pIcode->ll()->srcIsImmed() )
|
||||
{
|
||||
m_param_count = (int16_t)pIcode->ll()->src().getImm2();
|
||||
return true;
|
||||
@@ -138,7 +140,7 @@ bool Idiom4::match(iICODE pIcode)
|
||||
}
|
||||
int Idiom4::action()
|
||||
{
|
||||
if( ! m_icodes.empty()) // if not an empty RET[F] N
|
||||
if( not m_icodes.empty()) // if not an empty RET[F] N
|
||||
{
|
||||
for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
|
||||
m_icodes[idx]->invalidate();
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "idiom1.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* checkStkVars - Checks for PUSH SI
|
||||
@@ -19,14 +22,14 @@ int Idiom1::checkStkVars (iICODE pIcode)
|
||||
{
|
||||
si_matched = 1;
|
||||
++pIcode;
|
||||
if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rDI)) // Look for PUSH DI
|
||||
if ((pIcode != m_end) and pIcode->ll()->match(iPUSH,rDI)) // Look for PUSH DI
|
||||
di_matched = 1;
|
||||
}
|
||||
else if (pIcode->ll()->match(iPUSH,rDI))
|
||||
{
|
||||
di_matched = 1;
|
||||
++pIcode;
|
||||
if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rSI)) // Look for PUSH SI
|
||||
if ((pIcode != m_end) and pIcode->ll()->match(iPUSH,rSI)) // Look for PUSH SI
|
||||
si_matched = 1;
|
||||
}
|
||||
m_func->flg |= (si_matched ? SI_REGVAR : 0) | (di_matched ? DI_REGVAR : 0);
|
||||
@@ -50,8 +53,8 @@ int Idiom1::checkStkVars (iICODE pIcode)
|
||||
****************************************************************************/
|
||||
bool Idiom1::match(iICODE picode)
|
||||
{
|
||||
//uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
|
||||
//uint8_t regi; /* register of the MOV */
|
||||
//uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
|
||||
//uint8_t regi; /* register of the MOV */
|
||||
if(m_func->flg & PROC_HLL)
|
||||
return false;
|
||||
if(picode==m_end)
|
||||
@@ -60,13 +63,13 @@ bool Idiom1::match(iICODE picode)
|
||||
m_icodes.clear();
|
||||
m_min_off = 0;
|
||||
/* PUSH BP as first instruction of procedure */
|
||||
if ( (not picode->ll()->testFlags(I)) && picode->ll()->src().regi == rBP)
|
||||
if ( (not picode->ll()->srcIsImmed()) and picode->ll()->src().regi == rBP)
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iPUSH
|
||||
if(picode==m_end)
|
||||
return false;
|
||||
/* MOV BP, SP as next instruction */
|
||||
if ( !picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iMOV ,rBP,rSP) )
|
||||
if ( not picode->ll()->testFlags(I | TARGET | CASE) and picode->ll()->match(iMOV ,rBP,rSP) )
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iMOV
|
||||
if(picode==m_end)
|
||||
@@ -75,7 +78,7 @@ bool Idiom1::match(iICODE picode)
|
||||
|
||||
/* Look for SUB SP, immed */
|
||||
if (
|
||||
picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iSUB,rSP)
|
||||
picode->ll()->testFlags(I | TARGET | CASE) and picode->ll()->match(iSUB,rSP)
|
||||
)
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iSUB
|
||||
@@ -98,18 +101,18 @@ bool Idiom1::match(iICODE picode)
|
||||
if(picode == m_end)
|
||||
return false;
|
||||
/* Look for MOV BP, SP */
|
||||
if ( picode != m_end &&
|
||||
!picode->ll()->testFlags(I | TARGET | CASE) &&
|
||||
if ( picode != m_end and
|
||||
not picode->ll()->testFlags(I | TARGET | CASE) and
|
||||
picode->ll()->match(iMOV,rBP,rSP))
|
||||
{
|
||||
m_icodes.push_back(picode);
|
||||
m_min_off = 2 + (n * 2);
|
||||
}
|
||||
else
|
||||
return false; // Cristina: check this please!
|
||||
return false; // Cristina: check this please!
|
||||
}
|
||||
else
|
||||
return false; // Cristina: check this please!
|
||||
return false; // Cristina: check this please!
|
||||
}
|
||||
}
|
||||
else // push di [push si] / push si [push di]
|
||||
@@ -119,7 +122,7 @@ bool Idiom1::match(iICODE picode)
|
||||
m_icodes.push_back(picode++);
|
||||
|
||||
}
|
||||
return !m_icodes.empty();
|
||||
return not m_icodes.empty();
|
||||
}
|
||||
int Idiom1::action()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "mov_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -9,14 +12,14 @@ using namespace std;
|
||||
* Eg: MOV ax, di
|
||||
* XOR dx, dx
|
||||
* => MOV dx:ax, di
|
||||
* Note: only the following combinations are allowed:
|
||||
* dx:ax
|
||||
* cx:bx
|
||||
* this is to remove the possibility of making errors in situations
|
||||
* like this:
|
||||
* MOV dx, offH
|
||||
* MOV ax, offL
|
||||
* XOR cx, cx
|
||||
* Note: only the following combinations are allowed:
|
||||
* dx:ax
|
||||
* cx:bx
|
||||
* this is to remove the possibility of making errors in situations
|
||||
* like this:
|
||||
* MOV dx, offH
|
||||
* MOV ax, offL
|
||||
* XOR cx, cx
|
||||
* Found in Borland Turbo C, used for division of unsigned integer
|
||||
* operands.
|
||||
****************************************************************************/
|
||||
@@ -27,20 +30,20 @@ bool Idiom14::match(iICODE pIcode)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
LLInst * matched [] = {m_icodes[0]->ll(),m_icodes[1]->ll()};
|
||||
LLInst * matched [] {m_icodes[0]->ll(),m_icodes[1]->ll()};
|
||||
/* Check for regL */
|
||||
m_regL = m_icodes[0]->ll()->m_dst.regi;
|
||||
if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX)))
|
||||
m_regL = matched[0]->m_dst.regi;
|
||||
if (not matched[0]->srcIsImmed() and ((m_regL == rAX) or (m_regL ==rBX)))
|
||||
{
|
||||
/* Check for XOR regH, regH */
|
||||
if (m_icodes[1]->ll()->match(iXOR) && not m_icodes[1]->ll()->testFlags(I))
|
||||
if (matched[1]->match(iXOR) and not matched[1]->srcIsImmed())
|
||||
{
|
||||
m_regH = m_icodes[1]->ll()->m_dst.regi;
|
||||
if (m_regH == m_icodes[1]->ll()->src().getReg2())
|
||||
m_regH = matched[1]->m_dst.regi;
|
||||
if (m_regH == matched[1]->src().getReg2())
|
||||
{
|
||||
if ((m_regL == rAX) && (m_regH == rDX))
|
||||
if ((m_regL == rAX) and (m_regH == rDX))
|
||||
return true;
|
||||
if ((m_regL == rBX) && (m_regH == rCX))
|
||||
if ((m_regL == rBX) and (m_regH == rCX))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -49,14 +52,11 @@ bool Idiom14::match(iICODE pIcode)
|
||||
}
|
||||
int Idiom14::action()
|
||||
{
|
||||
int idx;
|
||||
AstIdent *lhs;
|
||||
Expr *rhs;
|
||||
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]);
|
||||
lhs = AstIdent::LongIdx (idx);
|
||||
int idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]);
|
||||
AstIdent *lhs = AstIdent::LongIdx (idx);
|
||||
m_icodes[0]->setRegDU( m_regH, eDEF);
|
||||
rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
|
||||
Expr *rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
@@ -84,10 +84,10 @@ bool Idiom13::match(iICODE pIcode)
|
||||
|
||||
/* Check for regL */
|
||||
regi = m_icodes[0]->ll()->m_dst.regi;
|
||||
if (not m_icodes[0]->ll()->testFlags(I) && (regi >= rAL) && (regi <= rBH))
|
||||
if (not m_icodes[0]->ll()->srcIsImmed() and (regi >= rAL) and (regi <= rBH))
|
||||
{
|
||||
/* Check for MOV regH, 0 */
|
||||
if (m_icodes[1]->ll()->match(iMOV,I) && (m_icodes[1]->ll()->src().getImm2() == 0))
|
||||
if (m_icodes[1]->ll()->match(iMOV,I) and (m_icodes[1]->ll()->src().getImm2() == 0))
|
||||
{
|
||||
if (m_icodes[1]->ll()->m_dst.regi == (regi + 4)) //WARNING: based on distance between AH-AL,BH-BL etc.
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "neg_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
@@ -23,7 +26,7 @@ bool Idiom11::match (iICODE picode)
|
||||
for(int i=0; i<3; ++i)
|
||||
m_icodes[i]=picode++;
|
||||
type = m_icodes[0]->ll()->idType(DST);
|
||||
if(type==CONSTANT || type == OTHER)
|
||||
if(type==CONSTANT or type == OTHER)
|
||||
return false;
|
||||
/* Check NEG reg/mem
|
||||
* SBB reg/mem, 0*/
|
||||
@@ -32,7 +35,7 @@ bool Idiom11::match (iICODE picode)
|
||||
switch (type)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
if ((m_icodes[2]->ll()->m_dst.segValue == m_icodes[0]->ll()->m_dst.segValue) &&
|
||||
if ((m_icodes[2]->ll()->m_dst.segValue == m_icodes[0]->ll()->m_dst.segValue) and
|
||||
(m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off))
|
||||
return true;
|
||||
break;
|
||||
@@ -64,15 +67,15 @@ int Idiom11::action()
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom 16: Bitwise negation
|
||||
* NEG reg
|
||||
* SBB reg, reg
|
||||
* INC reg
|
||||
* => ASGN reg, !reg
|
||||
* Eg: NEG ax
|
||||
* SBB ax, ax
|
||||
* INC ax
|
||||
* => ax = !ax
|
||||
* Found in Borland Turbo C when negating bitwise.
|
||||
* NEG reg
|
||||
* SBB reg, reg
|
||||
* INC reg
|
||||
* => ASGN reg, !reg
|
||||
* Eg: NEG ax
|
||||
* SBB ax, ax
|
||||
* INC ax
|
||||
* => ax = !ax
|
||||
* Found in Borland Turbo C when negating bitwise.
|
||||
****************************************************************************/
|
||||
bool Idiom16::match (iICODE picode)
|
||||
{
|
||||
@@ -83,11 +86,11 @@ bool Idiom16::match (iICODE picode)
|
||||
m_icodes[i]=picode++;
|
||||
|
||||
uint8_t regi = m_icodes[0]->ll()->m_dst.regi;
|
||||
if ((regi >= rAX) && (regi < INDEX_BX_SI))
|
||||
if ((regi >= rAX) and (regi < INDEX_BX_SI))
|
||||
{
|
||||
if (m_icodes[1]->ll()->match(iSBB) && m_icodes[2]->ll()->match(iINC))
|
||||
if ((m_icodes[1]->ll()->m_dst.regi == (m_icodes[1]->ll()->src().getReg2())) &&
|
||||
m_icodes[1]->ll()->match((eReg)regi) &&
|
||||
if (m_icodes[1]->ll()->match(iSBB) and m_icodes[2]->ll()->match(iINC))
|
||||
if ((m_icodes[1]->ll()->m_dst.regi == (m_icodes[1]->ll()->src().getReg2())) and
|
||||
m_icodes[1]->ll()->match((eReg)regi) and
|
||||
m_icodes[2]->ll()->match((eReg)regi))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "shift_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
@@ -18,8 +21,8 @@ bool Idiom8::match(iICODE pIcode)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if ( m_icodes[1]->ll()->match(iRCR,I) &&
|
||||
if (m_icodes[0]->ll()->srcIsImmed() and (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if ( m_icodes[1]->ll()->match(iRCR,I) and
|
||||
(m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
return true;
|
||||
return false;
|
||||
@@ -62,7 +65,7 @@ bool Idiom15::match(iICODE pIcode)
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
/* Match SHL reg, 1 */
|
||||
if (not pIcode->ll()->testFlags(I) or (pIcode->ll()->src().getImm2() != 1))
|
||||
if (not pIcode->ll()->srcIsImmed() or (pIcode->ll()->src().getImm2() != 1))
|
||||
return false;
|
||||
m_icodes.clear();
|
||||
regi = pIcode->ll()->m_dst.regi;
|
||||
@@ -107,8 +110,8 @@ bool Idiom12::match(iICODE pIcode)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCL,I) && (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[0]->ll()->srcIsImmed() and (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCL,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -147,8 +150,8 @@ bool Idiom9::match(iICODE pIcode)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCR,I) && (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[0]->ll()->srcIsImmed() and (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCR,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
#include "dcc.h"
|
||||
#include "xor_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom21 - Assign long kte with high part zero
|
||||
* XOR regH, regH
|
||||
* MOV regL, kte
|
||||
* => regH:regL = kte
|
||||
* Eg: XOR dx, dx
|
||||
* MOV ax, 3
|
||||
* => dx:ax = 3
|
||||
* Note: only the following valid combinations are available:
|
||||
* dx:ax
|
||||
* cx:bx
|
||||
* Found in Borland Turbo C code.
|
||||
* XOR regH, regH
|
||||
* MOV regL, kte
|
||||
* => regH:regL = kte
|
||||
* Eg: XOR dx, dx
|
||||
* MOV ax, 3
|
||||
* => dx:ax = 3
|
||||
* Note: only the following valid combinations are available:
|
||||
* dx:ax
|
||||
* cx:bx
|
||||
* Found in Borland Turbo C code.
|
||||
****************************************************************************/
|
||||
bool Idiom21::match (iICODE picode)
|
||||
{
|
||||
@@ -23,16 +26,16 @@ bool Idiom21::match (iICODE picode)
|
||||
m_icodes[0]=picode++;
|
||||
m_icodes[1]=picode++;
|
||||
|
||||
if (not m_icodes[1]->ll()->testFlags(I))
|
||||
if (not m_icodes[1]->ll()->srcIsImmed())
|
||||
return false;
|
||||
|
||||
dst = &m_icodes[0]->ll()->m_dst;
|
||||
src = &m_icodes[0]->ll()->src();
|
||||
if ((dst->regi == src->getReg2()) && (dst->getReg2() > 0) && (dst->getReg2() < INDEX_BX_SI))
|
||||
if ((dst->regi == src->getReg2()) and (dst->getReg2() > 0) and (dst->getReg2() < INDEX_BX_SI))
|
||||
{
|
||||
if ((dst->getReg2() == rDX) && m_icodes[1]->ll()->match(rAX))
|
||||
if ((dst->getReg2() == rDX) and m_icodes[1]->ll()->match(rAX))
|
||||
return true;
|
||||
if ((dst->getReg2() == rCX) && m_icodes[1]->ll()->match(rBX))
|
||||
if ((dst->getReg2() == rCX) and m_icodes[1]->ll()->match(rBX))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -45,7 +48,7 @@ int Idiom21::action()
|
||||
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll());
|
||||
rhs = new Constant(m_icodes[1]->ll()->src().getImm2(), 4);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[0]->du.use.reset(); /* clear register used in iXOR */
|
||||
m_icodes[0]->du.use.reset(); /* clear register used in iXOR */
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
@@ -67,7 +70,7 @@ bool Idiom7::match(iICODE picode)
|
||||
src = &picode->ll()->src();
|
||||
if (dst->regi == 0) /* global variable */
|
||||
{
|
||||
if ((dst->segValue == src->segValue) && (dst->off == src->off))
|
||||
if ((dst->segValue == src->segValue) and (dst->off == src->off))
|
||||
return true;
|
||||
}
|
||||
else if (dst->regi < INDEX_BX_SI) /* register */
|
||||
@@ -75,17 +78,17 @@ bool Idiom7::match(iICODE picode)
|
||||
if (dst->regi == src->regi)
|
||||
return true;
|
||||
}
|
||||
else if ((dst->off) && (dst->seg == rSS) && (dst->regi == INDEX_BP)) /* offset from BP */
|
||||
else if ((dst->off) and (dst->seg == rSS) and (dst->regi == INDEX_BP)) /* offset from BP */
|
||||
{
|
||||
if ((dst->off == src->off) && (dst->seg == src->seg) && (dst->regi == src->regi))
|
||||
if ((dst->off == src->off) and (dst->seg == src->seg) and (dst->regi == src->regi))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom7::action()
|
||||
{
|
||||
Expr *lhs;
|
||||
lhs = AstIdent::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
|
||||
Expr *lhs = AstIdent::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
|
||||
|
||||
m_icode->setAsgn(dynamic_cast<AstIdent *>(lhs), new Constant(0, 2));
|
||||
m_icode->du.use.reset(); /* clear register used in iXOR */
|
||||
m_icode->ll()->setFlags(I);
|
||||
@@ -100,11 +103,11 @@ int Idiom7::action()
|
||||
* Eg: OR ax, ax
|
||||
* JNE labX
|
||||
* => CMP reg 0
|
||||
* JNE labX
|
||||
* This instruction is NOT converted into the equivalent high-level
|
||||
* instruction "HLI_JCOND (reg != 0) labX" because we do not know yet if
|
||||
* it forms part of a long register conditional test. It is therefore
|
||||
* modified to simplify the analysis.
|
||||
* JNE labX
|
||||
* This instruction is NOT converted into the equivalent high-level
|
||||
* instruction "HLI_JCOND (reg != 0) labX" because we do not know yet if
|
||||
* it forms part of a long register conditional test. It is therefore
|
||||
* modified to simplify the analysis.
|
||||
* Found in Borland Turbo C.
|
||||
****************************************************************************/
|
||||
bool Idiom10::match(iICODE pIcode)
|
||||
@@ -114,8 +117,8 @@ bool Idiom10::match(iICODE pIcode)
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
/* Check OR reg, reg */
|
||||
if (not m_icodes[0]->ll()->testFlags(I) &&
|
||||
m_icodes[0]->ll()->src().isReg() &&
|
||||
if (not m_icodes[0]->ll()->srcIsImmed() and
|
||||
m_icodes[0]->ll()->src().isReg() and
|
||||
(m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->m_dst.getReg2()))
|
||||
if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump()
|
||||
{
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
* Date: October 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#include "locident.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "locident.h"
|
||||
#include "dcc.h"
|
||||
|
||||
bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
|
||||
{
|
||||
return (a->ll()->src().getReg2()==m_l) and (b->ll()->m_dst.getReg2()==m_h);
|
||||
@@ -23,7 +26,7 @@ ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
|
||||
macro[0]=0;
|
||||
memset(&id,0,sizeof(id));
|
||||
loc=f;
|
||||
assert(not ((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN)));
|
||||
assert(not ((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN)));
|
||||
}
|
||||
ID::ID(hlType t,const LONGID_TYPE &s) : type(t),illegal(false),hasMacro(false)
|
||||
{
|
||||
@@ -31,7 +34,7 @@ ID::ID(hlType t,const LONGID_TYPE &s) : type(t),illegal(false),hasMacro(false)
|
||||
memset(&id,0,sizeof(id));
|
||||
loc=REG_FRAME;
|
||||
m_longId = s;
|
||||
assert((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN));
|
||||
assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
|
||||
}
|
||||
ID::ID(hlType t,const LONG_STKID_TYPE &s) : type(t),illegal(false),hasMacro(false)
|
||||
{
|
||||
@@ -39,7 +42,7 @@ ID::ID(hlType t,const LONG_STKID_TYPE &s) : type(t),illegal(false),hasMacro(fals
|
||||
memset(&id,0,sizeof(id));
|
||||
loc=STK_FRAME;
|
||||
id.longStkId = s;
|
||||
assert((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN));
|
||||
assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
|
||||
}
|
||||
|
||||
ID::ID(hlType t, const LONGGLB_TYPE &s) : type(t),illegal(false)
|
||||
@@ -48,7 +51,7 @@ ID::ID(hlType t, const LONGGLB_TYPE &s) : type(t),illegal(false)
|
||||
memset(&id,0,sizeof(id));
|
||||
loc=GLB_FRAME;
|
||||
id.longGlb = s;
|
||||
assert((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN));
|
||||
assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +78,7 @@ int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
|
||||
|
||||
/* Check for entry in the table */
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[t,regi](ID &el)->bool {
|
||||
return ((el.type == t) && (el.id.regi == regi));
|
||||
return ((el.type == t) and (el.id.regi == regi));
|
||||
});
|
||||
if(found!=id_arr.end())
|
||||
return found-id_arr.begin();
|
||||
@@ -96,9 +99,9 @@ int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
|
||||
void LOCAL_ID::flagByteWordId (int off)
|
||||
{
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off](ID &en)->bool {
|
||||
//if (((en.type == TYPE_WORD_SIGN) || (en.type == TYPE_BYTE_SIGN)) &&
|
||||
if ((en.typeBitsize()<=16) &&
|
||||
(en.id.bwId.off == off) && (en.id.bwId.regOff == 0))
|
||||
//if (((en.type == TYPE_WORD_SIGN) or (en.type == TYPE_BYTE_SIGN)) and
|
||||
if ((en.typeBitsize()<=16) and
|
||||
(en.id.bwId.off == off) and (en.id.bwId.regOff == 0))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
@@ -118,7 +121,7 @@ int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
|
||||
|
||||
/* Check for entry in the table */
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off,regOff](ID &el)->bool {
|
||||
if ((el.id.bwId.off == off) && (el.id.bwId.regOff == regOff))
|
||||
if ((el.id.bwId.off == off) and (el.id.bwId.regOff == regOff))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
@@ -148,9 +151,9 @@ int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t)
|
||||
/* Check for entry in the table */
|
||||
for (size_t idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.bwGlb.seg == seg) &&
|
||||
(id_arr[idx].id.bwGlb.off == off) &&
|
||||
if (/*(locSym->id[idx].type == t) and Not checking type */
|
||||
(id_arr[idx].id.bwGlb.seg == seg) and
|
||||
(id_arr[idx].id.bwGlb.off == off) and
|
||||
(id_arr[idx].id.bwGlb.regi == regi))
|
||||
return (idx);
|
||||
}
|
||||
@@ -178,10 +181,10 @@ int LOCAL_ID::newLongReg(hlType t, const LONGID_TYPE &longT, iICODE ix_)
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
ID &entry(id_arr[idx]);
|
||||
if(!entry.isLong() || (entry.loc != REG_FRAME))
|
||||
if(not entry.isLong() or (entry.loc != REG_FRAME))
|
||||
continue;
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(entry.longId().h() == regH) &&
|
||||
if (/*(locSym->id[idx].type == t) and Not checking type */
|
||||
(entry.longId().h() == regH) and
|
||||
(entry.longId().l() == regL))
|
||||
{
|
||||
/* Check for occurrence in the list */
|
||||
@@ -201,8 +204,8 @@ int LOCAL_ID::newLongReg(hlType t, const LONGID_TYPE &longT, iICODE ix_)
|
||||
id_arr.back().idx.push_back(ix_);
|
||||
return (id_arr.size() - 1);
|
||||
}
|
||||
/* Returns an identifier conditional expression node of type TYPE_LONG or
|
||||
* TYPE_WORD_SIGN */
|
||||
/** Returns an identifier conditional expression node of type TYPE_LONG or
|
||||
* TYPE_WORD_SIGN */
|
||||
AstIdent * LOCAL_ID::createId(const ID *retVal, iICODE ix_)
|
||||
{
|
||||
return AstIdent::idID(retVal,this,ix_);
|
||||
@@ -218,9 +221,9 @@ int LOCAL_ID::newLongGlb(int16_t seg, int16_t offH, int16_t offL,hlType t)
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
||||
if (/*(locSym->id[idx].type == t) and Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) and
|
||||
(id_arr[idx].id.longGlb.offH == offH) and
|
||||
(id_arr[idx].id.longGlb.offL == offL))
|
||||
return (idx);
|
||||
}
|
||||
@@ -242,21 +245,17 @@ int LOCAL_ID::newLongIdx( int16_t seg, int16_t offH, int16_t offL,uint8_t regi,
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
||||
(id_arr[idx].id.longGlb.offL == offL) &&
|
||||
if (/*(locSym->id[idx].type == t) and Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) and
|
||||
(id_arr[idx].id.longGlb.offH == offH) and
|
||||
(id_arr[idx].id.longGlb.offL == offL) and
|
||||
(id_arr[idx].id.longGlb.regi == regi))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
id_arr.push_back(ID(t,LONGGLB_TYPE(seg,offH,offL,regi)));
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longGlb.seg = seg;
|
||||
id_arr[idx].id.longGlb.offH = offH;
|
||||
id_arr[idx].id.longGlb.offL = offL;
|
||||
id_arr[idx].id.longGlb.regi = regi;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
@@ -272,8 +271,8 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
|
||||
{
|
||||
if(id_arr[idx].loc!=STK_FRAME)
|
||||
continue;
|
||||
if ((id_arr[idx].type == t) &&
|
||||
(id_arr[idx].longStkId().offH == offH) &&
|
||||
if ((id_arr[idx].type == t) and
|
||||
(id_arr[idx].longStkId().offH == offH) and
|
||||
(id_arr[idx].longStkId().offL == offL))
|
||||
return (idx);
|
||||
}
|
||||
@@ -320,9 +319,9 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
||||
}
|
||||
|
||||
else if (pmL->off) { /* offset */
|
||||
if ((pmL->seg == rSS) && (pmL->regi == INDEX_BP)) /* idx on bp */
|
||||
if ((pmL->seg == rSS) and (pmL->regi == INDEX_BP)) /* idx on bp */
|
||||
idx = newLongStk(TYPE_LONG_SIGN, pmH->off, pmL->off);
|
||||
else if ((pmL->seg == rDS) && (pmL->regi == INDEX_BX)) /* bx */
|
||||
else if ((pmL->seg == rDS) and (pmL->regi == INDEX_BX)) /* bx */
|
||||
{ /* glb var indexed on bx */
|
||||
printf("Bx indexed global, BX is an unused parameter to newLongIdx\n");
|
||||
idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX,TYPE_LONG_SIGN);
|
||||
@@ -332,8 +331,8 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
||||
printf ("long not supported, idx <> bp\n");
|
||||
}
|
||||
|
||||
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */
|
||||
printf ("long not supported, idx && no off\n");
|
||||
else /* (pm->regi >= INDEXBASE and pm->off = 0) => indexed and no off */
|
||||
printf ("long not supported, idx and no off\n");
|
||||
|
||||
return (idx);
|
||||
}
|
||||
@@ -357,7 +356,7 @@ bool checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc
|
||||
pmLdst = &atOffset.m_dst;
|
||||
pmHsrc = &pIcode->ll()->src();
|
||||
pmLsrc = &atOffset.src();
|
||||
// if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
|
||||
// if ((longId.offH == pmHsrc->off) and (longId.offL == pmLsrc->off))
|
||||
// {
|
||||
// asgn.lhs = AstIdent::LongIdx (i);
|
||||
|
||||
@@ -367,14 +366,14 @@ bool checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
// else if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
|
||||
// else if ((longId.offH == pmHdst->off) and (longId.offL == pmLdst->off))
|
||||
// {
|
||||
// asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
|
||||
// asgn.rhs = AstIdent::LongIdx (i);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
|
||||
if ((longId.offH == pmHdst->off) and (longId.offL == pmLdst->off))
|
||||
{
|
||||
asgn.lhs = AstIdent::LongIdx (i);
|
||||
|
||||
@@ -384,7 +383,7 @@ bool checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
|
||||
else if ((longId.offH == pmHsrc->off) and (longId.offL == pmLsrc->off))
|
||||
{
|
||||
asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
|
||||
asgn.rhs = AstIdent::LongIdx (i);
|
||||
@@ -414,7 +413,7 @@ bool checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
|
||||
pmHsrc = &pIcode->ll()->src();
|
||||
pmLsrc = &atOffset.src();
|
||||
|
||||
if ((longId.h() == pmHdst->regi) && (longId.l() == pmLdst->regi))
|
||||
if ((longId.h() == pmHdst->regi) and (longId.l() == pmLdst->regi))
|
||||
{
|
||||
asgn.lhs = AstIdent::LongIdx (i);
|
||||
if ( not pIcode->ll()->testFlags(NO_SRC) )
|
||||
@@ -423,7 +422,7 @@ bool checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ((longId.h() == pmHsrc->regi) && (longId.l() == pmLsrc->regi))
|
||||
else if ((longId.h() == pmHsrc->regi) and (longId.l() == pmLsrc->regi))
|
||||
{
|
||||
asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
|
||||
asgn.rhs = AstIdent::LongIdx (i);
|
||||
@@ -442,7 +441,7 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
|
||||
ID *id;
|
||||
|
||||
id = &locTbl->id_arr[idx];
|
||||
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
|
||||
if ((id->loc == REG_FRAME) and ((id->type == TYPE_LONG_SIGN) or
|
||||
(id->type == TYPE_LONG_UNSIGN)))
|
||||
{
|
||||
if (id->longId().h() == regi)
|
||||
@@ -450,15 +449,16 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
|
||||
else if (id->longId().l() == regi)
|
||||
return (id->longId().h());
|
||||
}
|
||||
return rUNDEF; // Cristina: please check this!
|
||||
return rUNDEF; // Cristina: please check this!
|
||||
}
|
||||
|
||||
|
||||
/* Checks if the registers regL and regH have been used independently in
|
||||
/**
|
||||
* Checks if the registers regL and regH have been used independently in
|
||||
* the local identifier table. If so, macros for these registers are
|
||||
* placed in the local identifier table, as these registers belong to a
|
||||
* long register identifier. */
|
||||
void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const char *name)
|
||||
* long register identifier. */
|
||||
void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const QString &name)
|
||||
{
|
||||
for (ID &rid : id_arr)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
#include <cassert>
|
||||
#include "machine_x86.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "icode.h"
|
||||
|
||||
#include <QtCore/QTextStream>
|
||||
#include <cassert>
|
||||
|
||||
// Index registers **** temp solution
|
||||
static const std::string regNames[] = {
|
||||
static const QString regNames[] = {
|
||||
"undef",
|
||||
"ax", "cx", "dx", "bx",
|
||||
"sp", "bp", "si", "di",
|
||||
@@ -17,17 +22,17 @@ static const std::string regNames[] = {
|
||||
/* uint8_t and uint16_t registers */
|
||||
Machine_X86::Machine_X86()
|
||||
{
|
||||
static_assert((sizeof(regNames)/sizeof(std::string))==LAST_REG,
|
||||
static_assert((sizeof(regNames)/sizeof(QString))==LAST_REG,
|
||||
"Reg count not equal number of strings");
|
||||
}
|
||||
|
||||
const std::string &Machine_X86::regName(eReg r)
|
||||
const QString &Machine_X86::regName(eReg r)
|
||||
{
|
||||
assert(r<(sizeof(regNames)/sizeof(std::string)));
|
||||
assert(r<(sizeof(regNames)/sizeof(QString)));
|
||||
return regNames[r];
|
||||
}
|
||||
|
||||
static const std::string szOps[] =
|
||||
static const QString szOps[] =
|
||||
{
|
||||
"CBW", "AAA", "AAD", "AAM", "AAS", "ADC", "ADD", "AND",
|
||||
"BOUND","CALL", "CALL", "CLC", "CLD", "CLI", "CMC", "CMP",
|
||||
@@ -42,10 +47,10 @@ static const std::string szOps[] =
|
||||
"RCL", "RCR", "ROL", "ROR", "RET", "RETF", "SAHF", "SAR",
|
||||
"SHL", "SHR", "SBB", "SCAS", "REPNE SCAS","REPE SCAS", "CWD", "STC",
|
||||
"STD", "STI", "STOS", "REP STOS", "SUB", "TEST", "WAIT", "XCHG",
|
||||
"XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD"
|
||||
"XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD"
|
||||
};
|
||||
/* The following opcodes are for mod != 3 */
|
||||
static std::string szFlops1[] =
|
||||
static const QString szFlops1[] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
|
||||
@@ -58,7 +63,7 @@ static std::string szFlops1[] =
|
||||
"FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */
|
||||
};
|
||||
/* The following opcodes are for mod == 3 */
|
||||
static std::string szFlops2[] =
|
||||
static const QString szFlops2[] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
|
||||
@@ -71,17 +76,17 @@ static std::string szFlops2[] =
|
||||
"FILD", "???", "FIST", "FISTP", "", "???", "FBSTP", "FISTP" /* 38 */
|
||||
};
|
||||
|
||||
const std::string &Machine_X86::opcodeName(unsigned r)
|
||||
const QString &Machine_X86::opcodeName(unsigned r)
|
||||
{
|
||||
assert(r<(sizeof(szOps)/sizeof(std::string)));
|
||||
assert(r<(sizeof(szOps)/sizeof(QString)));
|
||||
return szOps[r];
|
||||
}
|
||||
const std::string &Machine_X86::floatOpName(unsigned r)
|
||||
const QString &Machine_X86::floatOpName(unsigned r)
|
||||
{
|
||||
if(r>=(sizeof(szFlops1)/sizeof(std::string)))
|
||||
if(r>=(sizeof(szFlops1)/sizeof(QString)))
|
||||
{
|
||||
r-= (sizeof(szFlops1)/sizeof(std::string));
|
||||
assert(r<(sizeof(szFlops2)/sizeof(std::string)));
|
||||
r-= (sizeof(szFlops1)/sizeof(QString));
|
||||
assert(r<(sizeof(szFlops2)/sizeof(QString)));
|
||||
return szFlops2[r];
|
||||
}
|
||||
return szFlops1[r];
|
||||
@@ -89,11 +94,11 @@ const std::string &Machine_X86::floatOpName(unsigned r)
|
||||
|
||||
bool Machine_X86::physicalReg(eReg r)
|
||||
{
|
||||
return (r>=rAX) && (r<rTMP);
|
||||
return (r>=rAX) and (r<rTMP);
|
||||
}
|
||||
bool Machine_X86::isMemOff(eReg r)
|
||||
{
|
||||
return r == 0 || r >= INDEX_BX_SI;
|
||||
return r == 0 or r >= INDEX_BX_SI;
|
||||
}
|
||||
//TODO: Move these to Machine_X86
|
||||
eReg Machine_X86::subRegH(eReg reg)
|
||||
@@ -106,18 +111,18 @@ eReg Machine_X86::subRegL(eReg reg)
|
||||
}
|
||||
bool Machine_X86::isSubRegisterOf(eReg reg,eReg parent)
|
||||
{
|
||||
if ((parent < rAX) || (parent > rBX))
|
||||
if ((parent < rAX) or (parent > rBX))
|
||||
return false; // only AX -> BX are coverede by subregisters
|
||||
return ((reg==subRegH(parent)) || (reg == subRegL(parent)));
|
||||
return ((reg==subRegH(parent)) or (reg == subRegL(parent)));
|
||||
}
|
||||
bool Machine_X86::hasSubregisters(eReg reg)
|
||||
{
|
||||
return ((reg >= rAX) && (reg <= rBX));
|
||||
return ((reg >= rAX) and (reg <= rBX));
|
||||
}
|
||||
|
||||
bool Machine_X86::isPartOfComposite(eReg reg)
|
||||
{
|
||||
return ((reg >= rAL) && (reg <= rBH));
|
||||
return ((reg >= rAL) and (reg <= rBH));
|
||||
}
|
||||
|
||||
eReg Machine_X86::compositeParent(eReg reg)
|
||||
@@ -133,7 +138,7 @@ eReg Machine_X86::compositeParent(eReg reg)
|
||||
}
|
||||
return rUNDEF;
|
||||
}
|
||||
void Machine_X86::writeRegVector (std::ostream &ostr,const LivenessSet ®i)
|
||||
void Machine_X86::writeRegVector (QTextStream &ostr,const LivenessSet ®i)
|
||||
{
|
||||
int j;
|
||||
for (j = rAX; j < INDEX_BX_SI; j++)
|
||||
|
||||
795
src/parser.cpp
795
src/parser.cpp
File diff suppressed because it is too large
Load Diff
7
src/parser.h
Normal file
7
src/parser.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
class Function;
|
||||
struct CALL_GRAPH;
|
||||
struct STATE;
|
||||
void FollowCtrl(Function & func, CALL_GRAPH * pcallGraph, STATE *pstate);
|
||||
#endif // PARSER_H
|
||||
101
src/perfhlib.cpp
101
src/perfhlib.cpp
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Perfect hashing function library. Contains functions to generate perfect
|
||||
* hashing functions
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "perfhlib.h"
|
||||
|
||||
/* Private data structures */
|
||||
|
||||
static uint16_t *T1, *T2; /* Pointers to T1[i], T2[i] */
|
||||
static short *g; /* g[] */
|
||||
|
||||
//static int numEdges; /* An edge counter */
|
||||
//static bool *visited; /* Array of bools: whether visited */
|
||||
|
||||
/* Private prototypes */
|
||||
//static void initGraph(void);
|
||||
//static void addToGraph(int e, int v1, int v2);
|
||||
//static bool isCycle(void);
|
||||
//static void duplicateKeys(int v1, int v2);
|
||||
PatternHasher g_pattern_hasher;
|
||||
|
||||
void PatternHasher::init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin, int _NumVert)
|
||||
{
|
||||
/* These parameters are stored in statics so as to obviate the need for
|
||||
passing all these (or defererencing pointers) for every call to hash()
|
||||
*/
|
||||
|
||||
NumEntry = _NumEntry;
|
||||
EntryLen = _EntryLen;
|
||||
SetSize = _SetSize;
|
||||
SetMin = _SetMin;
|
||||
NumVert = _NumVert;
|
||||
|
||||
/* Allocate the variable sized tables etc */
|
||||
T1base = new uint16_t [EntryLen * SetSize];
|
||||
T2base = new uint16_t [EntryLen * SetSize];
|
||||
graphNode = new int [NumEntry*2 + 1];
|
||||
graphNext = new int [NumEntry*2 + 1];
|
||||
graphFirst = new int [NumVert + 1];
|
||||
g = new short [NumVert + 1];
|
||||
// visited = new bool [NumVert + 1];
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void PatternHasher::cleanup(void)
|
||||
{
|
||||
/* Free the storage for variable sized tables etc */
|
||||
delete [] T1base;
|
||||
delete [] T2base;
|
||||
delete [] graphNode;
|
||||
delete [] graphNext;
|
||||
delete [] graphFirst;
|
||||
delete [] g;
|
||||
// delete [] visited;
|
||||
}
|
||||
|
||||
int PatternHasher::hash(uint8_t *string)
|
||||
{
|
||||
uint16_t u, v;
|
||||
int j;
|
||||
|
||||
u = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
u += T1[string[j] - SetMin];
|
||||
}
|
||||
u %= NumVert;
|
||||
|
||||
v = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T2 = T2base + j * SetSize;
|
||||
v += T2[string[j] - SetMin];
|
||||
}
|
||||
v %= NumVert;
|
||||
|
||||
return (g[u] + g[v]) % NumEntry;
|
||||
}
|
||||
|
||||
uint16_t * PatternHasher::readT1(void)
|
||||
{
|
||||
return T1base;
|
||||
}
|
||||
|
||||
uint16_t *PatternHasher::readT2(void)
|
||||
{
|
||||
return T2base;
|
||||
}
|
||||
|
||||
uint16_t * PatternHasher::readG(void)
|
||||
{
|
||||
return (uint16_t *)g;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user