From-SVN: r5379
This commit is contained in:
Jan Brittenson 1993-09-21 14:25:24 -07:00
parent 86d7f2db05
commit ca695ac93d
10 changed files with 2943 additions and 205 deletions

View File

@ -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 \
$(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.
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 \
@ -461,6 +464,7 @@ CONFIG_H =
RTL_H = rtl.h rtl.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
BYTECODE_H = bytecode.h bc-emit.h bc-optab.h
# Avoid a lot of time thinking about remaking Makefile.in and *.def.
.SUFFIXES: .in .def
@ -484,7 +488,7 @@ for-bootstrap: start.encap $(LIBGCC)
rest.encap: $(LIBGCC) stmp-headers $(STMP_FIXPROTO) $(EXTRA_PARTS)
# This is what is made with the host's compiler
# 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.
C c: cc1
@ -545,14 +549,14 @@ g++-cross: $(srcdir)/g++.c
$(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) -o g++-cross \
-DGCC_NAME=\"$(target)-gcc\" $(srcdir)/g++.c version.o $(LIBS)
cc1:$(P) $(C_OBJS) $(OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cc1 $(C_OBJS) $(OBJS) $(LIBS)
cc1:$(P) $(C_OBJS) $(OBJS) $(BC_OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cc1 $(C_OBJS) $(OBJS) $(BC_OBJS) $(LIBS)
cc1plus:$(P) $(CPLUS_OBJS) $(OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cc1plus $(CPLUS_OBJS) $(OBJS) $(LIBS)
cc1plus:$(P) $(CPLUS_OBJS) $(OBJS) $(BC_OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cc1plus $(CPLUS_OBJS) $(BC_OBJS) $(OBJS) $(LIBS)
cc1obj:$(P) $(OBJC_OBJS) $(OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cc1obj $(OBJC_OBJS) $(OBJS) $(LIBS)
cc1obj:$(P) $(OBJC_OBJS) $(OBJS) $(BC_OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cc1obj $(OBJC_OBJS) $(OBJS) $(BC_OBJS) $(LIBS)
# Copy float.h from its source.
gfloat.h: $(FLOAT_H)
@ -1247,6 +1251,63 @@ $(HOST_PREFIX_1)malloc.o: malloc.c
$(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.
# Making the preprocessor
@ -1507,7 +1568,7 @@ $(srcdir)/INSTALL: install1.texi install.texi
# `realclean' also deletes everything that could be regenerated automatically.
mostlyclean:
mostlyclean: bytecode.mostlyclean
-rm -f $(STAGESTUFF)
# Clean the objc subdir if we created one.
if [ -d objc ]; then \
@ -1545,7 +1606,7 @@ mostlyclean:
# Delete all files made by compilation
# that don't exist in the distribution.
clean: mostlyclean
clean: mostlyclean bytecode.clean
# It may not be quite desirable to delete unprotoize.c here,
# but the spec for `make clean' requires it.
# Using unprotoize.c is not quite right in the first place,
@ -1557,7 +1618,7 @@ clean: mostlyclean
# Delete all files that users would normally create
# 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 Makefile *.oaux
-rm -fr stage1 stage2 stage3 stage4
@ -1581,7 +1642,7 @@ extraclean: distclean
# Get rid of every file that's generated from some other file.
# 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 cp-parse.c cp-parse.h cp-parse.output
-rm -f objc-parse.c objc-parse.output

View File

@ -20,6 +20,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "config.h"
#include "tree.h"
#include "function.h"
#ifdef HANDLE_SYSV_PRAGMA
@ -45,20 +46,7 @@ handle_pragma_token (string, token)
char *string;
tree token;
{
static enum pragma_state
{
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 enum pragma_state state = ps_start, type;
static char *name;
static char *value;
static int align;
@ -76,24 +64,8 @@ handle_pragma_token (string, token)
{
#ifdef HANDLE_PRAGMA_WEAK
if (HANDLE_PRAGMA_WEAK)
{
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'");
}
handle_pragma_weak (state, asm_out_file, name, value);
#endif /* HANDLE_PRAMA_WEAK */
}

View File

@ -42,8 +42,29 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "regs.h"
#include "insn-config.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>
/* 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.
After rtl generation, it is 1 plus the largest register number used. */
@ -203,6 +224,11 @@ extern int emit_lineno;
rtx change_address ();
void init_emit ();
extern struct obstack *rtl_obstack;
extern int stack_depth;
extern int max_stack_depth;
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
**
** This routine generates an RTX of the size specified by
@ -1216,8 +1242,12 @@ change_address (memref, mode, addr)
rtx
gen_label_rtx ()
{
register rtx label = gen_rtx (CODE_LABEL, VOIDmode, 0, 0, 0,
label_num++, NULL_PTR);
register rtx label;
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;
return label;
}
@ -2559,6 +2589,13 @@ emit_line_note (file, line)
char *file;
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_lineno = line;

1308
gcc/expr.c

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "integrate.h"
#include "real.h"
#include "function.h"
#include "bytecode.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
@ -2850,9 +2851,16 @@ void
output_inline_function (fndecl)
tree fndecl;
{
rtx head = DECL_SAVED_INSNS (fndecl);
rtx head;
rtx last;
if (output_bytecode)
{
warning ("`inline' ignored for bytecode output");
return;
}
head = DECL_SAVED_INSNS (fndecl);
current_function_decl = fndecl;
/* This call is only used to initialize global variables. */

View File

@ -32,6 +32,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "recog.h"
#include "reload.h"
#include "real.h"
#include "bytecode.h"
#ifndef REGISTER_MOVE_COST
#define REGISTER_MOVE_COST(x, y) 2
@ -413,6 +414,13 @@ fix_register (name, fixed, call_used)
{
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
the register info. */

View File

@ -139,6 +139,22 @@ typedef struct rtx_def
The number of operands and their types are controlled
by the `code' field, according to rtl.def. */
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;
/* Add prototype support. */
@ -640,6 +656,7 @@ extern rtx gen_rtx PROTO((enum rtx_code, enum machine_mode, ...));
extern rtvec gen_rtvec PROTO((int, ...));
#else
extern rtx bc_gen_rtx ();
extern rtx gen_rtx ();
extern rtvec gen_rtvec ();
#endif

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h"
#endif
#include "bytecode.h"
#include "bc-emit.h"
#ifdef VMS
/* The extra parameters substantially improve the I/O performance. */
@ -211,6 +214,9 @@ int errorcount = 0;
int warningcount = 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. */
char *(*decl_printable_name) ();
@ -515,6 +521,7 @@ struct { char *string; int *variable; int on_value;} f_options[] =
{"inhibit-size-directive", &flag_inhibit_size_directive, 1},
{"verbose-asm", &flag_verbose_asm, 1},
{"gnu-linker", &flag_gnu_linker, 1}
{"bytecode", &output_bytecode, 1}
};
/* Table of language-specific options. */
@ -885,11 +892,14 @@ void
fatal_insn_not_found (insn)
rtx insn;
{
if (INSN_CODE (insn) < 0)
error ("internal error--unrecognizable insn:", 0);
else
error ("internal error--insn does not satisfy its constraints:", 0);
debug_rtx (insn);
if (!output_bytecode)
{
if (INSN_CODE (insn) < 0)
error ("internal error--unrecognizable insn:", 0);
else
error ("internal error--insn does not satisfy its constraints:", 0);
debug_rtx (insn);
}
if (asm_out_file)
fflush (asm_out_file);
if (aux_info_file)
@ -1585,6 +1595,8 @@ compile_file (name)
init_obstacks ();
init_tree_codes ();
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_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE);
@ -1813,34 +1825,51 @@ compile_file (name)
input_file_stack->next = 0;
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
fprintf (asm_out_file, "gcc2_compiled.:\n");
fprintf (asm_out_file, "gcc2_compiled.:\n");
#else
ASM_IDENTIFY_GCC (asm_out_file);
ASM_IDENTIFY_GCC (asm_out_file);
#endif
}
/* Output something to identify which front-end produced this file. */
#ifdef ASM_IDENTIFY_LANGUAGE
ASM_IDENTIFY_LANGUAGE (asm_out_file);
#endif
/* ??? Note: There used to be a conditional here
to call assemble_zeros without fail if DBX_DEBUGGING_INFO is defined.
This was to guarantee separation between gcc_compiled. and
the first function, for the sake of dbx on Suns.
However, having the extra zero here confused the Emacs
code for unexec, and might confuse other programs too.
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 (output_bytecode)
{
if (profile_flag || profile_block_flag)
error ("profiling not supported in bytecode compilation");
}
else
{
/* ??? Note: There used to be a conditional here
to call assemble_zeros without fail if DBX_DEBUGGING_INFO is defined.
This was to guarantee separation between gcc_compiled. and
the first function, for the sake of dbx on Suns.
However, having the extra zero here confused the Emacs
code for unexec, and might confuse other programs too.
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
and output the predefined types. */
@ -1861,7 +1890,8 @@ compile_file (name)
/* Initialize yet another pass. */
init_final (main_input_filename);
if (!output_bytecode)
init_final (main_input_filename);
start_time = get_run_time ();
@ -2031,11 +2061,14 @@ compile_file (name)
/* 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
ASM_FILE_END (asm_out_file);
ASM_FILE_END (asm_out_file);
#endif
}
after_finish_compilation:
@ -2113,24 +2146,28 @@ compile_file (name)
{
fprintf (stderr,"\n");
print_time ("parse", parse_time);
print_time ("integration", integration_time);
print_time ("jump", jump_time);
print_time ("cse", cse_time);
print_time ("loop", loop_time);
print_time ("cse2", cse2_time);
print_time ("flow", flow_time);
print_time ("combine", combine_time);
print_time ("sched", sched_time);
print_time ("local-alloc", local_alloc_time);
print_time ("global-alloc", global_alloc_time);
print_time ("sched2", sched2_time);
print_time ("dbranch", dbr_sched_time);
print_time ("shorten-branch", shorten_branch_time);
print_time ("stack-reg", stack_reg_time);
print_time ("final", final_time);
print_time ("varconst", varconst_time);
print_time ("symout", symout_time);
print_time ("dump", dump_time);
if (!output_bytecode)
{
print_time ("integration", integration_time);
print_time ("jump", jump_time);
print_time ("cse", cse_time);
print_time ("loop", loop_time);
print_time ("cse2", cse2_time);
print_time ("flow", flow_time);
print_time ("combine", combine_time);
print_time ("sched", sched_time);
print_time ("local-alloc", local_alloc_time);
print_time ("global-alloc", global_alloc_time);
print_time ("sched2", sched2_time);
print_time ("dbranch", dbr_sched_time);
print_time ("shorten-branch", shorten_branch_time);
print_time ("stack-reg", stack_reg_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)
tree saved_arguments = 0;
int failure = 0;
if (output_bytecode)
return;
/* If we are reconsidering an inline function
at the end of compilation, skip the stuff for making it inline. */
@ -3166,7 +3206,12 @@ main (argc, argv, envp)
error ("Invalid option `%s'", argv[i]);
}
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"))
{
#if !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER)
@ -3325,6 +3370,18 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
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)
{
/* Inlining does not work if not optimizing,
@ -3398,10 +3455,14 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
}
/* 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);
if (output_bytecode)
bc_write_file (stdout);
#ifndef OS2
#ifndef VMS
if (flag_print_mem)

View File

@ -38,6 +38,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "regs.h"
#include "defaults.h"
#include "real.h"
#include "bytecode.h"
#include "obstack.h"
@ -96,9 +97,11 @@ void assemble_name ();
int output_addressed_constants ();
void output_constant ();
void output_constructor ();
void output_byte_asm ();
void text_section ();
void readonly_data_section ();
void data_section ();
static void bc_assemble_integer ();
#ifdef EXTRA_SECTIONS
static enum in_section {no_section, in_text, in_data, EXTRA_SECTIONS} in_section
@ -120,7 +123,11 @@ text_section ()
{
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;
}
}
@ -132,16 +139,21 @@ data_section ()
{
if (in_section != in_data)
{
if (flag_shared_data)
{
#ifdef SHARED_SECTION_ASM_OP
fprintf (asm_out_file, "%s\n", SHARED_SECTION_ASM_OP);
#else
fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
#endif
}
if (output_bytecode)
bc_data ();
else
fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
{
if (flag_shared_data)
{
#ifdef SHARED_SECTION_ASM_OP
fprintf (asm_out_file, "%s\n", SHARED_SECTION_ASM_OP);
#else
fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
#endif
}
else
fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
}
in_section = in_data;
}
@ -178,6 +190,16 @@ make_function_rtl (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. */
if (decl_function_context (decl) != 0
&& DECL_INITIAL (decl) != 0
@ -211,6 +233,48 @@ make_function_rtl (decl)
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. */
static char *
@ -301,7 +365,15 @@ make_decl_rtl (decl, asmspec, top_level)
int top_level;
{
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)
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
@ -465,6 +537,12 @@ void
assemble_asm (string)
tree string;
{
if (output_bytecode)
{
error ("asm statements not allowed in interpreter");
return;
}
app_enable ();
if (TREE_CODE (string) == ADDR_EXPR)
@ -576,7 +654,12 @@ assemble_start_function (decl, fnname)
/* Tell assembler to move to target machine's alignment for functions. */
align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
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
ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname);
@ -600,7 +683,10 @@ assemble_start_function (decl, fnname)
{
if (!first_global_object_name)
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 */
@ -608,7 +694,10 @@ assemble_start_function (decl, fnname)
ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
#else
/* 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 */
}
@ -631,6 +720,12 @@ void
assemble_zeros (size)
int size;
{
if (output_bytecode)
{
bc_emit_const_skip (size);
return;
}
#ifdef ASM_NO_SKIP_IN_TEXT
/* The `space' pseudo in the text section outputs nop insns rather than 0s,
so we must output 0s explicitly in the text section. */
@ -664,7 +759,12 @@ assemble_zeros (size)
else
#endif
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. */
@ -688,6 +788,12 @@ assemble_string (p, size)
int pos = 0;
int maximum = 2000;
if (output_bytecode)
{
bc_emit (p, size);
return;
}
/* If the string is very long, split it up. */
while (pos < size)
@ -696,7 +802,10 @@ assemble_string (p, size)
if (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;
p += thissize;
@ -725,6 +834,9 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
int reloc = 0;
enum in_section saved_in_section;
if (output_bytecode)
return;
if (GET_CODE (DECL_RTL (decl)) == REG)
{
/* 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)
return;
TREE_ASM_WRITTEN (decl) = 1;
if (!output_bytecode)
{
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
/* File-scope global variables are output here. */
if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
&& top_level)
dbxout_symbol (decl, 0);
/* File-scope global variables are output here. */
if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
&& top_level)
dbxout_symbol (decl, 0);
#endif
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG && top_level
/* Leave initialized global vars for end of compilation;
see comment in compile_file. */
&& (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0))
sdbout_symbol (decl, 0);
if (write_symbols == SDB_DEBUG && top_level
/* Leave initialized global vars for end of compilation;
see comment in compile_file. */
&& (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0))
sdbout_symbol (decl, 0);
#endif
}
/* Don't output any DWARF debugging information for variables here.
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)
ASM_OUTPUT_SHARED_COMMON (asm_out_file, name, size, rounded);
else
#endif
if (output_bytecode)
BC_OUTPUT_COMMON (asm_out_file, name, size, rounded);
else
{
#ifdef ASM_OUTPUT_ALIGNED_COMMON
ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
DECL_ALIGN (decl));
ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
DECL_ALIGN (decl));
#else
ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);
ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);
#endif
}
}
else
{
@ -894,12 +1014,17 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded);
else
#endif
if (output_bytecode)
BC_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
else
{
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
DECL_ALIGN (decl));
ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
DECL_ALIGN (decl));
#else
ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
#endif
}
}
goto finish;
}
@ -1017,14 +1142,22 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
DECL_ALIGN (decl) = align;
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. */
#ifdef ASM_DECLARE_OBJECT_NAME
ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);
#else
/* 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 */
if (!dont_output_data)
@ -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.
(Most assemblers don't need this, so we normally output nothing.)
Do nothing if DECL is not external. */
@ -1118,6 +1300,9 @@ void
assemble_external (decl)
tree decl;
{
if (output_bytecode)
return;
#ifdef ASM_OUTPUT_EXTERNAL
if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd'
&& DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
@ -1142,11 +1327,14 @@ assemble_external_libcall (fun)
rtx fun;
{
#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL
/* Declare library function name external when first used, if nec. */
if (! SYMBOL_REF_USED (fun))
if (!output_bytecode)
{
SYMBOL_REF_USED (fun) = 1;
ASM_OUTPUT_EXTERNAL_LIBCALL (asm_out_file, fun);
/* Declare library function name external when first used, if nec. */
if (! SYMBOL_REF_USED (fun))
{
SYMBOL_REF_USED (fun) = 1;
ASM_OUTPUT_EXTERNAL_LIBCALL (asm_out_file, fun);
}
}
#endif
}
@ -1166,7 +1354,10 @@ void
assemble_label (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.
@ -1181,9 +1372,19 @@ assemble_name (file, name)
char *name;
{
if (name[0] == '*')
fputs (&name[1], file);
{
if (output_bytecode)
bc_emit_labelref (name);
else
fputs (&name[1], file);
}
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
@ -1214,12 +1415,21 @@ assemble_static_space (size)
strlen (name) + 2);
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
ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT);
ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT);
#else
ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
#endif
}
return x;
}
@ -1234,6 +1444,10 @@ assemble_trampoline_template ()
char *name;
int align;
/* Shouldn't get here */
if (output_bytecode)
abort ();
/* By default, put trampoline templates in read-only data section. */
#ifdef TRAMPOLINE_SECTION
@ -1683,9 +1897,13 @@ decode_addr_const (exp, value)
break;
case LABEL_DECL:
x = gen_rtx (MEM, FUNCTION_MODE,
gen_rtx (LABEL_REF, VOIDmode,
label_rtx (TREE_OPERAND (exp, 0))));
if (output_bytecode)
/* FIXME: this may not be correct, check it */
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;
case REAL_CST:
@ -1699,9 +1917,12 @@ decode_addr_const (exp, value)
abort ();
}
if (GET_CODE (x) != MEM)
abort ();
x = XEXP (x, 0);
if (!output_bytecode)
{
if (GET_CODE (x) != MEM)
abort ();
x = XEXP (x, 0);
}
value->base = x;
value->offset = offset;
@ -2171,47 +2392,57 @@ output_constant_def (exp)
to see if any of them describes EXP. If yes, the descriptor records
the label number already assigned. */
hash = const_hash (exp) % MAX_HASH_TABLE;
for (desc = const_hash_table[hash]; desc; desc = desc->next)
if (compare_constant (exp, desc))
{
found = desc->label;
break;
}
if (found == 0)
if (!output_bytecode)
{
/* No constant equal to EXP is known to have been output.
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;
hash = const_hash (exp) % MAX_HASH_TABLE;
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.
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. */
push_obstacks_nochange ();
if (TREE_PERMANENT (exp))
end_temporary_allocation ();
def = gen_rtx (SYMBOL_REF, Pmode, desc->label);
TREE_CST_RTL (exp)
= gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), def);
RTX_UNCHANGING_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;
if (!output_bytecode)
{
def = gen_rtx (SYMBOL_REF, Pmode, desc->label);
TREE_CST_RTL (exp)
= gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), def);
RTX_UNCHANGING_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 ();
/* Optionally set flags or add text to the name to record information
@ -2283,7 +2514,12 @@ output_constant_def_contents (exp, reloc, labelno)
#endif
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. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", labelno);
@ -2891,6 +3127,22 @@ output_addressed_constants (exp)
}
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.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
@ -2925,7 +3177,10 @@ output_constant (exp, size)
This means to fill the space with zeros. */
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;
}
@ -3005,6 +3260,101 @@ output_constant (exp, size)
if (size > 0)
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
(aggregate constants).
@ -3083,7 +3433,10 @@ output_constructor (exp, size)
if each element has the proper size. */
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;
}
@ -3254,3 +3607,42 @@ output_constructor (exp, size)
if (total_bytes < size)
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'");
}