Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
ca695ac9
Commit
ca695ac9
authored
Sep 21, 1993
by
Jan Brittenson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bytecode
From-SVN: r5379
parent
86d7f2db
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1631 additions
and
201 deletions
+1631
-201
gcc/Makefile.in
+72
-11
gcc/c-pragma.c
+4
-32
gcc/emit-rtl.c
+39
-2
gcc/expr.c
+0
-0
gcc/integrate.c
+9
-1
gcc/regclass.c
+8
-0
gcc/rtl.h
+17
-0
gcc/stmt.c
+902
-28
gcc/toplev.c
+107
-46
gcc/varasm.c
+473
-81
No files found.
gcc/Makefile.in
View file @
ca695ac9
...
@@ -399,6 +399,9 @@ CPLUS_OBJS = cp-parse.o cp-decl.o cp-decl2.o \
...
@@ -399,6 +399,9 @@ CPLUS_OBJS = cp-parse.o cp-decl.o cp-decl2.o \
cp-expr.o cp-pt.o cp-edsel.o cp-xref.o
\
cp-expr.o cp-pt.o cp-edsel.o cp-xref.o
\
$(CPLUS_INPUT)
cp-spew.o c-common.o
$(CPLUS_INPUT)
cp-spew.o c-common.o
# Files specific to the C interpreter bytecode compiler(s).
BC_OBJS
=
bc-emit.o bc-optab.o
# Language-independent object files.
# Language-independent object files.
OBJS
=
toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o
\
OBJS
=
toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o
\
function
.o stmt.o expr.o calls.o expmed.o explow.o optabs.o varasm.o
\
function
.o stmt.o expr.o calls.o expmed.o explow.o optabs.o varasm.o
\
...
@@ -461,6 +464,7 @@ CONFIG_H =
...
@@ -461,6 +464,7 @@ CONFIG_H =
RTL_H
=
rtl.h rtl.def machmode.h machmode.def
RTL_H
=
rtl.h rtl.def machmode.h machmode.def
TREE_H
=
tree.h real.h tree.def machmode.h machmode.def
TREE_H
=
tree.h real.h tree.def machmode.h machmode.def
CPLUS_TREE_H
=
$(TREE_H)
cp-tree.h cp-tree.def
CPLUS_TREE_H
=
$(TREE_H)
cp-tree.h cp-tree.def
BYTECODE_H
=
bytecode.h bc-emit.h bc-optab.h
# Avoid a lot of time thinking about remaking Makefile.in and *.def.
# Avoid a lot of time thinking about remaking Makefile.in and *.def.
.SUFFIXES
:
.in .def
.SUFFIXES
:
.in .def
...
@@ -484,7 +488,7 @@ for-bootstrap: start.encap $(LIBGCC)
...
@@ -484,7 +488,7 @@ for-bootstrap: start.encap $(LIBGCC)
rest.encap
:
$(LIBGCC) stmp-headers $(STMP_FIXPROTO) $(EXTRA_PARTS)
rest.encap
:
$(LIBGCC) stmp-headers $(STMP_FIXPROTO) $(EXTRA_PARTS)
# This is what is made with the host's compiler
# This is what is made with the host's compiler
# whether making a cross compiler or not.
# whether making a cross compiler or not.
native
:
config.status cpp $(LANGUAGES) $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2)
native
:
bytecode
config.status cpp $(LANGUAGES) $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2)
# Define the names for selecting languages in LANGUAGES.
# Define the names for selecting languages in LANGUAGES.
C c
:
cc1
C c
:
cc1
...
@@ -545,14 +549,14 @@ g++-cross: $(srcdir)/g++.c
...
@@ -545,14 +549,14 @@ g++-cross: $(srcdir)/g++.c
$(CC)
$(ALL_CFLAGS)
$(INCLUDES)
$(LDFLAGS)
-o
g++-cross
\
$(CC)
$(ALL_CFLAGS)
$(INCLUDES)
$(LDFLAGS)
-o
g++-cross
\
-DGCC_NAME
=
\"
$(target)
-gcc
\"
$(srcdir)
/g++.c version.o
$(LIBS)
-DGCC_NAME
=
\"
$(target)
-gcc
\"
$(srcdir)
/g++.c version.o
$(LIBS)
cc1
:
$(P) $(C_OBJS) $(OBJS) $(LIBDEPS)
cc1
:
$(P) $(C_OBJS) $(OBJS) $(
BC_OBJS) $(
LIBDEPS)
$(CC)
$(ALL_CFLAGS)
$(LDFLAGS)
-o
cc1
$(C_OBJS)
$(OBJS)
$(LIBS)
$(CC)
$(ALL_CFLAGS)
$(LDFLAGS)
-o
cc1
$(C_OBJS)
$(OBJS)
$(
BC_OBJS)
$(
LIBS)
cc1plus
:
$(P) $(CPLUS_OBJS) $(OBJS) $(LIBDEPS)
cc1plus
:
$(P) $(CPLUS_OBJS) $(OBJS) $(
BC_OBJS) $(
LIBDEPS)
$(CC)
$(ALL_CFLAGS)
$(LDFLAGS)
-o
cc1plus
$(CPLUS_OBJS)
$(OBJS)
$(LIBS)
$(CC)
$(ALL_CFLAGS)
$(LDFLAGS)
-o
cc1plus
$(CPLUS_OBJS)
$(
BC_OBJS)
$(
OBJS)
$(LIBS)
cc1obj
:
$(P) $(OBJC_OBJS) $(OBJS) $(LIBDEPS)
cc1obj
:
$(P) $(OBJC_OBJS) $(OBJS) $(
BC_OBJS) $(
LIBDEPS)
$(CC)
$(ALL_CFLAGS)
$(LDFLAGS)
-o
cc1obj
$(OBJC_OBJS)
$(OBJS)
$(LIBS)
$(CC)
$(ALL_CFLAGS)
$(LDFLAGS)
-o
cc1obj
$(OBJC_OBJS)
$(OBJS)
$(
BC_OBJS)
$(
LIBS)
# Copy float.h from its source.
# Copy float.h from its source.
gfloat.h
:
$(FLOAT_H)
gfloat.h
:
$(FLOAT_H)
...
@@ -1247,6 +1251,63 @@ $(HOST_PREFIX_1)malloc.o: malloc.c
...
@@ -1247,6 +1251,63 @@ $(HOST_PREFIX_1)malloc.o: malloc.c
$(HOST_PREFIX_1)
:
$(HOST_PREFIX_1)
:
touch
$(HOST_PREFIX_1)
touch
$(HOST_PREFIX_1)
# Remake bytecode files.
# BI_ALL=bi-run.o
BI_ALL
=
BC_ALL
=
bc-opname.h bc-opcode.h bc-arity.h
BI_OBJ
=
bi-parser.o bi-lexer.o bi-reverse.o
bc-emit.o
:
bc-emit.c $(CONFIG_H) $(BYTECODE_H)
bc-optab.o
:
bc-optab.c bc-typecd.def $(CONFIG_H) $(BYTECODE_H)
bytecode
:
$(BI_ALL) $(BC_ALL)
bi-arity
:
bi-arity.o
bi-opcode
:
bi-opcode.o
bi-opname
:
bi-opname.o
bi-unparse
:
bi-unparse.o
bi-lexer
:
bi-lexer.o
bi-arity bi-opcode bi-opname bi-unparse bi-lexer
:
$(BI_OBJ)
$(CC)
$(ALL_CFLAGS)
$(LDFLAGS)
-o
$@
$^
$(LEXLIB)
bi-run.o
:
$(srcdir)/bi-run.c $(srcdir)/bi-run.h $(srcdir)/bc-typecd.h bc-opname.h bc-arity.h bc-opcode.h
$(CC)
$(ALL_CFLAGS)
$(ALL_CPPFLAGS)
$(INCLUDES)
-c
$<
bi-parser.c
:
$(srcdir)/bi-parser.y $(srcdir)/bi-parser.h
bi-parser.o
:
$(srcdir)/bi-parser.c $(srcdir)/bi-defs.h
$(CC)
$(CFLAGS)
$(ALL_CPPFLAGS)
$(INCLUDES)
-c
$<
bi-lexer.c
:
$(srcdir)/bi-lexer.l $(srcdir)/bi-parser.h
bi-lexer.o
:
bi-lexer.c bi-parser.h
$(CC)
$(CFLAGS)
$(ALL_CPPFLAGS)
$(INCLUDES)
-c
$<
bc-arity.h
:
$(srcdir)/bytecode.def bi-arity
-
rm
-f
$@
bi-arity <
$<
>
$@
bc-opcode.h
:
$(srcdir)/bytecode.def bi-opcode
-
rm
-f
$@
bi-opcode <
$<
>
$@
bc-opname.h
:
$(srcdir)/bytecode.def bi-opname
-
rm
-f
$@
bi-opname <
$<
>
$@
bytecode.mostlyclean
:
-
rm
-f
bc-arity.h bc-opcode.h bc-opname.h
bytecode.distclean bytecode.clean
:
bytecode.mostlyclean
-
rm
-f
bi-arity bi-opcode bi-opname bi-unparse bi-lexer
bytecode.realclean
:
bytecode.clean
-
rm
-f
bi-parser.c bi-lexer.c bi-parser.h
# Remake cpp and protoize.
# Remake cpp and protoize.
# Making the preprocessor
# Making the preprocessor
...
@@ -1507,7 +1568,7 @@ $(srcdir)/INSTALL: install1.texi install.texi
...
@@ -1507,7 +1568,7 @@ $(srcdir)/INSTALL: install1.texi install.texi
# `realclean' also deletes everything that could be regenerated automatically.
# `realclean' also deletes everything that could be regenerated automatically.
mostlyclean
:
mostlyclean
:
bytecode.mostlyclean
-
rm
-f
$(STAGESTUFF)
-
rm
-f
$(STAGESTUFF)
# Clean the objc subdir if we created one.
# Clean the objc subdir if we created one.
if
[
-d
objc
];
then
\
if
[
-d
objc
];
then
\
...
@@ -1545,7 +1606,7 @@ mostlyclean:
...
@@ -1545,7 +1606,7 @@ mostlyclean:
# Delete all files made by compilation
# Delete all files made by compilation
# that don't exist in the distribution.
# that don't exist in the distribution.
clean
:
mostlyclean
clean
:
mostlyclean
bytecode.clean
# It may not be quite desirable to delete unprotoize.c here,
# It may not be quite desirable to delete unprotoize.c here,
# but the spec for `make clean' requires it.
# but the spec for `make clean' requires it.
# Using unprotoize.c is not quite right in the first place,
# Using unprotoize.c is not quite right in the first place,
...
@@ -1557,7 +1618,7 @@ clean: mostlyclean
...
@@ -1557,7 +1618,7 @@ clean: mostlyclean
# Delete all files that users would normally create
# Delete all files that users would normally create
# while building and installing GCC.
# while building and installing GCC.
distclean
:
clean
distclean
:
clean
bytecode.distclean
-
rm
-f
tm.h aux-output.c config.h md config.status tconfig.h hconfig.h
-
rm
-f
tm.h aux-output.c config.h md config.status tconfig.h hconfig.h
-
rm
-f
Makefile
*
.oaux
-
rm
-f
Makefile
*
.oaux
-
rm
-fr
stage1 stage2 stage3 stage4
-
rm
-fr
stage1 stage2 stage3 stage4
...
@@ -1581,7 +1642,7 @@ extraclean: distclean
...
@@ -1581,7 +1642,7 @@ extraclean: distclean
# Get rid of every file that's generated from some other file.
# Get rid of every file that's generated from some other file.
# Most of these files ARE PRESENT in the GCC distribution.
# Most of these files ARE PRESENT in the GCC distribution.
realclean
:
distclean
realclean
:
distclean
bytecode.realclean
-
rm
-f
c-parse.y objc-parse.y
-
rm
-f
c-parse.y objc-parse.y
-
rm
-f
cp-parse.c cp-parse.h cp-parse.output
-
rm
-f
cp-parse.c cp-parse.h cp-parse.output
-
rm
-f
objc-parse.c objc-parse.output
-
rm
-f
objc-parse.c objc-parse.output
...
...
gcc/c-pragma.c
View file @
ca695ac9
...
@@ -20,6 +20,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -20,6 +20,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <stdio.h>
#include "config.h"
#include "config.h"
#include "tree.h"
#include "tree.h"
#include "function.h"
#ifdef HANDLE_SYSV_PRAGMA
#ifdef HANDLE_SYSV_PRAGMA
...
@@ -45,20 +46,7 @@ handle_pragma_token (string, token)
...
@@ -45,20 +46,7 @@ handle_pragma_token (string, token)
char
*
string
;
char
*
string
;
tree
token
;
tree
token
;
{
{
static
enum
pragma_state
static
enum
pragma_state
state
=
ps_start
,
type
;
{
ps_start
,
ps_done
,
ps_bad
,
ps_weak
,
ps_name
,
ps_equals
,
ps_value
,
ps_pack
,
ps_left
,
ps_align
,
ps_right
}
state
=
ps_start
,
type
;
static
char
*
name
;
static
char
*
name
;
static
char
*
value
;
static
char
*
value
;
static
int
align
;
static
int
align
;
...
@@ -76,24 +64,8 @@ handle_pragma_token (string, token)
...
@@ -76,24 +64,8 @@ handle_pragma_token (string, token)
{
{
#ifdef HANDLE_PRAGMA_WEAK
#ifdef HANDLE_PRAGMA_WEAK
if
(
HANDLE_PRAGMA_WEAK
)
if
(
HANDLE_PRAGMA_WEAK
)
{
handle_pragma_weak
(
state
,
asm_out_file
,
name
,
value
);
if
(
state
==
ps_name
||
state
==
ps_value
)
{
fprintf
(
asm_out_file
,
"
\t
%s
\t
"
,
WEAK_ASM_OP
);
ASM_OUTPUT_LABELREF
(
asm_out_file
,
name
);
fputc
(
'\n'
,
asm_out_file
);
if
(
state
==
ps_value
)
{
fprintf
(
asm_out_file
,
"
\t
%s
\t
"
,
SET_ASM_OP
);
ASM_OUTPUT_LABELREF
(
asm_out_file
,
name
);
fputc
(
','
,
asm_out_file
);
ASM_OUTPUT_LABELREF
(
asm_out_file
,
value
);
fputc
(
'\n'
,
asm_out_file
);
}
}
else
if
(
!
(
state
==
ps_done
||
state
==
ps_start
))
warning
(
"malformed `#pragma weak'"
);
}
#endif
/* HANDLE_PRAMA_WEAK */
#endif
/* HANDLE_PRAMA_WEAK */
}
}
...
...
gcc/emit-rtl.c
View file @
ca695ac9
...
@@ -42,8 +42,29 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -42,8 +42,29 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "regs.h"
#include "regs.h"
#include "insn-config.h"
#include "insn-config.h"
#include "real.h"
#include "real.h"
#include "obstack.h"
#include "bytecode.h"
#include "machmode.h"
#include "bc-opcode.h"
#include "bc-typecd.h"
#include "bc-optab.h"
#include "bc-emit.h"
#include <stdio.h>
#include <stdio.h>
/* Opcode names */
#ifdef BCDEBUG_PRINT_CODE
char
*
opcode_name
[]
=
{
#include "bc-opname.h"
"***END***"
};
#endif
/* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.
/* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.
After rtl generation, it is 1 plus the largest register number used. */
After rtl generation, it is 1 plus the largest register number used. */
...
@@ -203,6 +224,11 @@ extern int emit_lineno;
...
@@ -203,6 +224,11 @@ extern int emit_lineno;
rtx
change_address
();
rtx
change_address
();
void
init_emit
();
void
init_emit
();
extern
struct
obstack
*
rtl_obstack
;
extern
int
stack_depth
;
extern
int
max_stack_depth
;
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
**
**
** This routine generates an RTX of the size specified by
** This routine generates an RTX of the size specified by
...
@@ -1216,8 +1242,12 @@ change_address (memref, mode, addr)
...
@@ -1216,8 +1242,12 @@ change_address (memref, mode, addr)
rtx
rtx
gen_label_rtx
()
gen_label_rtx
()
{
{
register
rtx
label
=
gen_rtx
(
CODE_LABEL
,
VOIDmode
,
0
,
0
,
0
,
register
rtx
label
;
label_num
++
,
NULL_PTR
);
label
=
output_bytecode
?
bc_gen_rtx
(
0
,
0
,
bc_get_bytecode_label
())
:
gen_rtx
(
CODE_LABEL
,
VOIDmode
,
0
,
0
,
0
,
label_num
++
,
NULL_PTR
);
LABEL_NUSES
(
label
)
=
0
;
LABEL_NUSES
(
label
)
=
0
;
return
label
;
return
label
;
}
}
...
@@ -2559,6 +2589,13 @@ emit_line_note (file, line)
...
@@ -2559,6 +2589,13 @@ emit_line_note (file, line)
char
*
file
;
char
*
file
;
int
line
;
int
line
;
{
{
if
(
output_bytecode
)
{
/* FIXME: for now we do nothing, but eventually we will have to deal with
debugging information. */
return
0
;
}
emit_filename
=
file
;
emit_filename
=
file
;
emit_lineno
=
line
;
emit_lineno
=
line
;
...
...
gcc/expr.c
View file @
ca695ac9
This source diff could not be displayed because it is too large. You can
view the blob
instead.
gcc/integrate.c
View file @
ca695ac9
...
@@ -32,6 +32,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -32,6 +32,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "integrate.h"
#include "integrate.h"
#include "real.h"
#include "real.h"
#include "function.h"
#include "function.h"
#include "bytecode.h"
#include "obstack.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_alloc xmalloc
...
@@ -2850,9 +2851,16 @@ void
...
@@ -2850,9 +2851,16 @@ void
output_inline_function
(
fndecl
)
output_inline_function
(
fndecl
)
tree
fndecl
;
tree
fndecl
;
{
{
rtx
head
=
DECL_SAVED_INSNS
(
fndecl
)
;
rtx
head
;
rtx
last
;
rtx
last
;
if
(
output_bytecode
)
{
warning
(
"`inline' ignored for bytecode output"
);
return
;
}
head
=
DECL_SAVED_INSNS
(
fndecl
);
current_function_decl
=
fndecl
;
current_function_decl
=
fndecl
;
/* This call is only used to initialize global variables. */
/* This call is only used to initialize global variables. */
...
...
gcc/regclass.c
View file @
ca695ac9
...
@@ -32,6 +32,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -32,6 +32,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "recog.h"
#include "recog.h"
#include "reload.h"
#include "reload.h"
#include "real.h"
#include "real.h"
#include "bytecode.h"
#ifndef REGISTER_MOVE_COST
#ifndef REGISTER_MOVE_COST
#define REGISTER_MOVE_COST(x, y) 2
#define REGISTER_MOVE_COST(x, y) 2
...
@@ -413,6 +414,13 @@ fix_register (name, fixed, call_used)
...
@@ -413,6 +414,13 @@ fix_register (name, fixed, call_used)
{
{
int
i
;
int
i
;
if
(
output_bytecode
)
{
warning
(
"request to mark `%s' as %s ignored by bytecode compiler"
,
name
,
call_used
?
"call-used"
:
"fixed"
);
return
;
}
/* Decode the name and update the primary form of
/* Decode the name and update the primary form of
the register info. */
the register info. */
...
...
gcc/rtl.h
View file @
ca695ac9
...
@@ -139,6 +139,22 @@ typedef struct rtx_def
...
@@ -139,6 +139,22 @@ typedef struct rtx_def
The number of operands and their types are controlled
The number of operands and their types are controlled
by the `code' field, according to rtl.def. */
by the `code' field, according to rtl.def. */
rtunion
fld
[
1
];
rtunion
fld
[
1
];
/* The rest is used instead of the above if bytecode is being output */
/* For static or external objects. */
char
*
label
;
/* From the named label, or the local variable pointer or the
argument pointer, depending on context. */
int
offset
;
/* For goto labels inside bytecode functions. */
struct
bc_label
*
bc_label
;
/* A unique identifier */
int
uid
;
}
*
rtx
;
}
*
rtx
;
/* Add prototype support. */
/* Add prototype support. */
...
@@ -640,6 +656,7 @@ extern rtx gen_rtx PROTO((enum rtx_code, enum machine_mode, ...));
...
@@ -640,6 +656,7 @@ extern rtx gen_rtx PROTO((enum rtx_code, enum machine_mode, ...));
extern rtvec gen_rtvec PROTO((int, ...));
extern rtvec gen_rtvec PROTO((int, ...));
#else
#else
extern
rtx
bc_gen_rtx
();
extern
rtx
gen_rtx
();
extern
rtx
gen_rtx
();
extern
rtvec
gen_rtvec
();
extern
rtvec
gen_rtvec
();
#endif
#endif
...
...
gcc/stmt.c
View file @
ca695ac9
...
@@ -49,6 +49,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -49,6 +49,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "obstack.h"
#include "obstack.h"
#include "loop.h"
#include "loop.h"
#include "recog.h"
#include "recog.h"
#include "machmode.h"
#include "bytecode.h"
#include "bc-typecd.h"
#include "bc-opcode.h"
#include "bc-optab.h"
#include "bc-emit.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
#define obstack_chunk_free free
...
@@ -181,13 +188,28 @@ static void emit_jump_if_reachable ();
...
@@ -181,13 +188,28 @@ static void emit_jump_if_reachable ();
static
int
warn_if_unused_value
();
static
int
warn_if_unused_value
();
static
void
expand_goto_internal
();
static
void
expand_goto_internal
();
static
void
bc_expand_goto_internal
();
static
int
expand_fixup
();
static
int
expand_fixup
();
static
void
bc_expand_fixup
();
void
fixup_gotos
();
void
fixup_gotos
();
static
void
bc_fixup_gotos
();
void
free_temp_slots
();
void
free_temp_slots
();
static
void
expand_cleanups
();
static
void
expand_cleanups
();
static
void
expand_null_return_1
();
static
void
expand_null_return_1
();
static
int
tail_recursion_args
();
static
int
tail_recursion_args
();
static
void
do_jump_if_equal
();
static
void
do_jump_if_equal
();
int
bc_expand_exit_loop_if_false
();
void
bc_expand_start_cond
();
void
bc_expand_end_cond
();
void
bc_expand_start_else
();
void
bc_expand_end_bindings
();
void
bc_expand_start_case
();
void
bc_check_for_full_enumeration_handling
();
void
bc_expand_end_case
();
void
bc_expand_decl
();
extern
rtx
bc_allocate_local
();
extern
rtx
bc_allocate_variable_array
();
/* Stack of control and binding constructs we are currently inside.
/* Stack of control and binding constructs we are currently inside.
...
@@ -250,7 +272,8 @@ struct nesting
...
@@ -250,7 +272,8 @@ struct nesting
/* Sequence number of this binding contour within the function,
/* Sequence number of this binding contour within the function,
in order of entry. */
in order of entry. */
int
block_start_count
;
int
block_start_count
;
/* Nonzero => value to restore stack to on exit. */
/* Nonzero => value to restore stack to on exit. Complemented by
bc_stack_level (see below) when generating bytecodes. */
rtx
stack_level
;
rtx
stack_level
;
/* The NOTE that starts this contour.
/* The NOTE that starts this contour.
Used by expand_goto to check whether the destination
Used by expand_goto to check whether the destination
...
@@ -277,6 +300,8 @@ struct nesting
...
@@ -277,6 +300,8 @@ struct nesting
struct
label_chain
*
label_chain
;
struct
label_chain
*
label_chain
;
/* Number of function calls seen, as of start of this block. */
/* Number of function calls seen, as of start of this block. */
int
function_call_count
;
int
function_call_count
;
/* Bytecode specific: stack level to restore stack to on exit. */
int
bc_stack_level
;
}
block
;
}
block
;
/* For switch (C) or case (Pascal) statements,
/* For switch (C) or case (Pascal) statements,
and also for dummies (see `expand_start_case_dummy'). */
and also for dummies (see `expand_start_case_dummy'). */
...
@@ -285,6 +310,10 @@ struct nesting
...
@@ -285,6 +310,10 @@ struct nesting
/* The insn after which the case dispatch should finally
/* The insn after which the case dispatch should finally
be emitted. Zero for a dummy. */
be emitted. Zero for a dummy. */
rtx
start
;
rtx
start
;
/* For bytecodes, the case table is in-lined right in the code.
A label is needed for skipping over this block. It is only
used when generating bytecodes. */
rtx
skip_label
;
/* A list of case labels, kept in ascending order by value
/* A list of case labels, kept in ascending order by value
as the list is built.
as the list is built.
During expand_end_case, this list may be rearranged into a
During expand_end_case, this list may be rearranged into a
...
@@ -425,6 +454,21 @@ struct goto_fixup
...
@@ -425,6 +454,21 @@ struct goto_fixup
time this goto was seen.
time this goto was seen.
The TREE_ADDRESSABLE flag is 1 for a block that has been exited. */
The TREE_ADDRESSABLE flag is 1 for a block that has been exited. */
tree
cleanup_list_list
;
tree
cleanup_list_list
;
/* Bytecode specific members follow */
/* The label that this jump is jumping to, or 0 for break, continue
or return. */
struct
bc_label
*
bc_target
;
/* The label we use for the fixup patch */
struct
bc_label
*
label
;
/* True (non-0) if fixup has been handled */
int
bc_handled
:
1
;
/* Like stack_level above, except refers to the interpreter stack */
int
bc_stack_level
;
};
};
static
struct
goto_fixup
*
goto_fixup_chain
;
static
struct
goto_fixup
*
goto_fixup_chain
;
...
@@ -514,11 +558,16 @@ restore_stmt_status (p)
...
@@ -514,11 +558,16 @@ restore_stmt_status (p)
void
void
emit_nop
()
emit_nop
()
{
{
rtx
last_insn
=
get_last_insn
();
rtx
last_insn
;
if
(
!
optimize
&&
(
GET_CODE
(
last_insn
)
==
CODE_LABEL
if
(
!
output_bytecode
)
||
prev_real_insn
(
last_insn
)
==
0
))
{
emit_insn
(
gen_nop
());
last_insn
=
get_last_insn
();
if
(
!
optimize
&&
(
GET_CODE
(
last_insn
)
==
CODE_LABEL
||
prev_real_insn
(
last_insn
)
==
0
))
emit_insn
(
gen_nop
());
}
}
}
/* Return the rtx-label that corresponds to a LABEL_DECL,
/* Return the rtx-label that corresponds to a LABEL_DECL,
...
@@ -555,9 +604,17 @@ void
...
@@ -555,9 +604,17 @@ void
expand_computed_goto
(
exp
)
expand_computed_goto
(
exp
)
tree
exp
;
tree
exp
;
{
{
rtx
x
=
expand_expr
(
exp
,
NULL_RTX
,
VOIDmode
,
0
);
if
(
output_bytecode
)
emit_queue
();
{
emit_indirect_jump
(
x
);
bc_expand_expr
(
exp
);
bc_emit_instruction
(
jumpP
);
}
else
{
rtx
x
=
expand_expr
(
exp
,
NULL_RTX
,
VOIDmode
,
0
);
emit_queue
();
emit_indirect_jump
(
x
);
}
}
}
/* Handle goto statements and the labels that they can go to. */
/* Handle goto statements and the labels that they can go to. */
...
@@ -579,6 +636,15 @@ expand_label (label)
...
@@ -579,6 +636,15 @@ expand_label (label)
{
{
struct
label_chain
*
p
;
struct
label_chain
*
p
;
if
(
output_bytecode
)
{
if
(
!
DECL_RTL
(
label
))
DECL_RTL
(
label
)
=
bc_gen_rtx
((
char
*
)
0
,
0
,
bc_get_bytecode_label
());
if
(
!
bc_emit_bytecode_labeldef
(
DECL_RTL
(
label
)
->
bc_label
))
error
(
"multiply defined label"
);
return
;
}
do_pending_stack_adjust
();
do_pending_stack_adjust
();
emit_label
(
label_rtx
(
label
));
emit_label
(
label_rtx
(
label
));
if
(
DECL_NAME
(
label
))
if
(
DECL_NAME
(
label
))
...
@@ -620,8 +686,16 @@ void
...
@@ -620,8 +686,16 @@ void
expand_goto
(
label
)
expand_goto
(
label
)
tree
label
;
tree
label
;
{
{
tree
context
;
if
(
output_bytecode
)
{
expand_goto_internal
(
label
,
label_rtx
(
label
),
NULL_RTX
);
return
;
}
/* Check for a nonlocal goto to a containing function. */
/* Check for a nonlocal goto to a containing function. */
tree
context
=
decl_function_context
(
label
);
context
=
decl_function_context
(
label
);
if
(
context
!=
0
&&
context
!=
current_function_decl
)
if
(
context
!=
0
&&
context
!=
current_function_decl
)
{
{
struct
function
*
p
=
find_function_data
(
context
);
struct
function
*
p
=
find_function_data
(
context
);
...
@@ -701,6 +775,16 @@ expand_goto_internal (body, label, last_insn)
...
@@ -701,6 +775,16 @@ expand_goto_internal (body, label, last_insn)
struct
nesting
*
block
;
struct
nesting
*
block
;
rtx
stack_level
=
0
;
rtx
stack_level
=
0
;
/* NOTICE! If a bytecode instruction other than `jump' is needed,
then the caller has to call bc_expand_goto_internal()
directly. This is rather an exceptional case, and there aren't
that many places where this is necessary. */
if
(
output_bytecode
)
{
expand_goto_internal
(
body
,
label
,
last_insn
);
return
;
}
if
(
GET_CODE
(
label
)
!=
CODE_LABEL
)
if
(
GET_CODE
(
label
)
!=
CODE_LABEL
)
abort
();
abort
();
...
@@ -753,6 +837,77 @@ expand_goto_internal (body, label, last_insn)
...
@@ -753,6 +837,77 @@ expand_goto_internal (body, label, last_insn)
emit_jump
(
label
);
emit_jump
(
label
);
}
}
/* Generate a jump with OPCODE to the given bytecode LABEL which is
found within BODY. */
static
void
bc_expand_goto_internal
(
opcode
,
label
,
body
)
enum
bytecode_opcode
opcode
;
struct
bc_label
*
label
;
tree
body
;
{
struct
nesting
*
block
;
int
stack_level
=
-
1
;
/* If the label is defined, adjust the stack as necessary.
If it's not defined, we have to push the reference on the
fixup list. */
if
(
label
->
defined
)
{
/* Find the innermost pending block that contains the label.
(Check containment by comparing bytecode uids.) Then restore the
outermost stack level within that block. */
for
(
block
=
block_stack
;
block
;
block
=
block
->
next
)
{
if
(
block
->
data
.
block
.
first_insn
->
uid
<
label
->
uid
)
break
;
if
(
block
->
data
.
block
.
bc_stack_level
)
stack_level
=
block
->
data
.
block
.
bc_stack_level
;
/* Execute the cleanups for blocks we are exiting. */
if
(
block
->
data
.
block
.
cleanups
!=
0
)
{
expand_cleanups
(
block
->
data
.
block
.
cleanups
,
NULL_TREE
);
do_pending_stack_adjust
();
}
}
/* Restore the stack level. If we need to adjust the stack, we
must do so after the jump, since the jump may depend on
what's on the stack. Thus, any stack-modifying conditional
jumps (these are the only ones that rely on what's on the
stack) go into the fixup list. */
if
(
stack_level
>=
0
&&
stack_depth
!=
stack_level
&&
opcode
!=
jump
)
bc_expand_fixup
(
opcode
,
label
,
stack_level
);
else
{
if
(
stack_level
>=
0
)
bc_adjust_stack
(
stack_depth
-
stack_level
);
if
(
body
&&
DECL_BIT_FIELD
(
body
))
error
(
"jump to `%s' invalidly jumps into binding contour"
,
IDENTIFIER_POINTER
(
DECL_NAME
(
body
)));
/* Emit immediate jump */
bc_emit_bytecode
(
opcode
);
bc_emit_bytecode_labelref
(
label
);
#ifdef DEBUG_PRINT_CODE
fputc
(
'\n'
,
stderr
);
#endif
}
}
else
/* Put goto in the fixup list */
bc_expand_fixup
(
opcode
,
label
,
stack_level
);
}
/* Generate if necessary a fixup for a goto
/* Generate if necessary a fixup for a goto
whose target label in tree structure (if any) is TREE_LABEL
whose target label in tree structure (if any) is TREE_LABEL
and whose target in rtl is RTL_LABEL.
and whose target in rtl is RTL_LABEL.
...
@@ -884,6 +1039,37 @@ expand_fixup (tree_label, rtl_label, last_insn)
...
@@ -884,6 +1039,37 @@ expand_fixup (tree_label, rtl_label, last_insn)
return
block
!=
0
;
return
block
!=
0
;
}
}
/* Generate bytecode jump with OPCODE to a fixup routine that links to LABEL.
Make the fixup restore the stack level to STACK_LEVEL. */
static
void
bc_expand_fixup
(
opcode
,
label
,
stack_level
)
enum
bytecode_opcode
opcode
;
struct
bc_label
*
label
;
int
stack_level
;
{
struct
goto_fixup
*
fixup
=
(
struct
goto_fixup
*
)
oballoc
(
sizeof
(
struct
goto_fixup
));
fixup
->
label
=
bc_get_bytecode_label
();
fixup
->
bc_target
=
label
;
fixup
->
bc_stack_level
=
stack_level
;
fixup
->
bc_handled
=
FALSE
;
fixup
->
next
=
goto_fixup_chain
;
goto_fixup_chain
=
fixup
;
/* Insert a jump to the fixup code */
bc_emit_bytecode
(
opcode
);
bc_emit_bytecode_labelref
(
fixup
->
label
);
#ifdef DEBUG_PRINT_CODE
fputc
(
'\n'
,
stderr
);
#endif
}
/* When exiting a binding contour, process all pending gotos requiring fixups.
/* When exiting a binding contour, process all pending gotos requiring fixups.
THISBLOCK is the structure that describes the block being exited.
THISBLOCK is the structure that describes the block being exited.
STACK_LEVEL is the rtx for the stack level to restore exiting this contour.
STACK_LEVEL is the rtx for the stack level to restore exiting this contour.
...
@@ -907,6 +1093,12 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
...
@@ -907,6 +1093,12 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
{
{
register
struct
goto_fixup
*
f
,
*
prev
;
register
struct
goto_fixup
*
f
,
*
prev
;
if
(
output_bytecode
)
{
bc_fixup_gotos
(
thisblock
,
stack_level
,
cleanup_list
,
first_insn
,
dont_jump_in
);
return
;
}
/* F is the fixup we are considering; PREV is the previous one. */
/* F is the fixup we are considering; PREV is the previous one. */
/* We run this loop in two passes so that cleanups of exited blocks
/* We run this loop in two passes so that cleanups of exited blocks
are run first, and blocks that are exited are marked so
are run first, and blocks that are exited are marked so
...
@@ -1039,6 +1231,72 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
...
@@ -1039,6 +1231,72 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
f
->
stack_level
=
stack_level
;
f
->
stack_level
=
stack_level
;
}
}
}
}
/* When exiting a binding contour, process all pending gotos requiring fixups.
Note: STACK_DEPTH is not altered.
The arguments are currently not used in the bytecode compiler, but we may need
them one day for languages other than C.
THISBLOCK is the structure that describes the block being exited.
STACK_LEVEL is the rtx for the stack level to restore exiting this contour.
CLEANUP_LIST is a list of expressions to evaluate on exiting this contour.
FIRST_INSN is the insn that began this contour.
Gotos that jump out of this contour must restore the
stack level and do the cleanups before actually jumping.
DONT_JUMP_IN nonzero means report error there is a jump into this
contour from before the beginning of the contour.
This is also done if STACK_LEVEL is nonzero. */
static
void
bc_fixup_gotos
(
thisblock
,
stack_level
,
cleanup_list
,
first_insn
,
dont_jump_in
)
struct
nesting
*
thisblock
;
int
stack_level
;
tree
cleanup_list
;
rtx
first_insn
;
int
dont_jump_in
;
{
register
struct
goto_fixup
*
f
,
*
prev
;
int
saved_stack_depth
;
/* F is the fixup we are considering; PREV is the previous one. */
for
(
prev
=
0
,
f
=
goto_fixup_chain
;
f
;
prev
=
f
,
f
=
f
->
next
)
{
/* Test for a fixup that is inactive because it is already handled. */
if
(
f
->
before_jump
==
0
)
{
/* Delete inactive fixup from the chain, if that is easy to do. */
if
(
prev
)
prev
->
next
=
f
->
next
;
}
/* Emit code to restore the stack and continue */
bc_emit_bytecode_labeldef
(
f
->
label
);
/* Save stack_depth across call, since bc_adjust_stack () will alter
the perceived stack depth via the instructions generated. */
if
(
f
->
bc_stack_level
>=
0
)
{
saved_stack_depth
=
stack_depth
;
bc_adjust_stack
(
stack_depth
-
f
->
bc_stack_level
);
stack_depth
=
saved_stack_depth
;
}
bc_emit_bytecode
(
jump
);
bc_emit_bytecode_labelref
(
f
->
bc_target
);
#ifdef DEBUG_PRINT_CODE
fputc
(
'\n'
,
stderr
);
#endif
}
goto_fixup_chain
=
NULL
;
}
/* Generate RTL for an asm statement (explicit assembler code).
/* Generate RTL for an asm statement (explicit assembler code).
BODY is a STRING_CST node containing the assembler code text,
BODY is a STRING_CST node containing the assembler code text,
...
@@ -1048,6 +1306,12 @@ void
...
@@ -1048,6 +1306,12 @@ void
expand_asm
(
body
)
expand_asm
(
body
)
tree
body
;
tree
body
;
{
{
if
(
output_bytecode
)
{
error
(
"`asm' is illegal when generating bytecode"
);
return
;
}
if
(
TREE_CODE
(
body
)
==
ADDR_EXPR
)
if
(
TREE_CODE
(
body
)
==
ADDR_EXPR
)
body
=
TREE_OPERAND
(
body
,
0
);
body
=
TREE_OPERAND
(
body
,
0
);
...
@@ -1090,6 +1354,12 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
...
@@ -1090,6 +1354,12 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
/* The insn we have emitted. */
/* The insn we have emitted. */
rtx
insn
;
rtx
insn
;
if
(
output_bytecode
)
{
error
(
"`asm' is illegal when generating bytecode"
);
return
;
}
/* Count the number of meaningful clobbered registers, ignoring what
/* Count the number of meaningful clobbered registers, ignoring what
we would ignore later. */
we would ignore later. */
nclobbers
=
0
;
nclobbers
=
0
;
...
@@ -1310,6 +1580,22 @@ void
...
@@ -1310,6 +1580,22 @@ void
expand_expr_stmt
(
exp
)
expand_expr_stmt
(
exp
)
tree
exp
;
tree
exp
;
{
{
if
(
output_bytecode
)
{
int
org_stack_depth
=
stack_depth
;
bc_expand_expr
(
exp
);
/* Restore stack depth */
if
(
stack_depth
<
org_stack_depth
)
abort
();
bc_emit_instruction
(
drop
);
last_expr_type
=
TREE_TYPE
(
exp
);
return
;
}
/* If -W, warn about statements with no side effects,
/* If -W, warn about statements with no side effects,
except for an explicit cast to void (e.g. for assert()), and
except for an explicit cast to void (e.g. for assert()), and
except inside a ({...}) where they may be useful. */
except inside a ({...}) where they may be useful. */
...
@@ -1459,10 +1745,17 @@ clear_last_expr ()
...
@@ -1459,10 +1745,17 @@ clear_last_expr ()
tree
tree
expand_start_stmt_expr
()
expand_start_stmt_expr
()
{
{
int
momentary
;
tree
t
;
/* When generating bytecode just note down the stack depth */
if
(
output_bytecode
)
return
(
build_int_2
(
stack_depth
,
0
));
/* Make the RTL_EXPR node temporary, not momentary,
/* Make the RTL_EXPR node temporary, not momentary,
so that rtl_expr_chain doesn't become garbage. */
so that rtl_expr_chain doesn't become garbage. */
int
momentary
=
suspend_momentary
();
momentary
=
suspend_momentary
();
t
ree
t
=
make_node
(
RTL_EXPR
);
t
=
make_node
(
RTL_EXPR
);
resume_momentary
(
momentary
);
resume_momentary
(
momentary
);
start_sequence
();
start_sequence
();
NO_DEFER_POP
;
NO_DEFER_POP
;
...
@@ -1486,6 +1779,38 @@ tree
...
@@ -1486,6 +1779,38 @@ tree
expand_end_stmt_expr
(
t
)
expand_end_stmt_expr
(
t
)
tree
t
;
tree
t
;
{
{
if
(
output_bytecode
)
{
int
i
;
tree
t
;
/* At this point, all expressions have been evaluated in order.
However, all expression values have been popped when evaluated,
which means we have to recover the last expression value. This is
the last value removed by means of a `drop' instruction. Instead
of adding code to inhibit dropping the last expression value, it
is here recovered by undoing the `drop'. Since `drop' is
equivalent to `adjustackSI [1]', it can be undone with `adjstackSI
[-1]'. */
bc_adjust_stack
(
-
1
);
if
(
!
last_expr_type
)
last_expr_type
=
void_type_node
;
t
=
make_node
(
RTL_EXPR
);
TREE_TYPE
(
t
)
=
last_expr_type
;
RTL_EXPR_RTL
(
t
)
=
NULL
;
RTL_EXPR_SEQUENCE
(
t
)
=
NULL
;
/* Don't consider deleting this expr or containing exprs at tree level. */
TREE_THIS_VOLATILE
(
t
)
=
1
;
last_expr_type
=
0
;
return
t
;
}
OK_DEFER_POP
;
OK_DEFER_POP
;
if
(
last_expr_type
==
0
)
if
(
last_expr_type
==
0
)
...
@@ -1849,7 +2174,10 @@ expand_start_cond (cond, exitflag)
...
@@ -1849,7 +2174,10 @@ expand_start_cond (cond, exitflag)
cond_stack
=
thiscond
;
cond_stack
=
thiscond
;
nesting_stack
=
thiscond
;
nesting_stack
=
thiscond
;
do_jump
(
cond
,
thiscond
->
data
.
cond
.
next_label
,
NULL_RTX
);
if
(
output_bytecode
)
bc_expand_start_cond
(
cond
,
exitflag
);
else
do_jump
(
cond
,
thiscond
->
data
.
cond
.
next_label
,
NULL_RTX
);
}
}
/* Generate RTL between then-clause and the elseif-clause
/* Generate RTL between then-clause and the elseif-clause
...
@@ -1875,6 +2203,13 @@ expand_start_else ()
...
@@ -1875,6 +2203,13 @@ expand_start_else ()
{
{
if
(
cond_stack
->
data
.
cond
.
endif_label
==
0
)
if
(
cond_stack
->
data
.
cond
.
endif_label
==
0
)
cond_stack
->
data
.
cond
.
endif_label
=
gen_label_rtx
();
cond_stack
->
data
.
cond
.
endif_label
=
gen_label_rtx
();
if
(
output_bytecode
)
{
bc_expand_start_else
();
return
;
}
emit_jump
(
cond_stack
->
data
.
cond
.
endif_label
);
emit_jump
(
cond_stack
->
data
.
cond
.
endif_label
);
emit_label
(
cond_stack
->
data
.
cond
.
next_label
);
emit_label
(
cond_stack
->
data
.
cond
.
next_label
);
cond_stack
->
data
.
cond
.
next_label
=
0
;
/* No more _else or _elseif calls. */
cond_stack
->
data
.
cond
.
next_label
=
0
;
/* No more _else or _elseif calls. */
...
@@ -1888,15 +2223,71 @@ expand_end_cond ()
...
@@ -1888,15 +2223,71 @@ expand_end_cond ()
{
{
struct
nesting
*
thiscond
=
cond_stack
;
struct
nesting
*
thiscond
=
cond_stack
;
do_pending_stack_adjust
();
if
(
output_bytecode
)
if
(
thiscond
->
data
.
cond
.
next_label
)
bc_expand_end_cond
();
emit_label
(
thiscond
->
data
.
cond
.
next_label
);
else
if
(
thiscond
->
data
.
cond
.
endif_label
)
{
emit_label
(
thiscond
->
data
.
cond
.
endif_label
);
do_pending_stack_adjust
();
if
(
thiscond
->
data
.
cond
.
next_label
)
emit_label
(
thiscond
->
data
.
cond
.
next_label
);
if
(
thiscond
->
data
.
cond
.
endif_label
)
emit_label
(
thiscond
->
data
.
cond
.
endif_label
);
}
POPSTACK
(
cond_stack
);
POPSTACK
(
cond_stack
);
last_expr_type
=
0
;
last_expr_type
=
0
;
}
}
/* Generate code for the start of an if-then. COND is the expression
whose truth is to be tested; if EXITFLAG is nonzero this conditional
is to be visible to exit_something. It is assumed that the caller
has pushed the previous context on the cond stack. */
void
bc_expand_start_cond
(
cond
,
exitflag
)
tree
cond
;
int
exitflag
;
{
struct
nesting
*
thiscond
=
cond_stack
;
thiscond
->
data
.
case_stmt
.
nominal_type
=
cond
;
bc_expand_expr
(
cond
);
bc_emit_bytecode
(
jumpifnot
);
bc_emit_bytecode_labelref
(
thiscond
->
exit_label
->
bc_label
);
#ifdef DEBUG_PRINT_CODE
fputc
(
'\n'
,
stderr
);
#endif
}
/* Generate the label for the end of an if with
no else- clause. */
void
bc_expand_end_cond
()
{
struct
nesting
*
thiscond
=
cond_stack
;
bc_emit_bytecode_labeldef
(
thiscond
->
exit_label
->
bc_label
);
}
/* Generate code for the start of the else- clause of
an if-then-else. */
void
bc_expand_start_else
()
{
struct
nesting
*
thiscond
=
cond_stack
;
thiscond
->
data
.
cond
.
endif_label
=
thiscond
->
exit_label
;
thiscond
->
exit_label
=
gen_label_rtx
();
bc_emit_bytecode
(
jump
);
bc_emit_bytecode_labelref
(
thiscond
->
exit_label
->
bc_label
);
#ifdef DEBUG_PRINT_CODE
fputc
(
'\n'
,
stderr
);
#endif
bc_emit_bytecode_labeldef
(
thiscond
->
data
.
cond
.
endif_label
->
bc_label
);
}
/* Generate RTL for the start of a loop. EXIT_FLAG is nonzero if this
/* Generate RTL for the start of a loop. EXIT_FLAG is nonzero if this
loop should be exited by `exit_something'. This is a loop for which
loop should be exited by `exit_something'. This is a loop for which
...
@@ -1923,6 +2314,12 @@ expand_start_loop (exit_flag)
...
@@ -1923,6 +2314,12 @@ expand_start_loop (exit_flag)
loop_stack
=
thisloop
;
loop_stack
=
thisloop
;
nesting_stack
=
thisloop
;
nesting_stack
=
thisloop
;
if
(
output_bytecode
)
{
bc_emit_bytecode_labeldef
(
thisloop
->
data
.
loop
.
start_label
->
bc_label
);
return
thisloop
;
}
do_pending_stack_adjust
();
do_pending_stack_adjust
();
emit_queue
();
emit_queue
();
emit_note
(
NULL_PTR
,
NOTE_INSN_LOOP_BEG
);
emit_note
(
NULL_PTR
,
NOTE_INSN_LOOP_BEG
);
...
@@ -1951,21 +2348,54 @@ expand_start_loop_continue_elsewhere (exit_flag)
...
@@ -1951,21 +2348,54 @@ expand_start_loop_continue_elsewhere (exit_flag)
void
void
expand_loop_continue_here
()
expand_loop_continue_here
()
{
{
if
(
output_bytecode
)
{
bc_emit_bytecode_labeldef
(
loop_stack
->
data
.
loop
.
continue_label
->
bc_label
);
return
;
}
do_pending_stack_adjust
();
do_pending_stack_adjust
();
emit_note
(
NULL_PTR
,
NOTE_INSN_LOOP_CONT
);
emit_note
(
NULL_PTR
,
NOTE_INSN_LOOP_CONT
);
emit_label
(
loop_stack
->
data
.
loop
.
continue_label
);
emit_label
(
loop_stack
->
data
.
loop
.
continue_label
);
}
}
/* End a loop. */
static
void
bc_expand_end_loop
()
{
struct
nesting
*
thisloop
=
loop_stack
;
bc_emit_bytecode
(
jump
);
bc_emit_bytecode_labelref
(
thisloop
->
data
.
loop
.
start_label
->
bc_label
);
#ifdef DEBUG_PRINT_CODE
fputc
(
'\n'
,
stderr
);
#endif
bc_emit_bytecode_labeldef
(
thisloop
->
exit_label
->
bc_label
);
POPSTACK
(
loop_stack
);
last_expr_type
=
0
;
}
/* Finish a loop. Generate a jump back to the top and the loop-exit label.
/* Finish a loop. Generate a jump back to the top and the loop-exit label.
Pop the block off of loop_stack. */
Pop the block off of loop_stack. */
void
void
expand_end_loop
()
expand_end_loop
()
{
{
register
rtx
insn
=
get_last_insn
()
;
register
rtx
insn
;
register
rtx
start_label
=
loop_stack
->
data
.
loop
.
start_label
;
register
rtx
start_label
;
rtx
last_test_insn
=
0
;
rtx
last_test_insn
=
0
;
int
num_insns
=
0
;
int
num_insns
=
0
;
if
(
output_bytecode
)
{
bc_expand_end_loop
();
return
;
}
insn
=
get_last_insn
();
start_label
=
loop_stack
->
data
.
loop
.
start_label
;
/* Mark the continue-point at the top of the loop if none elsewhere. */
/* Mark the continue-point at the top of the loop if none elsewhere. */
if
(
start_label
==
loop_stack
->
data
.
loop
.
continue_label
)
if
(
start_label
==
loop_stack
->
data
.
loop
.
continue_label
)
...
@@ -2113,7 +2543,15 @@ expand_exit_loop_if_false (whichloop, cond)
...
@@ -2113,7 +2543,15 @@ expand_exit_loop_if_false (whichloop, cond)
whichloop
=
loop_stack
;
whichloop
=
loop_stack
;
if
(
whichloop
==
0
)
if
(
whichloop
==
0
)
return
0
;
return
0
;
do_jump
(
cond
,
whichloop
->
data
.
loop
.
end_label
,
NULL_RTX
);
if
(
output_bytecode
)
{
bc_expand_expr
(
cond
);
bc_expand_goto_internal
(
jumpifnot
,
whichloop
->
exit_label
->
bc_label
,
NULL_RTX
);
}
else
do_jump
(
cond
,
whichloop
->
data
.
loop
.
end_label
,
NULL_RTX
);
return
1
;
return
1
;
}
}
...
@@ -2176,6 +2614,12 @@ expand_null_return ()
...
@@ -2176,6 +2614,12 @@ expand_null_return ()
struct
nesting
*
block
=
block_stack
;
struct
nesting
*
block
=
block_stack
;
rtx
last_insn
=
0
;
rtx
last_insn
=
0
;
if
(
output_bytecode
)
{
bc_emit_instruction
(
ret
);
return
;
}
/* Does any pending block have cleanups? */
/* Does any pending block have cleanups? */
while
(
block
&&
block
->
data
.
block
.
cleanups
==
0
)
while
(
block
&&
block
->
data
.
block
.
cleanups
==
0
)
...
@@ -2298,6 +2742,15 @@ expand_return (retval)
...
@@ -2298,6 +2742,15 @@ expand_return (retval)
int
cleanups
;
int
cleanups
;
struct
nesting
*
block
;
struct
nesting
*
block
;
/* Bytecode returns are quite simple, just leave the result on the
arithmetic stack. */
if
(
output_bytecode
)
{
bc_expand_expr
(
retval
);
bc_emit_instruction
(
ret
);
return
;
}
/* If function wants no value, give it none. */
/* If function wants no value, give it none. */
if
(
TREE_CODE
(
TREE_TYPE
(
TREE_TYPE
(
current_function_decl
)))
==
VOID_TYPE
)
if
(
TREE_CODE
(
TREE_TYPE
(
TREE_TYPE
(
current_function_decl
)))
==
VOID_TYPE
)
{
{
...
@@ -2536,8 +2989,10 @@ expand_start_bindings (exit_flag)
...
@@ -2536,8 +2989,10 @@ expand_start_bindings (exit_flag)
int
exit_flag
;
int
exit_flag
;
{
{
struct
nesting
*
thisblock
=
ALLOC_NESTING
();
struct
nesting
*
thisblock
=
ALLOC_NESTING
();
rtx
note
;
rtx
note
=
emit_note
(
NULL_PTR
,
NOTE_INSN_BLOCK_BEG
);
if
(
!
output_bytecode
)
note
=
emit_note
(
NULL_PTR
,
NOTE_INSN_BLOCK_BEG
);
/* Make an entry on block_stack for the block we are entering. */
/* Make an entry on block_stack for the block we are entering. */
...
@@ -2580,8 +3035,11 @@ expand_start_bindings (exit_flag)
...
@@ -2580,8 +3035,11 @@ expand_start_bindings (exit_flag)
block_stack
=
thisblock
;
block_stack
=
thisblock
;
nesting_stack
=
thisblock
;
nesting_stack
=
thisblock
;
/* Make a new level for allocating stack slots. */
if
(
!
output_bytecode
)
push_temp_slots
();
{
/* Make a new level for allocating stack slots. */
push_temp_slots
();
}
}
}
/* Given a pointer to a BLOCK node, save a pointer to the most recently
/* Given a pointer to a BLOCK node, save a pointer to the most recently
...
@@ -2614,6 +3072,12 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
...
@@ -2614,6 +3072,12 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
register
struct
nesting
*
thisblock
=
block_stack
;
register
struct
nesting
*
thisblock
=
block_stack
;
register
tree
decl
;
register
tree
decl
;
if
(
output_bytecode
)
{
bc_expand_end_bindings
(
vars
,
mark_ends
,
dont_jump_in
);
return
;
}
if
(
warn_unused
)
if
(
warn_unused
)
for
(
decl
=
vars
;
decl
;
decl
=
TREE_CHAIN
(
decl
))
for
(
decl
=
vars
;
decl
;
decl
=
TREE_CHAIN
(
decl
))
if
(
!
TREE_USED
(
decl
)
&&
TREE_CODE
(
decl
)
==
VAR_DECL
if
(
!
TREE_USED
(
decl
)
&&
TREE_CODE
(
decl
)
==
VAR_DECL
...
@@ -2830,6 +3294,35 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
...
@@ -2830,6 +3294,35 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
/* Pop the stack slot nesting and free any slots at this level. */
/* Pop the stack slot nesting and free any slots at this level. */
pop_temp_slots
();
pop_temp_slots
();
}
}
/* End a binding contour.
VARS is the chain of VAR_DECL nodes for the variables bound
in this contour. MARK_ENDS is nonzer if we should put a note
at the beginning and end of this binding contour.
DONT_JUMP_IN is nonzero if it is not valid to jump into this
contour. */
void
bc_expand_end_bindings
(
vars
,
mark_ends
,
dont_jump_in
)
tree
vars
;
int
mark_ends
;
int
dont_jump_in
;
{
struct
nesting
*
thisbind
=
nesting_stack
;
tree
decl
;
if
(
warn_unused
)
for
(
decl
=
vars
;
decl
;
decl
=
TREE_CHAIN
(
decl
))
if
(
!
TREE_USED
(
TREE_VALUE
(
decl
))
&&
TREE_CODE
(
TREE_VALUE
(
decl
))
==
VAR_DECL
)
warning_with_decl
(
decl
,
"unused variable `%s'"
);
bc_emit_bytecode_labeldef
(
thisbind
->
exit_label
->
bc_label
);
/* Pop block/bindings off stack */
POPSTACK
(
nesting_stack
);
POPSTACK
(
block_stack
);
}
/* Generate RTL for the automatic variable declaration DECL.
/* Generate RTL for the automatic variable declaration DECL.
(Other kinds of declarations are simply ignored if seen here.)
(Other kinds of declarations are simply ignored if seen here.)
...
@@ -2854,7 +3347,15 @@ expand_decl (decl)
...
@@ -2854,7 +3347,15 @@ expand_decl (decl)
register
tree
decl
;
register
tree
decl
;
{
{
struct
nesting
*
thisblock
=
block_stack
;
struct
nesting
*
thisblock
=
block_stack
;
tree
type
=
TREE_TYPE
(
decl
);
tree
type
;
if
(
output_bytecode
)
{
bc_expand_decl
(
decl
,
0
);
return
;
}
type
=
TREE_TYPE
(
decl
);
/* Only automatic variables need any expansion done.
/* Only automatic variables need any expansion done.
Static and external variables, and external functions,
Static and external variables, and external functions,
...
@@ -3046,6 +3547,52 @@ expand_decl (decl)
...
@@ -3046,6 +3547,52 @@ expand_decl (decl)
if
(
obey_regdecls
)
if
(
obey_regdecls
)
use_variable
(
DECL_RTL
(
decl
));
use_variable
(
DECL_RTL
(
decl
));
}
}
/* Generate code for the automatic variable declaration DECL. For
most variables this just means we give it a stack offset. The
compiler sometimes emits cleanups without variables and we will
have to deal with those too. */
void
bc_expand_decl
(
decl
,
cleanup
)
tree
decl
;
tree
cleanup
;
{
tree
type
;
if
(
!
decl
)
{
/* A cleanup with no variable. */
if
(
!
cleanup
)
abort
();
return
;
}
/* Only auto variables need any work. */
if
(
TREE_CODE
(
decl
)
!=
VAR_DECL
||
TREE_STATIC
(
decl
)
||
DECL_EXTERNAL
(
decl
))
return
;
type
=
TREE_TYPE
(
decl
);
if
(
type
==
error_mark_node
)
DECL_RTL
(
decl
)
=
bc_gen_rtx
((
char
*
)
0
,
0
,
(
struct
bc_label
*
)
0
);
else
if
(
DECL_SIZE
(
decl
)
==
0
)
/* Variable with incomplete type. The stack offset herein will be
fixed later in expand_decl_init (). */
DECL_RTL
(
decl
)
=
bc_gen_rtx
((
char
*
)
0
,
0
,
(
struct
bc_label
*
)
0
);
else
if
(
TREE_CONSTANT
(
DECL_SIZE
(
decl
)))
{
DECL_RTL
(
decl
)
=
bc_allocate_local
(
TREE_INT_CST_LOW
(
DECL_SIZE
(
decl
))
/
BITS_PER_UNIT
,
DECL_ALIGN
(
decl
));
}
else
DECL_RTL
(
decl
)
=
bc_allocate_variable_array
(
DECL_SIZE
(
decl
));
}
/* Emit code to perform the initialization of a declaration DECL. */
/* Emit code to perform the initialization of a declaration DECL. */
...
@@ -3083,6 +3630,82 @@ expand_decl_init (decl)
...
@@ -3083,6 +3630,82 @@ expand_decl_init (decl)
free_temp_slots
();
free_temp_slots
();
}
}
/* Expand initialization for variable-sized types. Allocate array
using newlocalSI and set local variable, which is a pointer to the
storage. */
bc_expand_variable_local_init
(
decl
)
tree
decl
;
{
/* Evaluate size expression and coerce to SI */
bc_expand_expr
(
DECL_SIZE
(
decl
));
/* Type sizes are always (?) of TREE_CODE INTEGER_CST, so
no coercion is necessary (?) */
/* emit_typecode_conversion (preferred_typecode (TYPE_MODE (DECL_SIZE (decl)),
TREE_UNSIGNED (DECL_SIZE (decl))), SIcode); */
/* Emit code to allocate array */
bc_emit_instruction
(
newlocalSI
);
/* Store array pointer in local variable. This is the only instance
where we actually want the address of the pointer to the
variable-size block, rather than the pointer itself. We avoid
using expand_address() since that would cause the pointer to be
pushed rather than its address. Hence the hard-coded reference;
notice also that the variable is always local (no global
variable-size type variables). */
bc_load_localaddr
(
DECL_RTL
(
decl
));
bc_emit_instruction
(
storeP
);
}
/* Emit code to initialize a declaration. */
void
bc_expand_decl_init
(
decl
)
tree
decl
;
{
int
org_stack_depth
;
/* Statical initializers are handled elsewhere */
if
(
TREE_STATIC
(
decl
))
return
;
/* Memory original stack depth */
org_stack_depth
=
stack_depth
;
/* If the type is variable-size, we first create its space (we ASSUME
it CAN'T be static). We do this regardless of whether there's an
initializer assignment or not. */
if
(
TREE_CODE
(
DECL_SIZE
(
decl
))
!=
INTEGER_CST
)
bc_expand_variable_local_init
(
decl
);
/* Expand initializer assignment */
if
(
DECL_INITIAL
(
decl
)
==
error_mark_node
)
{
enum
tree_code
code
=
TREE_CODE
(
TREE_TYPE
(
decl
));
if
(
code
==
INTEGER_TYPE
||
code
==
REAL_TYPE
||
code
==
ENUMERAL_TYPE
||
code
==
POINTER_TYPE
)
expand_assignment
(
TREE_TYPE
(
decl
),
decl
,
convert
(
TREE_TYPE
(
decl
),
integer_zero_node
));
}
else
if
(
DECL_INITIAL
(
decl
))
expand_assignment
(
TREE_TYPE
(
decl
),
decl
,
DECL_INITIAL
(
decl
));
/* Restore stack depth */
if
(
org_stack_depth
>
stack_depth
)
abort
();
bc_adjust_stack
(
stack_depth
-
org_stack_depth
);
}
/* CLEANUP is an expression to be executed at exit from this binding contour;
/* CLEANUP is an expression to be executed at exit from this binding contour;
for example, in C++, it might call the destructor for this variable.
for example, in C++, it might call the destructor for this variable.
...
@@ -3301,6 +3924,12 @@ expand_start_case (exit_flag, expr, type, printname)
...
@@ -3301,6 +3924,12 @@ expand_start_case (exit_flag, expr, type, printname)
case_stack
=
thiscase
;
case_stack
=
thiscase
;
nesting_stack
=
thiscase
;
nesting_stack
=
thiscase
;
if
(
output_bytecode
)
{
bc_expand_start_case
(
thiscase
,
expr
,
type
,
printname
);
return
;
}
do_pending_stack_adjust
();
do_pending_stack_adjust
();
/* Make sure case_stmt.start points to something that won't
/* Make sure case_stmt.start points to something that won't
...
@@ -3311,6 +3940,32 @@ expand_start_case (exit_flag, expr, type, printname)
...
@@ -3311,6 +3940,32 @@ expand_start_case (exit_flag, expr, type, printname)
thiscase
->
data
.
case_stmt
.
start
=
get_last_insn
();
thiscase
->
data
.
case_stmt
.
start
=
get_last_insn
();
}
}
/* Enter a case statement. It is assumed that the caller has pushed
the current context onto the case stack. */
void
bc_expand_start_case
(
thiscase
,
expr
,
type
,
printname
)
struct
nesting
*
thiscase
;
tree
expr
;
tree
type
;
char
*
printname
;
{
bc_expand_expr
(
expr
);
bc_expand_conversion
(
TREE_TYPE
(
expr
),
type
);
/* For cases, the skip is a place we jump to that's emitted after
the size of the jump table is known. */
thiscase
->
data
.
case_stmt
.
skip_label
=
gen_label_rtx
();
bc_emit_bytecode
(
jump
);
bc_emit_bytecode_labelref
(
thiscase
->
data
.
case_stmt
.
skip_label
->
bc_label
);
#ifdef DEBUG_PRINT_CODE
fputc
(
'\n'
,
stderr
);
#endif
}
/* Start a "dummy case statement" within which case labels are invalid
/* Start a "dummy case statement" within which case labels are invalid
and are not connected to any larger real case statement.
and are not connected to any larger real case statement.
This can be used if you don't want to let a case statement jump
This can be used if you don't want to let a case statement jump
...
@@ -3382,6 +4037,9 @@ pushcase (value, converter, label, duplicate)
...
@@ -3382,6 +4037,9 @@ pushcase (value, converter, label, duplicate)
tree
index_type
;
tree
index_type
;
tree
nominal_type
;
tree
nominal_type
;
if
(
output_bytecode
)
return
bc_pushcase
(
value
,
label
);
/* Fail if not inside a real case statement. */
/* Fail if not inside a real case statement. */
if
(
!
(
case_stack
&&
case_stack
->
data
.
case_stmt
.
start
))
if
(
!
(
case_stack
&&
case_stack
->
data
.
case_stmt
.
start
))
return
1
;
return
1
;
...
@@ -3588,6 +4246,62 @@ pushcase_range (value1, value2, converter, label, duplicate)
...
@@ -3588,6 +4246,62 @@ pushcase_range (value1, value2, converter, label, duplicate)
return
0
;
return
0
;
}
}
/* Accumulate one case or default label; VALUE is the value of the
case, or nil for a default label. If not currently inside a case,
return 1 and do nothing. If VALUE is a duplicate or overlaps, return
2 and do nothing. If VALUE is out of range, return 3 and do nothing.
Return 0 on success. This function is a leftover from the earlier
bytecode compiler, which was based on gcc 1.37. It should be
merged into pushcase. */
int
bc_pushcase
(
value
,
label
)
tree
value
;
tree
label
;
{
struct
nesting
*
thiscase
=
case_stack
;
struct
case_node
*
case_label
,
*
new_label
;
if
(
!
thiscase
)
return
1
;
/* Fail if duplicate, overlap, or out of type range. */
if
(
value
)
{
value
=
convert
(
thiscase
->
data
.
case_stmt
.
nominal_type
,
value
);
if
(
!
int_fits_type_p
(
value
,
thiscase
->
data
.
case_stmt
.
nominal_type
))
return
3
;
for
(
case_label
=
thiscase
->
data
.
case_stmt
.
case_list
;
case_label
->
left
;
case_label
=
case_label
->
left
)
if
(
!
tree_int_cst_lt
(
case_label
->
left
->
high
,
value
))
break
;
if
(
case_label
!=
thiscase
->
data
.
case_stmt
.
case_list
&&
!
tree_int_cst_lt
(
case_label
->
high
,
value
)
||
case_label
->
left
&&
!
tree_int_cst_lt
(
value
,
case_label
->
left
->
low
))
return
2
;
new_label
=
(
struct
case_node
*
)
oballoc
(
sizeof
(
struct
case_node
));
new_label
->
low
=
new_label
->
high
=
copy_node
(
value
);
new_label
->
code_label
=
label
;
new_label
->
left
=
case_label
->
left
;
case_label
->
left
=
new_label
;
thiscase
->
data
.
case_stmt
.
num_ranges
++
;
}
else
{
if
(
thiscase
->
data
.
case_stmt
.
default_label
)
return
2
;
thiscase
->
data
.
case_stmt
.
default_label
=
label
;
}
expand_label
(
label
);
return
0
;
}
/* Called when the index of a switch statement is an enumerated type
/* Called when the index of a switch statement is an enumerated type
and there is no default label.
and there is no default label.
...
@@ -3609,6 +4323,12 @@ check_for_full_enumeration_handling (type)
...
@@ -3609,6 +4323,12 @@ check_for_full_enumeration_handling (type)
register
tree
chain
;
register
tree
chain
;
int
all_values
=
1
;
int
all_values
=
1
;
if
(
output_bytecode
)
{
bc_check_for_full_enumeration_handling
(
type
);
return
;
}
/* The time complexity of this loop is currently O(N * M), with
/* The time complexity of this loop is currently O(N * M), with
N being the number of members in the enumerated type, and
N being the number of members in the enumerated type, and
M being the number of case expressions in the switch. */
M being the number of case expressions in the switch. */
...
@@ -3707,6 +4427,46 @@ check_for_full_enumeration_handling (type)
...
@@ -3707,6 +4427,46 @@ check_for_full_enumeration_handling (type)
}
}
#endif /* 0 */
#endif /* 0 */
}
}
/* Check that all enumeration literals are covered by the case
expressions of a switch. Also warn if there are any cases
that are not elements of the enumerated type. */
void
bc_check_for_full_enumeration_handling
(
type
)
tree
type
;
{
struct
nesting
*
thiscase
=
case_stack
;
struct
case_node
*
c
;
tree
e
;
/* Check for enums not handled. */
for
(
e
=
TYPE_VALUES
(
type
);
e
;
e
=
TREE_CHAIN
(
e
))
{
for
(
c
=
thiscase
->
data
.
case_stmt
.
case_list
->
left
;
c
&&
tree_int_cst_lt
(
c
->
high
,
TREE_VALUE
(
e
));
c
=
c
->
left
)
;
if
(
!
(
c
&&
tree_int_cst_equal
(
c
->
low
,
TREE_VALUE
(
e
))))
warning
(
"enumerated value `%s' not handled in switch"
,
IDENTIFIER_POINTER
(
TREE_PURPOSE
(
e
)));
}
/* Check for cases not in the enumeration. */
for
(
c
=
thiscase
->
data
.
case_stmt
.
case_list
->
left
;
c
;
c
=
c
->
left
)
{
for
(
e
=
TYPE_VALUES
(
type
);
e
&&
!
tree_int_cst_equal
(
c
->
low
,
TREE_VALUE
(
e
));
e
=
TREE_CHAIN
(
e
))
;
if
(
!
e
)
warning
(
"case value `%d' not in enumerated type `%s'"
,
TREE_INT_CST_LOW
(
c
->
low
),
IDENTIFIER_POINTER
(
TREE_CODE
(
TYPE_NAME
(
type
))
==
IDENTIFIER_NODE
?
TYPE_NAME
(
type
)
:
DECL_NAME
(
TYPE_NAME
(
type
))));
}
}
/* Terminate a case (Pascal) or switch (C) statement
/* Terminate a case (Pascal) or switch (C) statement
in which ORIG_INDEX is the expression to be tested.
in which ORIG_INDEX is the expression to be tested.
...
@@ -3721,14 +4481,24 @@ expand_end_case (orig_index)
...
@@ -3721,14 +4481,24 @@ expand_end_case (orig_index)
register
struct
case_node
*
n
;
register
struct
case_node
*
n
;
int
count
;
int
count
;
rtx
index
;
rtx
index
;
rtx
table_label
=
gen_label_rtx
()
;
rtx
table_label
;
int
ncases
;
int
ncases
;
rtx
*
labelvec
;
rtx
*
labelvec
;
register
int
i
;
register
int
i
;
rtx
before_case
;
rtx
before_case
;
register
struct
nesting
*
thiscase
=
case_stack
;
register
struct
nesting
*
thiscase
=
case_stack
;
tree
index_expr
=
thiscase
->
data
.
case_stmt
.
index_expr
;
tree
index_expr
;
int
unsignedp
=
TREE_UNSIGNED
(
TREE_TYPE
(
index_expr
));
int
unsignedp
;
if
(
output_bytecode
)
{
bc_expand_end_case
(
orig_index
);
return
;
}
table_label
=
gen_label_rtx
();
index_expr
=
thiscase
->
data
.
case_stmt
.
index_expr
;
unsignedp
=
TREE_UNSIGNED
(
TREE_TYPE
(
index_expr
));
do_pending_stack_adjust
();
do_pending_stack_adjust
();
...
@@ -4069,6 +4839,110 @@ expand_end_case (orig_index)
...
@@ -4069,6 +4839,110 @@ expand_end_case (orig_index)
free_temp_slots
();
free_temp_slots
();
}
}
/* Terminate a case statement. EXPR is the original index
expression. */
void
bc_expand_end_case
(
expr
)
tree
expr
;
{
struct
nesting
*
thiscase
=
case_stack
;
enum
bytecode_opcode
opcode
;
struct
bc_label
*
jump_label
;
struct
case_node
*
c
;
bc_emit_bytecode
(
jump
);
bc_emit_bytecode_labelref
(
thiscase
->
exit_label
->
bc_label
);
#ifdef DEBUG_PRINT_CODE
fputc
(
'\n'
,
stderr
);
#endif
/* Now that the size of the jump table is known, emit the actual
indexed jump instruction. */
bc_emit_bytecode_labeldef
(
thiscase
->
data
.
case_stmt
.
skip_label
->
bc_label
);
opcode
=
TYPE_MODE
(
thiscase
->
data
.
case_stmt
.
nominal_type
)
==
SImode
?
TREE_UNSIGNED
(
thiscase
->
data
.
case_stmt
.
nominal_type
)
?
caseSU
:
caseSI
:
TREE_UNSIGNED
(
thiscase
->
data
.
case_stmt
.
nominal_type
)
?
caseDU
:
caseDI
;
bc_emit_bytecode
(
opcode
);
/* Now emit the case instructions literal arguments, in order.
In addition to the value on the stack, it uses:
1. The address of the jump table.
2. The size of the jump table.
3. The default label. */
jump_label
=
bc_get_bytecode_label
();
bc_emit_bytecode_labelref
(
jump_label
);
bc_emit_bytecode_const
((
char
*
)
&
thiscase
->
data
.
case_stmt
.
num_ranges
,
sizeof
thiscase
->
data
.
case_stmt
.
num_ranges
);
if
(
thiscase
->
data
.
case_stmt
.
default_label
)
bc_emit_bytecode_labelref
(
DECL_RTL
(
thiscase
->
data
.
case_stmt
.
default_label
)
->
bc_label
);
else
bc_emit_bytecode_labelref
(
thiscase
->
exit_label
->
bc_label
);
/* Output the jump table. */
bc_align_bytecode
(
3
/* PTR_ALIGN */
);
bc_emit_bytecode_labeldef
(
jump_label
);
if
(
TYPE_MODE
(
thiscase
->
data
.
case_stmt
.
nominal_type
)
==
SImode
)
for
(
c
=
thiscase
->
data
.
case_stmt
.
case_list
->
left
;
c
;
c
=
c
->
left
)
{
opcode
=
TREE_INT_CST_LOW
(
c
->
low
);
bc_emit_bytecode_const
((
char
*
)
&
opcode
,
sizeof
opcode
);
opcode
=
TREE_INT_CST_LOW
(
c
->
high
);
bc_emit_bytecode_const
((
char
*
)
&
opcode
,
sizeof
opcode
);
bc_emit_bytecode_labelref
(
DECL_RTL
(
c
->
code_label
)
->
bc_label
);
}
else
if
(
TYPE_MODE
(
thiscase
->
data
.
case_stmt
.
nominal_type
)
==
DImode
)
for
(
c
=
thiscase
->
data
.
case_stmt
.
case_list
->
left
;
c
;
c
=
c
->
left
)
{
bc_emit_bytecode_DI_const
(
c
->
low
);
bc_emit_bytecode_DI_const
(
c
->
high
);
bc_emit_bytecode_labelref
(
DECL_RTL
(
c
->
code_label
)
->
bc_label
);
}
else
/* Bad mode */
abort
();
bc_emit_bytecode_labeldef
(
thiscase
->
exit_label
->
bc_label
);
/* Possibly issue enumeration warnings. */
if
(
!
thiscase
->
data
.
case_stmt
.
default_label
&&
TREE_CODE
(
TREE_TYPE
(
expr
))
==
ENUMERAL_TYPE
&&
TREE_CODE
(
expr
)
!=
INTEGER_CST
&&
warn_switch
)
check_for_full_enumeration_handling
(
TREE_TYPE
(
expr
));
#ifdef DEBUG_PRINT_CODE
fputc
(
'\n'
,
stderr
);
#endif
POPSTACK
(
case_stack
);
}
/* Return unique bytecode ID. */
int
bc_new_uid
()
{
static
int
bc_uid
=
0
;
return
(
++
bc_uid
);
}
/* Generate code to jump to LABEL if OP1 and OP2 are equal. */
/* Generate code to jump to LABEL if OP1 and OP2 are equal. */
static
void
static
void
...
...
gcc/toplev.c
View file @
ca695ac9
...
@@ -57,6 +57,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -57,6 +57,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef XCOFF_DEBUGGING_INFO
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h"
#include "xcoffout.h"
#endif
#endif
#include "bytecode.h"
#include "bc-emit.h"
#ifdef VMS
#ifdef VMS
/* The extra parameters substantially improve the I/O performance. */
/* The extra parameters substantially improve the I/O performance. */
...
@@ -211,6 +214,9 @@ int errorcount = 0;
...
@@ -211,6 +214,9 @@ int errorcount = 0;
int
warningcount
=
0
;
int
warningcount
=
0
;
int
sorrycount
=
0
;
int
sorrycount
=
0
;
/* Flag to output bytecode instead of native assembler */
int
output_bytecode
=
0
;
/* Pointer to function to compute the name to use to print a declaration. */
/* Pointer to function to compute the name to use to print a declaration. */
char
*
(
*
decl_printable_name
)
();
char
*
(
*
decl_printable_name
)
();
...
@@ -515,6 +521,7 @@ struct { char *string; int *variable; int on_value;} f_options[] =
...
@@ -515,6 +521,7 @@ struct { char *string; int *variable; int on_value;} f_options[] =
{
"inhibit-size-directive"
,
&
flag_inhibit_size_directive
,
1
},
{
"inhibit-size-directive"
,
&
flag_inhibit_size_directive
,
1
},
{
"verbose-asm"
,
&
flag_verbose_asm
,
1
},
{
"verbose-asm"
,
&
flag_verbose_asm
,
1
},
{
"gnu-linker"
,
&
flag_gnu_linker
,
1
}
{
"gnu-linker"
,
&
flag_gnu_linker
,
1
}
{
"bytecode"
,
&
output_bytecode
,
1
}
};
};
/* Table of language-specific options. */
/* Table of language-specific options. */
...
@@ -885,11 +892,14 @@ void
...
@@ -885,11 +892,14 @@ void
fatal_insn_not_found
(
insn
)
fatal_insn_not_found
(
insn
)
rtx
insn
;
rtx
insn
;
{
{
if
(
INSN_CODE
(
insn
)
<
0
)
if
(
!
output_bytecode
)
error
(
"internal error--unrecognizable insn:"
,
0
);
{
else
if
(
INSN_CODE
(
insn
)
<
0
)
error
(
"internal error--insn does not satisfy its constraints:"
,
0
);
error
(
"internal error--unrecognizable insn:"
,
0
);
debug_rtx
(
insn
);
else
error
(
"internal error--insn does not satisfy its constraints:"
,
0
);
debug_rtx
(
insn
);
}
if
(
asm_out_file
)
if
(
asm_out_file
)
fflush
(
asm_out_file
);
fflush
(
asm_out_file
);
if
(
aux_info_file
)
if
(
aux_info_file
)
...
@@ -1585,6 +1595,8 @@ compile_file (name)
...
@@ -1585,6 +1595,8 @@ compile_file (name)
init_obstacks
();
init_obstacks
();
init_tree_codes
();
init_tree_codes
();
init_lex
();
init_lex
();
/* Some of these really don't need to be called when generating bytecode,
but the options would have to be parsed first to know that. -bson */
init_rtl
();
init_rtl
();
init_emit_once
(
debug_info_level
==
DINFO_LEVEL_NORMAL
init_emit_once
(
debug_info_level
==
DINFO_LEVEL_NORMAL
||
debug_info_level
==
DINFO_LEVEL_VERBOSE
);
||
debug_info_level
==
DINFO_LEVEL_VERBOSE
);
...
@@ -1813,34 +1825,51 @@ compile_file (name)
...
@@ -1813,34 +1825,51 @@ compile_file (name)
input_file_stack
->
next
=
0
;
input_file_stack
->
next
=
0
;
input_file_stack
->
name
=
input_filename
;
input_file_stack
->
name
=
input_filename
;
ASM_FILE_START
(
asm_out_file
);
if
(
!
output_bytecode
)
{
ASM_FILE_START
(
asm_out_file
);
}
/* Output something to inform GDB that this compilation was by GCC. */
/* Output something to inform GDB that this compilation was by GCC. Also
serves to tell GDB file consists of bytecodes. */
if
(
output_bytecode
)
fprintf
(
asm_out_file
,
"bc_gcc2_compiled.:
\n
"
);
else
{
#ifndef ASM_IDENTIFY_GCC
#ifndef ASM_IDENTIFY_GCC
fprintf
(
asm_out_file
,
"gcc2_compiled.:
\n
"
);
fprintf
(
asm_out_file
,
"gcc2_compiled.:
\n
"
);
#else
#else
ASM_IDENTIFY_GCC
(
asm_out_file
);
ASM_IDENTIFY_GCC
(
asm_out_file
);
#endif
#endif
}
/* Output something to identify which front-end produced this file. */
/* Output something to identify which front-end produced this file. */
#ifdef ASM_IDENTIFY_LANGUAGE
#ifdef ASM_IDENTIFY_LANGUAGE
ASM_IDENTIFY_LANGUAGE
(
asm_out_file
);
ASM_IDENTIFY_LANGUAGE
(
asm_out_file
);
#endif
#endif
/* ??? Note: There used to be a conditional here
if
(
output_bytecode
)
to call assemble_zeros without fail if DBX_DEBUGGING_INFO is defined.
{
This was to guarantee separation between gcc_compiled. and
if
(
profile_flag
||
profile_block_flag
)
the first function, for the sake of dbx on Suns.
error
(
"profiling not supported in bytecode compilation"
);
However, having the extra zero here confused the Emacs
}
code for unexec, and might confuse other programs too.
else
Therefore, I took out that change.
{
In future versions we should find another way to solve
/* ??? Note: There used to be a conditional here
that dbx problem. -- rms, 23 May 93. */
to call assemble_zeros without fail if DBX_DEBUGGING_INFO is defined.
This was to guarantee separation between gcc_compiled. and
/* Don't let the first function fall at the same address
the first function, for the sake of dbx on Suns.
as gcc_compiled., if profiling. */
However, having the extra zero here confused the Emacs
if
(
profile_flag
||
profile_block_flag
)
code for unexec, and might confuse other programs too.
assemble_zeros
(
UNITS_PER_WORD
);
Therefore, I took out that change.
In future versions we should find another way to solve
that dbx problem. -- rms, 23 May 93. */
/* Don't let the first function fall at the same address
as gcc_compiled., if profiling. */
if
(
profile_flag
||
profile_block_flag
)
assemble_zeros
(
UNITS_PER_WORD
);
}
/* If dbx symbol table desired, initialize writing it
/* If dbx symbol table desired, initialize writing it
and output the predefined types. */
and output the predefined types. */
...
@@ -1861,7 +1890,8 @@ compile_file (name)
...
@@ -1861,7 +1890,8 @@ compile_file (name)
/* Initialize yet another pass. */
/* Initialize yet another pass. */
init_final
(
main_input_filename
);
if
(
!
output_bytecode
)
init_final
(
main_input_filename
);
start_time
=
get_run_time
();
start_time
=
get_run_time
();
...
@@ -2031,11 +2061,14 @@ compile_file (name)
...
@@ -2031,11 +2061,14 @@ compile_file (name)
/* Output some stuff at end of file if nec. */
/* Output some stuff at end of file if nec. */
end_final
(
main_input_filename
);
if
(
!
output_bytecode
)
{
end_final
(
main_input_filename
);
#ifdef ASM_FILE_END
#ifdef ASM_FILE_END
ASM_FILE_END
(
asm_out_file
);
ASM_FILE_END
(
asm_out_file
);
#endif
#endif
}
after_finish_compilation
:
after_finish_compilation
:
...
@@ -2113,24 +2146,28 @@ compile_file (name)
...
@@ -2113,24 +2146,28 @@ compile_file (name)
{
{
fprintf
(
stderr
,
"
\n
"
);
fprintf
(
stderr
,
"
\n
"
);
print_time
(
"parse"
,
parse_time
);
print_time
(
"parse"
,
parse_time
);
print_time
(
"integration"
,
integration_time
);
print_time
(
"jump"
,
jump_time
);
if
(
!
output_bytecode
)
print_time
(
"cse"
,
cse_time
);
{
print_time
(
"loop"
,
loop_time
);
print_time
(
"integration"
,
integration_time
);
print_time
(
"cse2"
,
cse2_time
);
print_time
(
"jump"
,
jump_time
);
print_time
(
"flow"
,
flow_time
);
print_time
(
"cse"
,
cse_time
);
print_time
(
"combine"
,
combine_time
);
print_time
(
"loop"
,
loop_time
);
print_time
(
"sched"
,
sched_time
);
print_time
(
"cse2"
,
cse2_time
);
print_time
(
"local-alloc"
,
local_alloc_time
);
print_time
(
"flow"
,
flow_time
);
print_time
(
"global-alloc"
,
global_alloc_time
);
print_time
(
"combine"
,
combine_time
);
print_time
(
"sched2"
,
sched2_time
);
print_time
(
"sched"
,
sched_time
);
print_time
(
"dbranch"
,
dbr_sched_time
);
print_time
(
"local-alloc"
,
local_alloc_time
);
print_time
(
"shorten-branch"
,
shorten_branch_time
);
print_time
(
"global-alloc"
,
global_alloc_time
);
print_time
(
"stack-reg"
,
stack_reg_time
);
print_time
(
"sched2"
,
sched2_time
);
print_time
(
"final"
,
final_time
);
print_time
(
"dbranch"
,
dbr_sched_time
);
print_time
(
"varconst"
,
varconst_time
);
print_time
(
"shorten-branch"
,
shorten_branch_time
);
print_time
(
"symout"
,
symout_time
);
print_time
(
"stack-reg"
,
stack_reg_time
);
print_time
(
"dump"
,
dump_time
);
print_time
(
"final"
,
final_time
);
print_time
(
"varconst"
,
varconst_time
);
print_time
(
"symout"
,
symout_time
);
print_time
(
"dump"
,
dump_time
);
}
}
}
}
}
...
@@ -2236,6 +2273,9 @@ rest_of_compilation (decl)
...
@@ -2236,6 +2273,9 @@ rest_of_compilation (decl)
tree
saved_arguments
=
0
;
tree
saved_arguments
=
0
;
int
failure
=
0
;
int
failure
=
0
;
if
(
output_bytecode
)
return
;
/* If we are reconsidering an inline function
/* If we are reconsidering an inline function
at the end of compilation, skip the stuff for making it inline. */
at the end of compilation, skip the stuff for making it inline. */
...
@@ -3166,7 +3206,12 @@ main (argc, argv, envp)
...
@@ -3166,7 +3206,12 @@ main (argc, argv, envp)
error
(
"Invalid option `%s'"
,
argv
[
i
]);
error
(
"Invalid option `%s'"
,
argv
[
i
]);
}
}
else
if
(
!
strcmp
(
str
,
"p"
))
else
if
(
!
strcmp
(
str
,
"p"
))
profile_flag
=
1
;
{
if
(
!
output_bytecode
)
profile_flag
=
1
;
else
error
(
"profiling not supported in bytecode compilation"
);
}
else
if
(
!
strcmp
(
str
,
"a"
))
else
if
(
!
strcmp
(
str
,
"a"
))
{
{
#if !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER)
#if !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER)
...
@@ -3325,6 +3370,18 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
...
@@ -3325,6 +3370,18 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
filename
=
argv
[
i
];
filename
=
argv
[
i
];
}
}
/* Initialize for bytecode output. A good idea to do this as soon as
possible after the "-f" options have been parsed. */
if
(
output_bytecode
)
{
#ifndef TARGET_SUPPORTS_BYTECODE
/* Just die with a fatal error if not supported */
fatal
(
"-fbytecode can not be used for this target"
);
#else
bc_initialize
();
#endif
}
if
(
optimize
==
0
)
if
(
optimize
==
0
)
{
{
/* Inlining does not work if not optimizing,
/* Inlining does not work if not optimizing,
...
@@ -3398,10 +3455,14 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
...
@@ -3398,10 +3455,14 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
}
}
/* Now that register usage is specified, convert it to HARD_REG_SETs. */
/* Now that register usage is specified, convert it to HARD_REG_SETs. */
init_reg_sets_1
();
if
(
!
output_bytecode
)
init_reg_sets_1
();
compile_file
(
filename
);
compile_file
(
filename
);
if
(
output_bytecode
)
bc_write_file
(
stdout
);
#ifndef OS2
#ifndef OS2
#ifndef VMS
#ifndef VMS
if
(
flag_print_mem
)
if
(
flag_print_mem
)
...
...
gcc/varasm.c
View file @
ca695ac9
...
@@ -38,6 +38,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -38,6 +38,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "regs.h"
#include "regs.h"
#include "defaults.h"
#include "defaults.h"
#include "real.h"
#include "real.h"
#include "bytecode.h"
#include "obstack.h"
#include "obstack.h"
...
@@ -96,9 +97,11 @@ void assemble_name ();
...
@@ -96,9 +97,11 @@ void assemble_name ();
int
output_addressed_constants
();
int
output_addressed_constants
();
void
output_constant
();
void
output_constant
();
void
output_constructor
();
void
output_constructor
();
void
output_byte_asm
();
void
text_section
();
void
text_section
();
void
readonly_data_section
();
void
readonly_data_section
();
void
data_section
();
void
data_section
();
static
void
bc_assemble_integer
();
#ifdef EXTRA_SECTIONS
#ifdef EXTRA_SECTIONS
static
enum
in_section
{
no_section
,
in_text
,
in_data
,
EXTRA_SECTIONS
}
in_section
static
enum
in_section
{
no_section
,
in_text
,
in_data
,
EXTRA_SECTIONS
}
in_section
...
@@ -120,7 +123,11 @@ text_section ()
...
@@ -120,7 +123,11 @@ text_section ()
{
{
if
(
in_section
!=
in_text
)
if
(
in_section
!=
in_text
)
{
{
fprintf
(
asm_out_file
,
"%s
\n
"
,
TEXT_SECTION_ASM_OP
);
if
(
output_bytecode
)
bc_text
();
else
fprintf
(
asm_out_file
,
"%s
\n
"
,
TEXT_SECTION_ASM_OP
);
in_section
=
in_text
;
in_section
=
in_text
;
}
}
}
}
...
@@ -132,16 +139,21 @@ data_section ()
...
@@ -132,16 +139,21 @@ data_section ()
{
{
if
(
in_section
!=
in_data
)
if
(
in_section
!=
in_data
)
{
{
if
(
flag_shared_data
)
if
(
output_bytecode
)
bc_data
();
else
{
{
if
(
flag_shared_data
)
{
#ifdef SHARED_SECTION_ASM_OP
#ifdef SHARED_SECTION_ASM_OP
fprintf
(
asm_out_file
,
"%s
\n
"
,
SHARED_SECTION_ASM_OP
);
fprintf
(
asm_out_file
,
"%s
\n
"
,
SHARED_SECTION_ASM_OP
);
#else
#else
fprintf
(
asm_out_file
,
"%s
\n
"
,
DATA_SECTION_ASM_OP
);
fprintf
(
asm_out_file
,
"%s
\n
"
,
DATA_SECTION_ASM_OP
);
#endif
#endif
}
else
fprintf
(
asm_out_file
,
"%s
\n
"
,
DATA_SECTION_ASM_OP
);
}
}
else
fprintf
(
asm_out_file
,
"%s
\n
"
,
DATA_SECTION_ASM_OP
);
in_section
=
in_data
;
in_section
=
in_data
;
}
}
...
@@ -178,6 +190,16 @@ make_function_rtl (decl)
...
@@ -178,6 +190,16 @@ make_function_rtl (decl)
{
{
char
*
name
=
IDENTIFIER_POINTER
(
DECL_ASSEMBLER_NAME
(
decl
));
char
*
name
=
IDENTIFIER_POINTER
(
DECL_ASSEMBLER_NAME
(
decl
));
if
(
output_bytecode
)
{
if
(
DECL_RTL
(
decl
)
==
0
)
DECL_RTL
(
decl
)
=
bc_gen_rtx
(
name
,
0
,
(
struct
bc_label
*
)
0
);
/* Record that at least one function has been defined. */
function_defined
=
1
;
return
;
}
/* Rename a nested function to avoid conflicts. */
/* Rename a nested function to avoid conflicts. */
if
(
decl_function_context
(
decl
)
!=
0
if
(
decl_function_context
(
decl
)
!=
0
&&
DECL_INITIAL
(
decl
)
!=
0
&&
DECL_INITIAL
(
decl
)
!=
0
...
@@ -211,6 +233,48 @@ make_function_rtl (decl)
...
@@ -211,6 +233,48 @@ make_function_rtl (decl)
function_defined
=
1
;
function_defined
=
1
;
}
}
/* Create the DECL_RTL for a declaration for a static or external
variable or static or external function.
ASMSPEC, if not 0, is the string which the user specified
as the assembler symbol name.
TOP_LEVEL is nonzero if this is a file-scope variable.
This is never called for PARM_DECLs. */
void
bc_make_decl_rtl
(
decl
,
asmspec
,
top_level
)
tree
decl
;
char
*
asmspec
;
int
top_level
;
{
register
char
*
name
=
TREE_STRING_POINTER
(
DECL_ASSEMBLER_NAME
(
decl
));
if
(
DECL_RTL
(
decl
)
==
0
)
{
/* Print an error message for register variables. */
if
(
DECL_REGISTER
(
decl
)
&&
TREE_CODE
(
decl
)
==
FUNCTION_DECL
)
error
(
"function declared `register'"
);
else
if
(
DECL_REGISTER
(
decl
))
error
(
"global register variables not supported in the interpreter"
);
/* Handle ordinary static variables and functions. */
if
(
DECL_RTL
(
decl
)
==
0
)
{
/* Can't use just the variable's own name for a variable
whose scope is less than the whole file.
Concatenate a distinguishing number. */
if
(
!
top_level
&&
!
DECL_EXTERNAL
(
decl
)
&&
asmspec
==
0
)
{
char
*
label
;
ASM_FORMAT_PRIVATE_NAME
(
label
,
name
,
var_labelno
);
name
=
obstack_copy0
(
saveable_obstack
,
label
,
strlen
(
label
));
var_labelno
++
;
}
DECL_RTL
(
decl
)
=
bc_gen_rtx
(
name
,
0
,
(
struct
bc_label
*
)
0
);
}
}
}
/* Given NAME, a putative register name, discard any customary prefixes. */
/* Given NAME, a putative register name, discard any customary prefixes. */
static
char
*
static
char
*
...
@@ -301,7 +365,15 @@ make_decl_rtl (decl, asmspec, top_level)
...
@@ -301,7 +365,15 @@ make_decl_rtl (decl, asmspec, top_level)
int
top_level
;
int
top_level
;
{
{
register
char
*
name
;
register
char
*
name
;
int
reg_number
=
decode_reg_name
(
asmspec
);
int
reg_number
;
if
(
output_bytecode
)
{
bc_make_decl_rtl
(
decl
,
asmspec
,
top_level
);
return
;
}
reg_number
=
decode_reg_name
(
asmspec
);
if
(
DECL_ASSEMBLER_NAME
(
decl
)
!=
NULL_TREE
)
if
(
DECL_ASSEMBLER_NAME
(
decl
)
!=
NULL_TREE
)
name
=
IDENTIFIER_POINTER
(
DECL_ASSEMBLER_NAME
(
decl
));
name
=
IDENTIFIER_POINTER
(
DECL_ASSEMBLER_NAME
(
decl
));
...
@@ -465,6 +537,12 @@ void
...
@@ -465,6 +537,12 @@ void
assemble_asm
(
string
)
assemble_asm
(
string
)
tree
string
;
tree
string
;
{
{
if
(
output_bytecode
)
{
error
(
"asm statements not allowed in interpreter"
);
return
;
}
app_enable
();
app_enable
();
if
(
TREE_CODE
(
string
)
==
ADDR_EXPR
)
if
(
TREE_CODE
(
string
)
==
ADDR_EXPR
)
...
@@ -576,7 +654,12 @@ assemble_start_function (decl, fnname)
...
@@ -576,7 +654,12 @@ assemble_start_function (decl, fnname)
/* Tell assembler to move to target machine's alignment for functions. */
/* Tell assembler to move to target machine's alignment for functions. */
align
=
floor_log2
(
FUNCTION_BOUNDARY
/
BITS_PER_UNIT
);
align
=
floor_log2
(
FUNCTION_BOUNDARY
/
BITS_PER_UNIT
);
if
(
align
>
0
)
if
(
align
>
0
)
ASM_OUTPUT_ALIGN
(
asm_out_file
,
align
);
{
if
(
output_bytecode
)
BC_OUTPUT_ALIGN
(
asm_out_file
,
align
);
else
ASM_OUTPUT_ALIGN
(
asm_out_file
,
align
);
}
#ifdef ASM_OUTPUT_FUNCTION_PREFIX
#ifdef ASM_OUTPUT_FUNCTION_PREFIX
ASM_OUTPUT_FUNCTION_PREFIX
(
asm_out_file
,
fnname
);
ASM_OUTPUT_FUNCTION_PREFIX
(
asm_out_file
,
fnname
);
...
@@ -600,7 +683,10 @@ assemble_start_function (decl, fnname)
...
@@ -600,7 +683,10 @@ assemble_start_function (decl, fnname)
{
{
if
(
!
first_global_object_name
)
if
(
!
first_global_object_name
)
STRIP_NAME_ENCODING
(
first_global_object_name
,
fnname
);
STRIP_NAME_ENCODING
(
first_global_object_name
,
fnname
);
ASM_GLOBALIZE_LABEL
(
asm_out_file
,
fnname
);
if
(
output_bytecode
)
BC_GLOBALIZE_LABEL
(
asm_out_file
,
fnname
);
else
ASM_GLOBALIZE_LABEL
(
asm_out_file
,
fnname
);
}
}
/* Do any machine/system dependent processing of the function name */
/* Do any machine/system dependent processing of the function name */
...
@@ -608,7 +694,10 @@ assemble_start_function (decl, fnname)
...
@@ -608,7 +694,10 @@ assemble_start_function (decl, fnname)
ASM_DECLARE_FUNCTION_NAME
(
asm_out_file
,
fnname
,
current_function_decl
);
ASM_DECLARE_FUNCTION_NAME
(
asm_out_file
,
fnname
,
current_function_decl
);
#else
#else
/* Standard thing is just output label for the function. */
/* Standard thing is just output label for the function. */
ASM_OUTPUT_LABEL
(
asm_out_file
,
fnname
);
if
(
output_bytecode
)
BC_OUTPUT_LABEL
(
asm_out_file
,
fnname
);
else
ASM_OUTPUT_LABEL
(
asm_out_file
,
fnname
);
#endif
/* ASM_DECLARE_FUNCTION_NAME */
#endif
/* ASM_DECLARE_FUNCTION_NAME */
}
}
...
@@ -631,6 +720,12 @@ void
...
@@ -631,6 +720,12 @@ void
assemble_zeros
(
size
)
assemble_zeros
(
size
)
int
size
;
int
size
;
{
{
if
(
output_bytecode
)
{
bc_emit_const_skip
(
size
);
return
;
}
#ifdef ASM_NO_SKIP_IN_TEXT
#ifdef ASM_NO_SKIP_IN_TEXT
/* The `space' pseudo in the text section outputs nop insns rather than 0s,
/* The `space' pseudo in the text section outputs nop insns rather than 0s,
so we must output 0s explicitly in the text section. */
so we must output 0s explicitly in the text section. */
...
@@ -664,7 +759,12 @@ assemble_zeros (size)
...
@@ -664,7 +759,12 @@ assemble_zeros (size)
else
else
#endif
#endif
if
(
size
>
0
)
if
(
size
>
0
)
ASM_OUTPUT_SKIP
(
asm_out_file
,
size
);
{
if
(
output_bytecode
)
BC_OUTPUT_SKIP
(
asm_out_file
,
size
);
else
ASM_OUTPUT_SKIP
(
asm_out_file
,
size
);
}
}
}
/* Assemble an alignment pseudo op for an ALIGN-bit boundary. */
/* Assemble an alignment pseudo op for an ALIGN-bit boundary. */
...
@@ -688,6 +788,12 @@ assemble_string (p, size)
...
@@ -688,6 +788,12 @@ assemble_string (p, size)
int
pos
=
0
;
int
pos
=
0
;
int
maximum
=
2000
;
int
maximum
=
2000
;
if
(
output_bytecode
)
{
bc_emit
(
p
,
size
);
return
;
}
/* If the string is very long, split it up. */
/* If the string is very long, split it up. */
while
(
pos
<
size
)
while
(
pos
<
size
)
...
@@ -696,7 +802,10 @@ assemble_string (p, size)
...
@@ -696,7 +802,10 @@ assemble_string (p, size)
if
(
thissize
>
maximum
)
if
(
thissize
>
maximum
)
thissize
=
maximum
;
thissize
=
maximum
;
ASM_OUTPUT_ASCII
(
asm_out_file
,
p
,
thissize
);
if
(
output_bytecode
)
BC_OUTPUT_ASCII
(
asm_out_file
,
p
,
thissize
);
else
ASM_OUTPUT_ASCII
(
asm_out_file
,
p
,
thissize
);
pos
+=
thissize
;
pos
+=
thissize
;
p
+=
thissize
;
p
+=
thissize
;
...
@@ -725,6 +834,9 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
...
@@ -725,6 +834,9 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
int
reloc
=
0
;
int
reloc
=
0
;
enum
in_section
saved_in_section
;
enum
in_section
saved_in_section
;
if
(
output_bytecode
)
return
;
if
(
GET_CODE
(
DECL_RTL
(
decl
))
==
REG
)
if
(
GET_CODE
(
DECL_RTL
(
decl
))
==
REG
)
{
{
/* Do output symbol info for global register variables, but do nothing
/* Do output symbol info for global register variables, but do nothing
...
@@ -734,19 +846,22 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
...
@@ -734,19 +846,22 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
return
;
return
;
TREE_ASM_WRITTEN
(
decl
)
=
1
;
TREE_ASM_WRITTEN
(
decl
)
=
1
;
if
(
!
output_bytecode
)
{
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
/* File-scope global variables are output here. */
/* File-scope global variables are output here. */
if
((
write_symbols
==
DBX_DEBUG
||
write_symbols
==
XCOFF_DEBUG
)
if
((
write_symbols
==
DBX_DEBUG
||
write_symbols
==
XCOFF_DEBUG
)
&&
top_level
)
&&
top_level
)
dbxout_symbol
(
decl
,
0
);
dbxout_symbol
(
decl
,
0
);
#endif
#endif
#ifdef SDB_DEBUGGING_INFO
#ifdef SDB_DEBUGGING_INFO
if
(
write_symbols
==
SDB_DEBUG
&&
top_level
if
(
write_symbols
==
SDB_DEBUG
&&
top_level
/* Leave initialized global vars for end of compilation;
/* Leave initialized global vars for end of compilation;
see comment in compile_file. */
see comment in compile_file. */
&&
(
TREE_PUBLIC
(
decl
)
==
0
||
DECL_INITIAL
(
decl
)
==
0
))
&&
(
TREE_PUBLIC
(
decl
)
==
0
||
DECL_INITIAL
(
decl
)
==
0
))
sdbout_symbol
(
decl
,
0
);
sdbout_symbol
(
decl
,
0
);
#endif
#endif
}
/* Don't output any DWARF debugging information for variables here.
/* Don't output any DWARF debugging information for variables here.
In the case of local variables, the information for them is output
In the case of local variables, the information for them is output
...
@@ -880,12 +995,17 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
...
@@ -880,12 +995,17 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
ASM_OUTPUT_SHARED_COMMON
(
asm_out_file
,
name
,
size
,
rounded
);
ASM_OUTPUT_SHARED_COMMON
(
asm_out_file
,
name
,
size
,
rounded
);
else
else
#endif
#endif
if
(
output_bytecode
)
BC_OUTPUT_COMMON
(
asm_out_file
,
name
,
size
,
rounded
);
else
{
#ifdef ASM_OUTPUT_ALIGNED_COMMON
#ifdef ASM_OUTPUT_ALIGNED_COMMON
ASM_OUTPUT_ALIGNED_COMMON
(
asm_out_file
,
name
,
size
,
ASM_OUTPUT_ALIGNED_COMMON
(
asm_out_file
,
name
,
size
,
DECL_ALIGN
(
decl
));
DECL_ALIGN
(
decl
));
#else
#else
ASM_OUTPUT_COMMON
(
asm_out_file
,
name
,
size
,
rounded
);
ASM_OUTPUT_COMMON
(
asm_out_file
,
name
,
size
,
rounded
);
#endif
#endif
}
}
}
else
else
{
{
...
@@ -894,12 +1014,17 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
...
@@ -894,12 +1014,17 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
ASM_OUTPUT_SHARED_LOCAL
(
asm_out_file
,
name
,
size
,
rounded
);
ASM_OUTPUT_SHARED_LOCAL
(
asm_out_file
,
name
,
size
,
rounded
);
else
else
#endif
#endif
if
(
output_bytecode
)
BC_OUTPUT_LOCAL
(
asm_out_file
,
name
,
size
,
rounded
);
else
{
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
ASM_OUTPUT_ALIGNED_LOCAL
(
asm_out_file
,
name
,
size
,
ASM_OUTPUT_ALIGNED_LOCAL
(
asm_out_file
,
name
,
size
,
DECL_ALIGN
(
decl
));
DECL_ALIGN
(
decl
));
#else
#else
ASM_OUTPUT_LOCAL
(
asm_out_file
,
name
,
size
,
rounded
);
ASM_OUTPUT_LOCAL
(
asm_out_file
,
name
,
size
,
rounded
);
#endif
#endif
}
}
}
goto
finish
;
goto
finish
;
}
}
...
@@ -1017,14 +1142,22 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
...
@@ -1017,14 +1142,22 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
DECL_ALIGN
(
decl
)
=
align
;
DECL_ALIGN
(
decl
)
=
align
;
if
(
align
>
BITS_PER_UNIT
)
if
(
align
>
BITS_PER_UNIT
)
ASM_OUTPUT_ALIGN
(
asm_out_file
,
floor_log2
(
align
/
BITS_PER_UNIT
));
{
if
(
output_bytecode
)
BC_OUTPUT_ALIGN
(
asm_out_file
,
floor_log2
(
align
/
BITS_PER_UNIT
));
else
ASM_OUTPUT_ALIGN
(
asm_out_file
,
floor_log2
(
align
/
BITS_PER_UNIT
));
}
/* Do any machine/system dependent processing of the object. */
/* Do any machine/system dependent processing of the object. */
#ifdef ASM_DECLARE_OBJECT_NAME
#ifdef ASM_DECLARE_OBJECT_NAME
ASM_DECLARE_OBJECT_NAME
(
asm_out_file
,
name
,
decl
);
ASM_DECLARE_OBJECT_NAME
(
asm_out_file
,
name
,
decl
);
#else
#else
/* Standard thing is just output label for the object. */
/* Standard thing is just output label for the object. */
ASM_OUTPUT_LABEL
(
asm_out_file
,
name
);
if
(
output_bytecode
)
BC_OUTPUT_LABEL
(
asm_out_file
,
name
);
else
ASM_OUTPUT_LABEL
(
asm_out_file
,
name
);
#endif
/* ASM_DECLARE_OBJECT_NAME */
#endif
/* ASM_DECLARE_OBJECT_NAME */
if
(
!
dont_output_data
)
if
(
!
dont_output_data
)
...
@@ -1110,6 +1243,55 @@ contains_pointers_p (type)
...
@@ -1110,6 +1243,55 @@ contains_pointers_p (type)
}
}
}
}
/* Output text storage for constructor CONSTR. Returns rtx of
storage. */
rtx
bc_output_constructor
(
constr
)
tree
constr
;
{
int
i
;
/* Must always be a literal; non-literal constructors are handled
differently. */
if
(
!
TREE_CONSTANT
(
constr
))
abort
();
/* Always const */
text_section
();
/* Align */
for
(
i
=
0
;
TYPE_ALIGN
(
constr
)
>=
BITS_PER_UNIT
<<
(
i
+
1
);
i
++
);
if
(
i
>
0
)
BC_OUTPUT_ALIGN
(
asm_out_file
,
i
);
/* Output data */
output_constant
(
constr
,
int_size_in_bytes
(
TREE_TYPE
(
constr
)));
}
/* Create storage for constructor CONSTR. */
void
bc_output_data_constructor
(
constr
)
tree
constr
;
{
int
i
;
/* Put in data section */
data_section
();
/* Align */
for
(
i
=
0
;
TYPE_ALIGN
(
constr
)
>=
BITS_PER_UNIT
<<
(
i
+
1
);
i
++
);
if
(
i
>
0
)
BC_OUTPUT_ALIGN
(
asm_out_file
,
i
);
/* The constructor is filled in at runtime. */
BC_OUTPUT_SKIP
(
asm_out_file
,
int_size_in_bytes
(
TREE_TYPE
(
constr
)));
}
/* Output something to declare an external symbol to the assembler.
/* Output something to declare an external symbol to the assembler.
(Most assemblers don't need this, so we normally output nothing.)
(Most assemblers don't need this, so we normally output nothing.)
Do nothing if DECL is not external. */
Do nothing if DECL is not external. */
...
@@ -1118,6 +1300,9 @@ void
...
@@ -1118,6 +1300,9 @@ void
assemble_external
(
decl
)
assemble_external
(
decl
)
tree
decl
;
tree
decl
;
{
{
if
(
output_bytecode
)
return
;
#ifdef ASM_OUTPUT_EXTERNAL
#ifdef ASM_OUTPUT_EXTERNAL
if
(
TREE_CODE_CLASS
(
TREE_CODE
(
decl
))
==
'd'
if
(
TREE_CODE_CLASS
(
TREE_CODE
(
decl
))
==
'd'
&&
DECL_EXTERNAL
(
decl
)
&&
TREE_PUBLIC
(
decl
))
&&
DECL_EXTERNAL
(
decl
)
&&
TREE_PUBLIC
(
decl
))
...
@@ -1142,11 +1327,14 @@ assemble_external_libcall (fun)
...
@@ -1142,11 +1327,14 @@ assemble_external_libcall (fun)
rtx
fun
;
rtx
fun
;
{
{
#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL
#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL
/* Declare library function name external when first used, if nec. */
if
(
!
output_bytecode
)
if
(
!
SYMBOL_REF_USED
(
fun
))
{
{
SYMBOL_REF_USED
(
fun
)
=
1
;
/* Declare library function name external when first used, if nec. */
ASM_OUTPUT_EXTERNAL_LIBCALL
(
asm_out_file
,
fun
);
if
(
!
SYMBOL_REF_USED
(
fun
))
{
SYMBOL_REF_USED
(
fun
)
=
1
;
ASM_OUTPUT_EXTERNAL_LIBCALL
(
asm_out_file
,
fun
);
}
}
}
#endif
#endif
}
}
...
@@ -1166,7 +1354,10 @@ void
...
@@ -1166,7 +1354,10 @@ void
assemble_label
(
name
)
assemble_label
(
name
)
char
*
name
;
char
*
name
;
{
{
ASM_OUTPUT_LABEL
(
asm_out_file
,
name
);
if
(
output_bytecode
)
BC_OUTPUT_LABEL
(
asm_out_file
,
name
);
else
ASM_OUTPUT_LABEL
(
asm_out_file
,
name
);
}
}
/* Output to FILE a reference to the assembler name of a C-level name NAME.
/* Output to FILE a reference to the assembler name of a C-level name NAME.
...
@@ -1181,9 +1372,19 @@ assemble_name (file, name)
...
@@ -1181,9 +1372,19 @@ assemble_name (file, name)
char
*
name
;
char
*
name
;
{
{
if
(
name
[
0
]
==
'*'
)
if
(
name
[
0
]
==
'*'
)
fputs
(
&
name
[
1
],
file
);
{
if
(
output_bytecode
)
bc_emit_labelref
(
name
);
else
fputs
(
&
name
[
1
],
file
);
}
else
else
ASM_OUTPUT_LABELREF
(
file
,
name
);
{
if
(
output_bytecode
)
BC_OUTPUT_LABELREF
(
file
,
name
);
else
ASM_OUTPUT_LABELREF
(
file
,
name
);
}
}
}
/* Allocate SIZE bytes writable static space with a gensym name
/* Allocate SIZE bytes writable static space with a gensym name
...
@@ -1214,12 +1415,21 @@ assemble_static_space (size)
...
@@ -1214,12 +1415,21 @@ assemble_static_space (size)
strlen
(
name
)
+
2
);
strlen
(
name
)
+
2
);
strcpy
(
namestring
,
name
);
strcpy
(
namestring
,
name
);
x
=
gen_rtx
(
SYMBOL_REF
,
Pmode
,
namestring
);
if
(
output_bytecode
)
x
=
bc_gen_rtx
(
namestring
,
0
,
(
struct
bc_label
*
)
0
);
else
x
=
gen_rtx
(
SYMBOL_REF
,
Pmode
,
namestring
);
if
(
output_bytecode
)
BC_OUTPUT_LOCAL
(
asm_out_file
,
name
,
size
,
rounded
);
else
{
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
ASM_OUTPUT_ALIGNED_LOCAL
(
asm_out_file
,
name
,
size
,
BIGGEST_ALIGNMENT
);
ASM_OUTPUT_ALIGNED_LOCAL
(
asm_out_file
,
name
,
size
,
BIGGEST_ALIGNMENT
);
#else
#else
ASM_OUTPUT_LOCAL
(
asm_out_file
,
name
,
size
,
rounded
);
ASM_OUTPUT_LOCAL
(
asm_out_file
,
name
,
size
,
rounded
);
#endif
#endif
}
return
x
;
return
x
;
}
}
...
@@ -1234,6 +1444,10 @@ assemble_trampoline_template ()
...
@@ -1234,6 +1444,10 @@ assemble_trampoline_template ()
char
*
name
;
char
*
name
;
int
align
;
int
align
;
/* Shouldn't get here */
if
(
output_bytecode
)
abort
();
/* By default, put trampoline templates in read-only data section. */
/* By default, put trampoline templates in read-only data section. */
#ifdef TRAMPOLINE_SECTION
#ifdef TRAMPOLINE_SECTION
...
@@ -1683,9 +1897,13 @@ decode_addr_const (exp, value)
...
@@ -1683,9 +1897,13 @@ decode_addr_const (exp, value)
break
;
break
;
case
LABEL_DECL
:
case
LABEL_DECL
:
x
=
gen_rtx
(
MEM
,
FUNCTION_MODE
,
if
(
output_bytecode
)
gen_rtx
(
LABEL_REF
,
VOIDmode
,
/* FIXME: this may not be correct, check it */
label_rtx
(
TREE_OPERAND
(
exp
,
0
))));
x
=
bc_gen_rtx
(
TREE_STRING_POINTER
(
target
),
0
,
(
struct
bc_label
*
)
0
);
else
x
=
gen_rtx
(
MEM
,
FUNCTION_MODE
,
gen_rtx
(
LABEL_REF
,
VOIDmode
,
label_rtx
(
TREE_OPERAND
(
exp
,
0
))));
break
;
break
;
case
REAL_CST
:
case
REAL_CST
:
...
@@ -1699,9 +1917,12 @@ decode_addr_const (exp, value)
...
@@ -1699,9 +1917,12 @@ decode_addr_const (exp, value)
abort
();
abort
();
}
}
if
(
GET_CODE
(
x
)
!=
MEM
)
if
(
!
output_bytecode
)
abort
();
{
x
=
XEXP
(
x
,
0
);
if
(
GET_CODE
(
x
)
!=
MEM
)
abort
();
x
=
XEXP
(
x
,
0
);
}
value
->
base
=
x
;
value
->
base
=
x
;
value
->
offset
=
offset
;
value
->
offset
=
offset
;
...
@@ -2171,47 +2392,57 @@ output_constant_def (exp)
...
@@ -2171,47 +2392,57 @@ output_constant_def (exp)
to see if any of them describes EXP. If yes, the descriptor records
to see if any of them describes EXP. If yes, the descriptor records
the label number already assigned. */
the label number already assigned. */
hash
=
const_hash
(
exp
)
%
MAX_HASH_TABLE
;
if
(
!
output_bytecode
)
for
(
desc
=
const_hash_table
[
hash
];
desc
;
desc
=
desc
->
next
)
if
(
compare_constant
(
exp
,
desc
))
{
found
=
desc
->
label
;
break
;
}
if
(
found
==
0
)
{
{
/* No constant equal to EXP is known to have been output.
hash
=
const_hash
(
exp
)
%
MAX_HASH_TABLE
;
Make a constant descriptor to enter EXP in the hash table.
Assign the label number and record it in the descriptor for
for
(
desc
=
const_hash_table
[
hash
];
desc
;
desc
=
desc
->
next
)
future calls to this function to find. */
if
(
compare_constant
(
exp
,
desc
))
{
/* Create a string containing the label name, in LABEL. */
found
=
desc
->
label
;
ASM_GENERATE_INTERNAL_LABEL
(
label
,
"LC"
,
const_labelno
);
break
;
}
desc
=
record_constant
(
exp
);
desc
->
next
=
const_hash_table
[
hash
];
if
(
found
==
0
)
desc
->
label
{
=
(
char
*
)
obstack_copy0
(
&
permanent_obstack
,
label
,
strlen
(
label
));
/* No constant equal to EXP is known to have been output.
const_hash_table
[
hash
]
=
desc
;
Make a constant descriptor to enter EXP in the hash table.
Assign the label number and record it in the descriptor for
future calls to this function to find. */
/* Create a string containing the label name, in LABEL. */
ASM_GENERATE_INTERNAL_LABEL
(
label
,
"LC"
,
const_labelno
);
desc
=
record_constant
(
exp
);
desc
->
next
=
const_hash_table
[
hash
];
desc
->
label
=
(
char
*
)
obstack_copy0
(
&
permanent_obstack
,
label
,
strlen
(
label
));
const_hash_table
[
hash
]
=
desc
;
}
else
{
/* Create a string containing the label name, in LABEL. */
ASM_GENERATE_INTERNAL_LABEL
(
label
,
"LC"
,
const_labelno
);
}
}
}
/* We have a symbol name; construct the SYMBOL_REF and the MEM. */
/* We have a symbol name; construct the SYMBOL_REF and the MEM. */
push_obstacks_nochange
();
push_obstacks_nochange
();
if
(
TREE_PERMANENT
(
exp
))
if
(
TREE_PERMANENT
(
exp
))
end_temporary_allocation
();
end_temporary_allocation
();
def
=
gen_rtx
(
SYMBOL_REF
,
Pmode
,
desc
->
label
);
if
(
!
output_bytecode
)
{
TREE_CST_RTL
(
exp
)
def
=
gen_rtx
(
SYMBOL_REF
,
Pmode
,
desc
->
label
);
=
gen_rtx
(
MEM
,
TYPE_MODE
(
TREE_TYPE
(
exp
)),
def
);
RTX_UNCHANGING_P
(
TREE_CST_RTL
(
exp
))
=
1
;
TREE_CST_RTL
(
exp
)
if
(
TREE_CODE
(
TREE_TYPE
(
exp
))
==
RECORD_TYPE
=
gen_rtx
(
MEM
,
TYPE_MODE
(
TREE_TYPE
(
exp
)),
def
);
||
TREE_CODE
(
TREE_TYPE
(
exp
))
==
ARRAY_TYPE
)
RTX_UNCHANGING_P
(
TREE_CST_RTL
(
exp
))
=
1
;
MEM_IN_STRUCT_P
(
TREE_CST_RTL
(
exp
))
=
1
;
if
(
TREE_CODE
(
TREE_TYPE
(
exp
))
==
RECORD_TYPE
||
TREE_CODE
(
TREE_TYPE
(
exp
))
==
ARRAY_TYPE
)
MEM_IN_STRUCT_P
(
TREE_CST_RTL
(
exp
))
=
1
;
}
pop_obstacks
();
pop_obstacks
();
/* Optionally set flags or add text to the name to record information
/* Optionally set flags or add text to the name to record information
...
@@ -2283,7 +2514,12 @@ output_constant_def_contents (exp, reloc, labelno)
...
@@ -2283,7 +2514,12 @@ output_constant_def_contents (exp, reloc, labelno)
#endif
#endif
if
(
align
>
BITS_PER_UNIT
)
if
(
align
>
BITS_PER_UNIT
)
ASM_OUTPUT_ALIGN
(
asm_out_file
,
floor_log2
(
align
/
BITS_PER_UNIT
));
{
if
(
!
output_bytecode
)
ASM_OUTPUT_ALIGN
(
asm_out_file
,
floor_log2
(
align
/
BITS_PER_UNIT
));
else
BC_OUTPUT_ALIGN
(
asm_out_file
,
floor_log2
(
align
/
BITS_PER_UNIT
));
}
/* Output the label itself. */
/* Output the label itself. */
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
"LC"
,
labelno
);
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
"LC"
,
labelno
);
...
@@ -2891,6 +3127,22 @@ output_addressed_constants (exp)
...
@@ -2891,6 +3127,22 @@ output_addressed_constants (exp)
}
}
return
reloc
;
return
reloc
;
}
}
/* Output assembler for byte constant */
void
output_byte_asm
(
byte
)
int
byte
;
{
if
(
output_bytecode
)
bc_emit_const
((
char
*
)
&
byte
,
sizeof
(
char
));
#ifdef ASM_OUTPUT_BYTE
else
{
ASM_OUTPUT_BYTE
(
asm_out_file
,
byte
);
}
#endif
}
/* Output assembler code for constant EXP to FILE, with no label.
/* Output assembler code for constant EXP to FILE, with no label.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
...
@@ -2925,7 +3177,10 @@ output_constant (exp, size)
...
@@ -2925,7 +3177,10 @@ output_constant (exp, size)
This means to fill the space with zeros. */
This means to fill the space with zeros. */
if
(
TREE_CODE
(
exp
)
==
CONSTRUCTOR
&&
CONSTRUCTOR_ELTS
(
exp
)
==
0
)
if
(
TREE_CODE
(
exp
)
==
CONSTRUCTOR
&&
CONSTRUCTOR_ELTS
(
exp
)
==
0
)
{
{
assemble_zeros
(
size
);
if
(
output_bytecode
)
bc_emit_const_skip
(
size
);
else
assemble_zeros
(
size
);
return
;
return
;
}
}
...
@@ -3005,6 +3260,101 @@ output_constant (exp, size)
...
@@ -3005,6 +3260,101 @@ output_constant (exp, size)
if
(
size
>
0
)
if
(
size
>
0
)
assemble_zeros
(
size
);
assemble_zeros
(
size
);
}
}
/* Bytecode specific code to output assembler for integer. */
void
bc_assemble_integer
(
exp
,
size
)
tree
exp
;
int
size
;
{
tree
const_part
;
tree
addr_part
;
tree
tmp
;
/* FIXME: is this fold() business going to be as good as the
expand_expr() using EXPAND_SUM above in the RTL case? I
hate RMS.
FIXME: Copied as is from BC-GCC1; may need work. Don't hate. -bson */
exp
=
fold
(
exp
);
while
(
TREE_CODE
(
exp
)
==
NOP_EXPR
||
TREE_CODE
(
exp
)
==
CONVERT_EXPR
)
exp
=
TREE_OPERAND
(
exp
,
0
);
if
(
TREE_CODE
(
exp
)
==
INTEGER_CST
)
{
const_part
=
exp
;
addr_part
=
0
;
}
else
if
(
TREE_CODE
(
exp
)
==
PLUS_EXPR
)
{
const_part
=
TREE_OPERAND
(
exp
,
0
);
while
(
TREE_CODE
(
const_part
)
==
NOP_EXPR
||
TREE_CODE
(
const_part
)
==
CONVERT_EXPR
)
const_part
=
TREE_OPERAND
(
const_part
,
0
);
addr_part
=
TREE_OPERAND
(
exp
,
1
);
while
(
TREE_CODE
(
addr_part
)
==
NOP_EXPR
||
TREE_CODE
(
addr_part
)
==
CONVERT_EXPR
)
addr_part
=
TREE_OPERAND
(
addr_part
,
0
);
if
(
TREE_CODE
(
const_part
)
!=
INTEGER_CST
)
tmp
=
const_part
,
const_part
=
addr_part
,
addr_part
=
tmp
;
if
(
TREE_CODE
(
const_part
)
!=
INTEGER_CST
||
TREE_CODE
(
addr_part
)
!=
ADDR_EXPR
)
abort
();
/* FIXME: we really haven't considered
all the possible cases here. */
}
else
if
(
TREE_CODE
(
exp
)
==
ADDR_EXPR
)
{
const_part
=
integer_zero_node
;
addr_part
=
exp
;
}
else
abort
();
/* FIXME: ditto previous. */
if
(
addr_part
==
0
)
{
if
(
size
==
1
)
{
char
c
=
TREE_INT_CST_LOW
(
const_part
);
bc_emit
(
&
c
,
1
);
size
-=
1
;
}
else
if
(
size
==
2
)
{
short
s
=
TREE_INT_CST_LOW
(
const_part
);
bc_emit
((
char
*
)
&
s
,
2
);
size
-=
2
;
}
else
if
(
size
==
4
)
{
int
i
=
TREE_INT_CST_LOW
(
const_part
);
bc_emit
((
char
*
)
&
i
,
4
);
size
-=
4
;
}
else
if
(
size
==
8
)
{
#if WORDS_BIG_ENDIAN
int
i
=
TREE_INT_CST_HIGH
(
const_part
);
bc_emit
((
char
*
)
&
i
,
4
);
i
=
TREE_INT_CST_LOW
(
const_part
);
bc_emit
((
char
*
)
&
i
,
4
);
#else
int
i
=
TREE_INT_CST_LOW
(
const_part
);
bc_emit
((
char
*
)
&
i
,
4
);
i
=
TREE_INT_CST_HIGH
(
const_part
);
bc_emit
((
char
*
)
&
i
,
4
);
#endif
size
-=
8
;
}
}
else
if
(
size
==
4
&&
TREE_CODE
(
TREE_OPERAND
(
addr_part
,
0
))
==
VAR_DECL
)
bc_emit_labelref
(
DECL_ASSEMBLER_NAME
(
TREE_OPERAND
(
addr_part
,
0
)),
TREE_INT_CST_LOW
(
const_part
));
else
abort
();
/* FIXME: there may be more cases. */
}
/* Subroutine of output_constant, used for CONSTRUCTORs
/* Subroutine of output_constant, used for CONSTRUCTORs
(aggregate constants).
(aggregate constants).
...
@@ -3083,7 +3433,10 @@ output_constructor (exp, size)
...
@@ -3083,7 +3433,10 @@ output_constructor (exp, size)
if each element has the proper size. */
if each element has the proper size. */
if
((
field
!=
0
||
index
!=
0
)
&&
bitpos
!=
total_bytes
)
if
((
field
!=
0
||
index
!=
0
)
&&
bitpos
!=
total_bytes
)
{
{
assemble_zeros
(
bitpos
-
total_bytes
);
if
(
!
output_bytecode
)
assemble_zeros
(
bitpos
-
total_bytes
);
else
bc_emit_const_skip
(
bitpos
-
total_bytes
);
total_bytes
=
bitpos
;
total_bytes
=
bitpos
;
}
}
...
@@ -3254,3 +3607,42 @@ output_constructor (exp, size)
...
@@ -3254,3 +3607,42 @@ output_constructor (exp, size)
if
(
total_bytes
<
size
)
if
(
total_bytes
<
size
)
assemble_zeros
(
size
-
total_bytes
);
assemble_zeros
(
size
-
total_bytes
);
}
}
/* Output asm to handle ``#pragma weak'' */
void
handle_pragma_weak
(
what
,
asm_out_file
,
name
,
value
)
enum
pragma_state
what
;
FILE
*
asm_out_file
;
char
*
name
,
*
value
;
{
if
(
what
==
ps_name
||
what
==
ps_value
)
{
fprintf
(
asm_out_file
,
"
\t
%s
\t
"
,
WEAK_ASM_OP
);
if
(
output_bytecode
)
BC_OUTPUT_LABELREF
(
asm_out_file
,
name
);
else
ASM_OUTPUT_LABELREF
(
asm_out_file
,
name
);
fputc
(
'\n'
,
asm_out_file
);
if
(
what
==
ps_value
)
{
fprintf
(
asm_out_file
,
"
\t
%s
\t
"
,
SET_ASM_OP
);
if
(
output_bytecode
)
BC_OUTPUT_LABELREF
(
asm_out_file
,
name
);
else
ASM_OUTPUT_LABELREF
(
asm_out_file
,
name
);
fputc
(
','
,
asm_out_file
);
if
(
output_bytecode
)
BC_OUTPUT_LABELREF
(
asm_out_file
,
value
);
else
ASM_OUTPUT_LABELREF
(
asm_out_file
,
value
);
fputc
(
'\n'
,
asm_out_file
);
}
}
else
if
(
!
(
what
==
ps_done
||
what
==
ps_start
))
warning
(
"malformed `#pragma weak'"
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment