commit 0d929287d77ccc3fb52ca8bd072678b5ae2c81c8
parent e493a7f23352f51acc0a1e12284ab19d7894488a
Author: Thomas Bracht Laumann Jespersen <t@laumann.xyz>
Date: Thu, 26 Jan 2023 12:09:44 +0100
implement line number info tracking
Support "file" and "loc" directives. "file" 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.
Diffstat:
10 files changed, 75 insertions(+), 7 deletions(-)
diff --git a/all.h b/all.h
@@ -502,7 +502,7 @@ bshas(BSet *bs, uint elt)
/* parse.c */
extern Op optab[NOp];
-void parse(FILE *, char *, void (Dat *), void (Fn *));
+void parse(FILE *, char *, void (char *), void (Dat *), void (Fn *));
void printfn(Fn *, FILE *);
void printref(Ref, Fn *, FILE *);
void err(char *, ...) __attribute__((noreturn));
@@ -568,6 +568,8 @@ void rega(Fn *);
/* emit.c */
void emitfnlnk(char *, Lnk *, FILE *);
void emitdat(Dat *, FILE *);
+void emitdbgfile(char *, FILE *);
+void emitdbgloc(uint, FILE *);
int stashbits(void *, int);
void elf_emitfnfin(char *, FILE *);
void elf_emitfin(FILE *);
diff --git a/amd64/emit.c b/amd64/emit.c
@@ -547,6 +547,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:
+ emitdbgloc(i.arg[0].val, f);
+ break;
}
}
diff --git a/amd64/isel.c b/amd64/isel.c
@@ -392,6 +392,7 @@ sel(Ins i, ANum *an, Fn *fn)
case_Oload:
seladdr(&i.arg[0], an, fn);
goto Emit;
+ case Oloc:
case Ocall:
case Osalloc:
case Ocopy:
diff --git 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:
+ emitdbgloc(i->arg[0].val, e->f);
+ break;
}
}
diff --git a/emit.c b/emit.c
@@ -207,3 +207,35 @@ macho_emitfin(FILE *f)
emitfin(f, sec);
}
+
+static uint32_t *file;
+static uint nfile;
+static uint curfile;
+
+void
+emitdbgfile(char *fn, FILE *f)
+{
+ uint32_t id;
+ uint n;
+
+ id = intern(fn);
+ for (n=0; n<nfile; n++)
+ if (file[n] == id) {
+ /* gas requires positive
+ * file numbers */
+ curfile = n + 1;
+ return;
+ }
+ if (!file)
+ file = vnew(0, sizeof *file, PHeap);
+ vgrow(&file, ++nfile);
+ file[nfile-1] = id;
+ curfile = nfile;
+ fprintf(f, ".file %u %s\n", curfile, fn);
+}
+
+void
+emitdbgloc(uint loc, FILE *f)
+{
+ fprintf(f, "\t.loc %u %u\n", curfile, loc);
+}
diff --git a/main.c b/main.c
@@ -107,6 +107,12 @@ func(Fn *fn)
freeall();
}
+static void
+dbgfile(char *fn)
+{
+ emitdbgfile(fn, outf);
+}
+
int
main(int ac, char *av[])
{
@@ -181,7 +187,7 @@ main(int ac, char *av[])
exit(1);
}
}
- parse(inf, f, data, func);
+ parse(inf, f, dbgfile, data, func);
fclose(inf);
} while (++optind < ac);
diff --git 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 */
+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
@@ -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,
};
@@ -655,6 +657,16 @@ parseline(PState ps)
expect(Tnl);
closeblk();
return PLbl;
+ case Oloc:
+ expect(Tint);
+ op = Oloc;
+ k = Kw;
+ r = R;
+ arg[0] = INT(tokval.num);
+ if (arg[0].val != tokval.num)
+ err("line number too big");
+ arg[1] = R;
+ goto Ins;
}
r = tmpref(tokval.str);
expect(Teq);
@@ -1160,7 +1172,7 @@ parselnk(Lnk *lnk)
}
void
-parse(FILE *f, char *path, void data(Dat *), void func(Fn *))
+parse(FILE *f, char *path, void dbgfile(char *), void data(Dat *), void func(Fn *))
{
Lnk lnk;
uint n;
@@ -1177,6 +1189,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);
+ break;
case Tfunc:
func(parsefn(&lnk));
break;
diff --git 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:
+ emitdbgloc(i->arg[0].val, f);
+ break;
}
}
diff --git 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",