145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * YASM assembler virtual line mapping handling (for parse stage)
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  Copyright (C) 2002-2007  Peter Johnson
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Redistribution and use in source and binary forms, with or without
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * modification, are permitted provided that the following conditions
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * are met:
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 1. Redistributions of source code must retain the above copyright
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    notice, this list of conditions and the following disclaimer.
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    notice, this list of conditions and the following disclaimer in the
1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    documentation and/or other materials provided with the distribution.
1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * POSSIBILITY OF SUCH DAMAGE.
2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "util.h"
2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "coretype.h"
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "hamt.h"
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "errwarn.h"
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "linemap.h"
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct line_mapping {
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* monotonically increasing virtual line */
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long line;
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* related info */
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* "original" source filename */
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@dependent@*/ const char *filename;
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* "original" source base line number */
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long file_line;
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* "original" source line number increment (for following lines) */
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long line_inc;
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} line_mapping;
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct line_source_info {
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* first bytecode on line; NULL if no bytecodes on line */
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@dependent@*/ yasm_bytecode *bc;
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* source code line */
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@owned@*/ char *source;
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} line_source_info;
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct yasm_linemap {
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Shared storage for filenames */
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ /*@null@*/ HAMT *filenames;
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Current virtual line number. */
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long current;
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Mappings from virtual to physical line numbers */
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct line_mapping *map_vector;
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long map_size;
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long map_allocated;
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Bytecode and source line information */
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ line_source_info *source_info;
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t source_info_size;
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfilename_delete_one(/*@only@*/ void *d)
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(d);
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_set(yasm_linemap *linemap, const char *filename,
82a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                 unsigned long virtual_line, unsigned long file_line,
83a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                 unsigned long line_inc)
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *copy;
86a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    unsigned long i;
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int replace = 0;
88a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    line_mapping *mapping = NULL;
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
90a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    if (virtual_line == 0) {
91a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        virtual_line = linemap->current;
92a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    }
93a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
94a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    /* Replace all existing mappings that have line numbers >= this one. */
95a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    for (i = linemap->map_size; i > 0; i--) {
96a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        if (linemap->map_vector[i-1].line < virtual_line) {
97a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            if (i < linemap->map_size) {
98a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                mapping = &linemap->map_vector[i];
99a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                linemap->map_size = i + 1;
100a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            }
101a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            break;
102a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        }
103a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    }
104a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
105a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    if (mapping == NULL) {
106a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        /* Create a new mapping in the map */
107a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        if (linemap->map_size >= linemap->map_allocated) {
108a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            /* allocate another size bins when full for 2x space */
109a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            linemap->map_vector = yasm_xrealloc(linemap->map_vector,
110a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                2*linemap->map_allocated*sizeof(line_mapping));
111a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            linemap->map_allocated *= 2;
112a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        }
113a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        mapping = &linemap->map_vector[linemap->map_size];
114a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        linemap->map_size++;
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Fill it */
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!filename) {
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (linemap->map_size >= 2)
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mapping->filename =
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                linemap->map_vector[linemap->map_size-2].filename;
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            filename = "unknown";
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (filename) {
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Copy the filename (via shared storage) */
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        copy = yasm__xstrdup(filename);
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@-aliasunique@*/
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mapping->filename = HAMT_insert(linemap->filenames, copy, copy,
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        &replace, filename_delete_one);
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@=aliasunique@*/
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
135a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    mapping->line = virtual_line;
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mapping->file_line = file_line;
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mapping->line_inc = line_inc;
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgunsigned long
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_poke(yasm_linemap *linemap, const char *filename,
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                  unsigned long file_line)
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long line;
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    line_mapping *mapping;
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->current++;
148a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    yasm_linemap_set(linemap, filename, 0, file_line, 0);
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mapping = &linemap->map_vector[linemap->map_size-1];
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    line = linemap->current;
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->current++;
155a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    yasm_linemap_set(linemap, mapping->filename, 0,
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     mapping->file_line +
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     mapping->line_inc*(linemap->current-2-mapping->line),
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     mapping->line_inc);
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return line;
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap *
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_create(void)
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t i;
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_linemap *linemap = yasm_xmalloc(sizeof(yasm_linemap));
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->filenames = HAMT_create(0, yasm_internal_error_);
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->current = 1;
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* initialize mapping vector */
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->map_vector = yasm_xmalloc(8*sizeof(line_mapping));
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->map_size = 0;
17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->map_allocated = 8;
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* initialize source line information array */
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->source_info_size = 2;
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->source_info = yasm_xmalloc(linemap->source_info_size *
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        sizeof(line_source_info));
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i=0; i<linemap->source_info_size; i++) {
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        linemap->source_info[i].bc = NULL;
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        linemap->source_info[i].source = NULL;
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return linemap;
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_destroy(yasm_linemap *linemap)
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t i;
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i=0; i<linemap->source_info_size; i++) {
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (linemap->source_info[i].source)
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_xfree(linemap->source_info[i].source);
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(linemap->source_info);
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(linemap->map_vector);
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (linemap->filenames)
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        HAMT_destroy(linemap->filenames, filename_delete_one);
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(linemap);
20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgunsigned long
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_get_current(yasm_linemap *linemap)
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return linemap->current;
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_add_source(yasm_linemap *linemap, yasm_bytecode *bc,
21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        const char *source)
21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t i;
21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (linemap->current > linemap->source_info_size) {
22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* allocate another size bins when full for 2x space */
22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        linemap->source_info = yasm_xrealloc(linemap->source_info,
22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            2*linemap->source_info_size*sizeof(line_source_info));
22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (i=linemap->source_info_size; i<linemap->source_info_size*2; i++) {
22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            linemap->source_info[i].bc = NULL;
22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            linemap->source_info[i].source = NULL;
22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        linemap->source_info_size *= 2;
22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Delete existing info for that line (if any) */
23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (linemap->source_info[linemap->current-1].source)
23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(linemap->source_info[linemap->current-1].source);
23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->source_info[linemap->current-1].bc = bc;
23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    linemap->source_info[linemap->current-1].source = yasm__xstrdup(source);
23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgunsigned long
24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_goto_next(yasm_linemap *linemap)
24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return ++(linemap->current);
24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_lookup(yasm_linemap *linemap, unsigned long line,
24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    const char **filename, unsigned long *file_line)
24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    line_mapping *mapping;
25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long vindex, step;
25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(line <= linemap->current);
25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Binary search through map to find highest line_index <= index */
25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vindex = 0;
25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* start step as the greatest power of 2 <= size */
25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    step = 1;
25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (step*2<=linemap->map_size)
25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        step*=2;
26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (step>0) {
26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (vindex+step < linemap->map_size
26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                && linemap->map_vector[vindex+step].line <= line)
26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            vindex += step;
26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        step /= 2;
26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mapping = &linemap->map_vector[vindex];
26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *filename = mapping->filename;
269a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    *file_line = (line ? mapping->file_line + mapping->line_inc*(line-mapping->line) : 0);
27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint
27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_traverse_filenames(yasm_linemap *linemap, /*@null@*/ void *d,
27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                int (*func) (const char *filename, void *d))
27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return HAMT_traverse(linemap->filenames, d, (int (*) (void *, void *))func);
27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint
28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_linemap_get_source(yasm_linemap *linemap, unsigned long line,
28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_bytecode **bcp, const char **sourcep)
28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (line > linemap->source_info_size) {
28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *bcp = NULL;
28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *sourcep = NULL;
28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 1;
28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *bcp = linemap->source_info[line-1].bc;
29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *sourcep = linemap->source_info[line-1].source;
29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return (!(*sourcep));
29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
294