Support "line" and "loc" directives. "line" takes a string (a file name)
assigns it a number, sets the current file to that number and records
the string for later. "loc" takes a single number and outputs location
information with a reference to the current file.
---
v4 -> v5:
* Rename emitfile()/emitloc() to dbgfile()/dbgloc()
* This version keeps track of seen file names. Calling dbgfile() sets a global
current file and optionally emits a .file n <filename> directive once per
file name.
* Removes the "file number" from Fn and calls to dbgfile() and dbgloc(). Calls
to dbgloc() just use the current file number
The result is that something like:
file "x.ha"
file "y.ha"
loc 1
loc 2
file "x.ha"
loc 3
produces:
.file 1 "x.ha"
.file 2 "y.ha"
.loc 2 1
.loc 2 2
.loc 1 3
So for qbe, you need to emit "file" to set the current file for subsequent
occurrences of "loc", but the .file directive is only emitted once per file.
I'd appreciate feedback on the string vector setup (dbgfiles), I'm not sure it's
the right way to go about it.
all.h | 8 +++++++-
amd64/emit.c | 3 +++
amd64/isel.c | 3 +++
arm64/emit.c | 3 +++
arm64/isel.c | 4 ++++
emit.c | 37 +++++++++++++++++++++++++++++++++++++
main.c | 4 +++-
ops.h | 2 ++
parse.c | 11 +++++++++--
rv64/emit.c | 3 +++
rv64/isel.c | 4 ++++
tools/lexh.c | 6 +++---
12 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/all.h b/all.h
index 7eba443..3c5b460 100644
--- a/all.h
+++ b/all.h
@@ -501,7 +501,7 @@ bshas(BSet *bs, uint elt)
/* parse.c */
extern Op optab[NOp];
-void parse(FILE *, char *, void (Dat *), void (Fn *));
+void parse(FILE *, char *, FILE *, void (Dat *), void (Fn *));
void printfn(Fn *, FILE *);
void printref(Ref, Fn *, FILE *);
void err(char *, ...) __attribute__((noreturn));
@@ -571,3 +571,9 @@ int stashbits(void *, int);
void elf_emitfnfin(char *, FILE *);
void elf_emitfin(FILE *);
void macho_emitfin(FILE *);
+
+extern uint curfile;
+extern char **dbgfiles;
+void dbgfile(char *, FILE *);
+void dbgloc(long int, FILE *);
+void freedbgfiles();
diff --git a/amd64/emit.c b/amd64/emit.c
index 9b8bb5d..15f7c1e 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -525,6 +525,9 @@ emitins(Ins i, Fn *fn, FILE *f)
emitcopy(i.arg[0], i.arg[1], i.cls, fn, f);
emitcopy(i.arg[1], TMP(XMM0+15), i.cls, fn, f);
break;
+ case Oloc:
+ dbgloc(fn->con[i.arg[0].val].bits.i, f);
+ break;
}
}
diff --git a/amd64/isel.c b/amd64/isel.c
index 3e3fe62..caf10d2 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -371,6 +371,9 @@ sel(Ins i, ANum *an, Fn *fn)
case_Oload:
seladdr(&i.arg[0], an, fn);
goto Emit;
+ case Oloc:
+ emiti(i);
+ break;
case Ocall:
case Osalloc:
case Ocopy:
diff --git a/arm64/emit.c b/arm64/emit.c
index 5113c66..1b9e417 100644
--- a/arm64/emit.c
+++ b/arm64/emit.c
@@ -446,6 +446,9 @@ emitins(Ins *i, E *e)
if (!req(i->to, R))
emitf("mov %=, sp", i, e);
break;
+ case Oloc:
+ dbgloc(e->fn->con[i->arg[0].val].bits.i, e->f);
+ break;
}
}
diff --git a/arm64/isel.c b/arm64/isel.c
index 062beb3..a2c53aa 100644
--- a/arm64/isel.c
+++ b/arm64/isel.c
@@ -224,6 +224,10 @@ sel(Ins i, Fn *fn)
emiti(i);
return;
}
+ if (i.op == Oloc) {
+ emiti(i);
+ return;
+ }
if (i.op != Onop) {
emiti(i);
iarg = curi->arg; /* fixarg() can change curi */
diff --git a/emit.c b/emit.c
index 017c461..45b80cb 100644
--- a/emit.c
+++ b/emit.c
@@ -207,3 +207,40 @@ macho_emitfin(FILE *f)
emitfin(f, sec);
}
+
+uint curfile = 0;
+static uint nfiles = 0;
+char **dbgfiles = NULL;
+
+// Emit a ".file" line and set the current file for subsequent calls to dbgloc()
+void
+dbgfile(char *fname, FILE *f)
+{
+ uint i;
+
+ for (i = 0; i < nfiles; i++)
+ if (!strcmp(fname, dbgfiles[i]))
+ break;
+
+ curfile = i + 1;
+ if (i == nfiles) {
+ vgrow(&dbgfiles, ++nfiles);
+ dbgfiles[i] = emalloc(strlen(fname)+1);
+ strcpy(dbgfiles[i], fname);
+ fprintf(f, ".file %u %s\n", curfile, fname);
+ }
+}
+
+void
+dbgloc(long int line, FILE *f)
+{
+ fprintf(f, "\t.loc %u %ld\n", curfile, line);
+}
+
+void
+freedbgfiles()
+{
+ for (uint i = 0; i < nfiles; i++)
+ free(dbgfiles[i]);
+ vfree(dbgfiles);
+}
diff --git a/main.c b/main.c
index abfe03e..8e11b90 100644
--- a/main.c
+++ b/main.c
@@ -169,6 +169,7 @@ main(int ac, char *av[])
exit(c != 'h');
}
+ dbgfiles = vnew(0, sizeof(char *), PHeap);
do {
f = av[optind];
if (!f || strcmp(f, "-") == 0) {
@@ -181,9 +182,10 @@ main(int ac, char *av[])
exit(1);
}
}
- parse(inf, f, data, func);
+ parse(inf, f, outf, data, func);
fclose(inf);
} while (++optind < ac);
+ freedbgfiles();
if (!dbg)
T.emitfin(outf);
diff --git a/ops.h b/ops.h
index fbcc2a8..6a7fb3b 100644
--- a/ops.h
+++ b/ops.h
@@ -121,6 +121,8 @@ O(vastart, T(m,e,e,e, x,e,e,e), 0) X(0, 0, 0) V(0)
O(copy, T(w,l,s,d, x,x,x,x), 0) X(0, 0, 1) V(0)
+/* Debug info */
+O(loc, T(w,l,s,d, x,x,x,x), 0) X(0, 0, 1) V(0)
/****************************************/
/* INTERNAL OPERATIONS (keep nop first) */
diff --git a/parse.c b/parse.c
index aed9427..0afeac0 100644
--- a/parse.c
+++ b/parse.c
@@ -53,6 +53,7 @@ enum Token {
Tdata,
Tsection,
Talign,
+ Tfile,
Tl,
Tw,
Tsh,
@@ -110,6 +111,7 @@ static char *kwmap[Ntok] = {
[Tdata] = "data",
[Tsection] = "section",
[Talign] = "align",
+ [Tfile] = "file",
[Tsb] = "sb",
[Tub] = "ub",
[Tsh] = "sh",
@@ -130,7 +132,7 @@ enum {
TMask = 16383, /* for temps hash */
BMask = 8191, /* for blocks hash */
- K = 9583425, /* found using tools/lexh.c */
+ K = 10525445, /* found using tools/lexh.c */
M = 23,
};
@@ -592,6 +594,7 @@ parseline(PState ps)
case Tblit:
case Tcall:
case Ovastart:
+ case Oloc:
/* operations without result */
r = R;
k = Kw;
@@ -1160,7 +1163,7 @@ parselnk(Lnk *lnk)
}
void
-parse(FILE *f, char *path, void data(Dat *), void func(Fn *))
+parse(FILE *f, char *path, FILE *outf, void data(Dat *), void func(Fn *))
{
Lnk lnk;
uint n;
@@ -1177,6 +1180,10 @@ parse(FILE *f, char *path, void data(Dat *), void func(Fn *))
switch (parselnk(&lnk)) {
default:
err("top-level definition expected");
+ case Tfile:
+ expect(Tstr);
+ dbgfile(tokval.str, outf);
+ break;
case Tfunc:
func(parsefn(&lnk));
break;
diff --git a/rv64/emit.c b/rv64/emit.c
index f9df146..2643b66 100644
--- a/rv64/emit.c
+++ b/rv64/emit.c
@@ -405,6 +405,9 @@ emitins(Ins *i, Fn *fn, FILE *f)
if (!req(i->to, R))
emitf("mv %=, sp", i, fn, f);
break;
+ case Oloc:
+ dbgloc(fn->con[i->arg[0].val].bits.i, f);
+ break;
}
}
diff --git a/rv64/isel.c b/rv64/isel.c
index 8921a07..d9bbefe 100644
--- a/rv64/isel.c
+++ b/rv64/isel.c
@@ -187,6 +187,10 @@ sel(Ins i, Fn *fn)
selcmp(i, ck, cc, fn);
return;
}
+ if (i.op == Oloc) {
+ emiti(i);
+ return;
+ }
if (i.op != Onop) {
emiti(i);
i0 = curi; /* fixarg() can change curi */
diff --git a/tools/lexh.c b/tools/lexh.c
index 5ceb4ee..8883976 100644
--- a/tools/lexh.c
+++ b/tools/lexh.c
@@ -23,11 +23,11 @@ char *tok[] = {
"ceql", "cnel", "cles", "clts", "cgts", "cges",
"cnes", "ceqs", "cos", "cuos", "cled", "cltd",
"cgtd", "cged", "cned", "ceqd", "cod", "cuod",
- "vaarg", "vastart", "...", "env",
+ "vaarg", "vastart", "...", "env", "loc",
"call", "phi", "jmp", "jnz", "ret", "hlt", "export",
- "function", "type", "data", "section", "align", "blit",
- "l", "w", "sh", "uh", "h", "sb", "ub", "b",
+ "function", "type", "data", "section", "align", "file",
+ "blit", "l", "w", "sh", "uh", "h", "sb", "ub", "b",
"d", "s", "z", "loadw", "loadl", "loads", "loadd",
"alloc1", "alloc2",
--
2.38.2