1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-04 05:50:26 +02:00
guile/lib/jit_note.c
pcpa 33ee2337c7 Implement the new jit_set_data interface.
* include/lightning.h, include/lightning/jit_private.h,
	lib/lightning.c: Implement the new jit_set_data() interface,
	and the new jit_get_data() helper. Like jit_set_code(),
	jit_realize() should be called before jit_set_data().
	The most common usage should be jit_set_data(JIT_DISABLE_DATA
	| JIT_DISABLE_NOTE), to force synthesize any float/double
	constant in the stack and not generate any debug information.

	* lib/jit_note.c: Minor change to debug note generation as
	now it uses an alternate temporary data buffer during constants
	and debug generation to accommodate the possibility of the user
	setting an alternate data buffer.

	* lib/jit_hppa-fpu.c, lib/jit_s390x.c, lib/jit_s390x-cpu.c,
	lib/jit_s390x-fpu.c, lib/jit_sparc.c, lib/jit_sparc-fpu.c,
	lib/jit_x86-sse.c, lib/jit_x86-x87.c: Implement jit_set_data.

	* lib/jit_hppa-sz.c, lib/jit_sparc-sz.c, lib/jit_x86-sz.c,
	lib/jit_s390x-sz.c: Update for several instructions that now
	have a different maximum length due to jit_set_data.

	* lib/jit_mips-fpu.c: Implement jit_set_data, but missing
	validation on n32 and n64 abis (and/or big endian).

	* lib/jit_mips-sz.c: Update for changes in o32.

	* lib/jit_ppc-fpu.c: Implement jit_set_data, but missing
	validation on Darwin PPC.

	* lib/jit_ppc-sz.c: Update for changes in powerpc 32 and
	64 bit.

	* lib/jit_ia64-fpu.c: Implement untested jit_set_data.

	* TODO: Add note to list ports that were not tested for the
	new jit_set_data() feature, due to no longer having access
	to them.

	* check/nodata.c: New file implementing a simple test exercising
	several different conditions created by jit_set_data().

	* check/check.nodata.sh: New file implementing a wrapper
	over the existing *.tst files, that runs all tests without
	using a data buffer for constants; only meaningful (and
	enabled) on architectures that used to store float/double
	constants on a read only data buffer.

	* configure.ac, check/Makefile.am: Update for the new test
	cases.

	* check/lightning.c: Implement the new "-d" option that
	sets an internal flag to call jit_set_data() disable
	constants and debug, that is, using only a pure code
	buffer.
2014-03-12 14:50:31 -03:00

413 lines
11 KiB
C

/*
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* This file is part of GNU lightning.
*
* GNU lightning is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU lightning is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* Authors:
* Paulo Cesar Pereira de Andrade
*/
#include <lightning.h>
#include <lightning/jit_private.h>
/*
* Prototypes
*/
#define new_note(u, v) _new_note(_jit, u, v)
static jit_note_t *_new_note(jit_state_t *, jit_uint8_t*, char*);
static void new_line(jit_int32_t,jit_note_t*,char*,jit_int32_t,jit_int32_t);
#define note_search_index(u) _note_search_index(_jit, u)
static jit_int32_t _note_search_index(jit_state_t*, jit_uint8_t*);
static jit_int32_t line_insert_index(jit_note_t*,jit_int32_t);
static jit_int32_t line_search_index(jit_note_t*,jit_int32_t);
static jit_int32_t offset_insert_index(jit_line_t*,jit_int32_t);
static jit_int32_t offset_search_index(jit_line_t*,jit_int32_t);
/*
* Implementation
*/
void
jit_init_note(void)
{
}
void
jit_finish_note(void)
{
}
jit_node_t *
_jit_name(jit_state_t *_jit, char *name)
{
jit_node_t *node;
node = jit_new_node(jit_code_name);
if (name)
node->v.n = jit_data(name, strlen(name) + 1, 1);
else
node->v.p = NULL;
if (_jitc->note.head == NULL)
_jitc->note.head = _jitc->note.tail = node;
else {
_jitc->note.tail->link = node;
_jitc->note.tail = node;
}
++_jit->note.length;
_jitc->note.size += sizeof(jit_note_t);
/* remember previous note is invalid due to name change */
_jitc->note.note = NULL;
return (_jitc->note.name = node);
}
jit_node_t *
_jit_note(jit_state_t *_jit, char *name, int line)
{
jit_node_t *node;
node = jit_new_node(jit_code_note);
if (name)
node->v.n = jit_data(name, strlen(name) + 1, 1);
else
node->v.p = NULL;
node->w.w = line;
if (_jitc->note.head == NULL)
_jitc->note.head = _jitc->note.tail = node;
else {
_jitc->note.tail->link = node;
_jitc->note.tail = node;
}
if (_jitc->note.note == NULL ||
(name == NULL && _jitc->note.note != NULL) ||
(name != NULL && _jitc->note.note == NULL) ||
(name != NULL && _jitc->note.note != NULL &&
strcmp(name, (char *)_jitc->data.ptr + _jitc->note.note->v.n->u.w)))
_jitc->note.size += sizeof(jit_line_t);
_jitc->note.size += sizeof(jit_int32_t) * 2;
return (_jitc->note.note = node);
}
void
_jit_annotate(jit_state_t *_jit)
{
jit_node_t *node;
jit_note_t *note;
jit_line_t *line;
jit_word_t length;
jit_word_t note_offset;
jit_word_t line_offset;
/* initialize pointers in mmaped data area */
_jit->note.ptr = (jit_note_t *)_jitc->note.base;
_jit->note.length = 0;
note = NULL;
for (node = _jitc->note.head; node; node = node->link) {
if (node->code == jit_code_name)
note = new_note(node->u.p, node->v.p ? node->v.n->u.p : NULL);
else if (node->v.p) {
if (note == NULL)
note = new_note(node->u.p, NULL);
jit_set_note(note, node->v.n->u.p, node->w.w,
(jit_uint8_t *)node->u.p - note->code);
}
}
/* last note */
if (note)
note->size = _jit->pc.uc - note->code;
/* annotations may be very complex with conditions to extend
* or ignore redudant notes, as well as add entries to earlier
* notes, so, relocate the information to the data buffer,
* with likely over allocated reserved space */
/* relocate jit_line_t objects */
for (note_offset = 0; note_offset < _jit->note.length; note_offset++) {
note = _jit->note.ptr + note_offset;
length = sizeof(jit_line_t) * note->length;
assert(_jitc->note.base + length < _jit->data.ptr + _jit->data.length);
memcpy(_jitc->note.base, note->lines, length);
jit_free((jit_pointer_t *)&note->lines);
note->lines = (jit_line_t *)_jitc->note.base;
_jitc->note.base += length;
}
/* relocate offset and line number information */
for (note_offset = 0; note_offset < _jit->note.length; note_offset++) {
note = _jit->note.ptr + note_offset;
for (line_offset = 0; line_offset < note->length; line_offset++) {
line = note->lines + line_offset;
length = sizeof(jit_int32_t) * line->length;
assert(_jitc->note.base + length <
_jit->data.ptr + _jit->data.length);
memcpy(_jitc->note.base, line->linenos, length);
jit_free((jit_pointer_t *)&line->linenos);
line->linenos = (jit_int32_t *)_jitc->note.base;
_jitc->note.base += length;
assert(_jitc->note.base + length <
_jit->data.ptr + _jit->data.length);
memcpy(_jitc->note.base, line->offsets, length);
jit_free((jit_pointer_t *)&line->offsets);
line->offsets = (jit_int32_t *)_jitc->note.base;
_jitc->note.base += length;
}
}
}
void
_jit_set_note(jit_state_t *_jit, jit_note_t *note,
char *file, int lineno, jit_int32_t offset)
{
jit_line_t *line;
jit_int32_t index;
index = line_insert_index(note, offset);
if (note->length && index == note->length &&
note->lines[index - 1].file == file)
--index;
if (index >= note->length || note->lines[index].file != file)
new_line(index, note, file, lineno, offset);
else {
line = note->lines + index;
index = offset_insert_index(line, offset);
if (index < line->length && line->offsets[index] == offset) {
/* common case if no code was generated for several source lines */
if (line->linenos[index] < lineno)
line->linenos[index] = lineno;
}
else if (index < line->length && line->linenos[index] == lineno) {
/* common case of extending entry */
if (line->offsets[index] > offset)
line->offsets[index] = offset;
}
else {
/* line or offset changed */
if ((line->length & 15) == 0) {
jit_realloc((jit_pointer_t *)&line->linenos,
line->length * sizeof(jit_int32_t),
(line->length + 17) * sizeof(jit_int32_t));
jit_realloc((jit_pointer_t *)&line->offsets,
line->length * sizeof(jit_int32_t),
(line->length + 17) * sizeof(jit_int32_t));
}
if (index < note->length) {
memmove(line->linenos + index + 1, line->linenos + index,
sizeof(jit_int32_t) * (line->length - index));
memmove(line->offsets + index + 1, line->offsets + index,
sizeof(jit_int32_t) * (line->length - index));
}
line->linenos[index] = lineno;
line->offsets[index] = offset;
++line->length;
}
}
}
jit_bool_t
_jit_get_note(jit_state_t *_jit, jit_pointer_t code,
char **name, char **file, jit_int32_t *lineno)
{
jit_note_t *note;
jit_line_t *line;
jit_int32_t index;
jit_int32_t offset;
if ((index = note_search_index((jit_uint8_t *)code)) >= _jit->note.length)
return (0);
note = _jit->note.ptr + index;
if ((jit_uint8_t *)code < note->code ||
(jit_uint8_t *)code >= note->code + note->size)
return (0);
offset = (jit_uint8_t *)code - note->code;
if ((index = line_search_index(note, offset)) >= note->length)
return (0);
if (index == 0 && offset < note->lines[0].offsets[0])
return (0);
line = note->lines + index;
if ((index = offset_search_index(line, offset)) >= line->length)
return (0);
if (name)
*name = note->name;
if (file)
*file = line->file;
if (lineno)
*lineno = line->linenos[index];
return (1);
}
static jit_note_t *
_new_note(jit_state_t *_jit, jit_uint8_t *code, char *name)
{
jit_note_t *note;
jit_note_t *prev;
if (_jit->note.length) {
prev = _jit->note.ptr + _jit->note.length - 1;
assert(code >= prev->code);
prev->size = code - prev->code;
}
note = (jit_note_t *)_jitc->note.base;
_jitc->note.base += sizeof(jit_note_t);
++_jit->note.length;
note->code = code;
note->name = name;
return (note);
}
static void
new_line(jit_int32_t index, jit_note_t *note,
char *file, jit_int32_t lineno, jit_int32_t offset)
{
jit_line_t *line;
if (note->lines == NULL)
jit_alloc((jit_pointer_t *)&note->lines, 16 * sizeof(jit_line_t));
else if ((note->length & 15) == 15)
jit_realloc((jit_pointer_t *)&note->lines,
note->length * sizeof(jit_line_t),
(note->length + 17) * sizeof(jit_line_t));
if (index < note->length)
memmove(note->lines + index + 1, note->lines + index,
sizeof(jit_line_t) * (note->length - index));
line = note->lines + index;
++note->length;
line->file = file;
line->length = 1;
jit_alloc((jit_pointer_t *)&line->linenos, 16 * sizeof(jit_int32_t));
line->linenos[0] = lineno;
jit_alloc((jit_pointer_t *)&line->offsets, 16 * sizeof(jit_int32_t));
line->offsets[0] = offset;
}
static jit_int32_t
_note_search_index(jit_state_t *_jit, jit_uint8_t *code)
{
jit_int32_t bot;
jit_int32_t top;
jit_int32_t index;
jit_note_t *notes;
bot = 0;
top = _jit->note.length;
notes = _jit->note.ptr;
for (index = (bot + top) >> 1; bot < top; index = (bot + top) >> 1) {
if (code < notes[index].code)
top = index;
else if (code >= notes[index].code &&
code - notes[index].code < notes[index].size)
break;
else
bot = index + 1;
}
return (index);
}
static jit_int32_t
line_insert_index(jit_note_t *note, jit_int32_t offset)
{
jit_int32_t bot;
jit_int32_t top;
jit_int32_t index;
jit_line_t *lines;
bot = 0;
top = note->length;
if ((lines = note->lines) == NULL)
return (0);
for (index = (bot + top) >> 1; bot < top; index = (bot + top) >> 1) {
if (offset < *lines[index].offsets)
top = index;
else
bot = index + 1;
}
return ((bot + top) >> 1);
}
static jit_int32_t
line_search_index(jit_note_t *note, jit_int32_t offset)
{
jit_int32_t bot;
jit_int32_t top;
jit_int32_t index;
jit_line_t *lines;
bot = 0;
top = note->length;
if ((lines = note->lines) == NULL)
return (0);
for (index = (bot + top) >> 1; bot < top; index = (bot + top) >> 1) {
if (offset < *lines[index].offsets)
top = index;
/* offset should be already verified to be in range */
else if (index == note->length - 1 ||
(offset >= *lines[index].offsets &&
offset < *lines[index + 1].offsets))
break;
else
bot = index + 1;
}
return (index);
}
static jit_int32_t
offset_insert_index(jit_line_t *line, jit_int32_t offset)
{
jit_int32_t bot;
jit_int32_t top;
jit_int32_t index;
jit_int32_t *offsets;
bot = 0;
top = line->length;
offsets = line->offsets;
for (index = (bot + top) >> 1; bot < top; index = (bot + top) >> 1) {
if (offset < offsets[index])
top = index;
else
bot = index + 1;
}
return ((bot + top) >> 1);
}
static jit_int32_t
offset_search_index(jit_line_t *line, jit_int32_t offset)
{
jit_int32_t bot;
jit_int32_t top;
jit_int32_t index;
jit_int32_t *offsets;
bot = 0;
top = line->length;
offsets = line->offsets;
for (index = (bot + top) >> 1; bot < top; index = (bot + top) >> 1) {
if (offset < offsets[index])
top = index;
/* offset should be already verified to be in range */
else if (index == line->length - 1 ||
(offset >= offsets[index] && offset < offsets[index + 1]))
break;
else
bot = index + 1;
}
return (index);
}