2017-10-21 23:40:19 +00:00
|
|
|
procedure PrintOneSymbol {ip: identPtr};
|
|
|
|
|
|
|
|
{ Print a symbol }
|
|
|
|
{ }
|
|
|
|
{ Parameters: }
|
|
|
|
{ ip - identifier to print }
|
|
|
|
|
|
|
|
|
|
|
|
procedure PrintClass (class: tokenEnum);
|
|
|
|
|
|
|
|
{ Print the class of a symbol }
|
|
|
|
{ }
|
|
|
|
{ Parameters: }
|
|
|
|
{ class - class of the symbol }
|
|
|
|
|
|
|
|
begin {PrintClass}
|
|
|
|
case class of
|
|
|
|
autosy: write('auto');
|
|
|
|
externsy: write('extern');
|
|
|
|
ident: write('ident');
|
|
|
|
otherwise: write(ord(class):1);
|
|
|
|
end; {case}
|
|
|
|
end; {PrintClass}
|
|
|
|
|
|
|
|
|
|
|
|
procedure PrintType (tp: typePtr);
|
|
|
|
|
|
|
|
{ Print a type }
|
|
|
|
{ }
|
|
|
|
{ Parameters: }
|
|
|
|
{ tp - type pointer }
|
|
|
|
|
|
|
|
begin {PrintType}
|
|
|
|
with tp^ do begin
|
|
|
|
write(' ', size:1, ' byte ');
|
Record volatile and restrict qualifiers in types.
These are needed to correctly distinguish pointer types in _Generic. They should also be used for type compatibility checks in other contexts, but currently are not.
This also fixes a couple small problems related to type qualifiers:
*restrict was not allowed to appear after * in type-names
*volatile status was not properly recorded in sym files
Here is an example of using _Generic to distinguish pointer types based on the qualifiers of the pointed-to type:
#include <stdio.h>
#define f(e) _Generic((e),\
int * restrict *: 1,\
int * volatile const *: 2,\
int **: 3,\
default: 0)
#define g(e) _Generic((e),\
int *: 1,\
const int *: 2,\
volatile int *: 3,\
default: 0)
int main(void) {
int * restrict * p1;
int * volatile const * p2;
int * const * p3;
// should print "1 2 0 1"
printf("%i %i %i %i\n", f(p1), f(p2), f(p3), f((int * restrict *)0));
int *q1;
const int *q2;
volatile int *q3;
const volatile int *q4;
// should print "1 2 3 0"
printf("%i %i %i %i\n", g(q1), g(q2), g(q3), g(q4));
}
Here is an example of a problem resulting from volatile not being recorded in sym files (if a sym file was present, the read of x was lifted out of the loop):
#pragma optimize -1
static volatile int x;
#include <stdio.h>
int main(void) {
int y;
for (unsigned i = 0; i < 100; i++) {
y = x*2 + 7;
}
}
2021-08-30 02:10:20 +00:00
|
|
|
if tqConst in qualifiers then
|
2017-10-21 23:40:19 +00:00
|
|
|
write('constant ');
|
Record volatile and restrict qualifiers in types.
These are needed to correctly distinguish pointer types in _Generic. They should also be used for type compatibility checks in other contexts, but currently are not.
This also fixes a couple small problems related to type qualifiers:
*restrict was not allowed to appear after * in type-names
*volatile status was not properly recorded in sym files
Here is an example of using _Generic to distinguish pointer types based on the qualifiers of the pointed-to type:
#include <stdio.h>
#define f(e) _Generic((e),\
int * restrict *: 1,\
int * volatile const *: 2,\
int **: 3,\
default: 0)
#define g(e) _Generic((e),\
int *: 1,\
const int *: 2,\
volatile int *: 3,\
default: 0)
int main(void) {
int * restrict * p1;
int * volatile const * p2;
int * const * p3;
// should print "1 2 0 1"
printf("%i %i %i %i\n", f(p1), f(p2), f(p3), f((int * restrict *)0));
int *q1;
const int *q2;
volatile int *q3;
const volatile int *q4;
// should print "1 2 3 0"
printf("%i %i %i %i\n", g(q1), g(q2), g(q3), g(q4));
}
Here is an example of a problem resulting from volatile not being recorded in sym files (if a sym file was present, the read of x was lifted out of the loop):
#pragma optimize -1
static volatile int x;
#include <stdio.h>
int main(void) {
int y;
for (unsigned i = 0; i < 100; i++) {
y = x*2 + 7;
}
}
2021-08-30 02:10:20 +00:00
|
|
|
if tqVolatile in qualifiers then
|
|
|
|
write('volatile ');
|
|
|
|
if tqRestrict in qualifiers then
|
|
|
|
write('restricted ');
|
2017-10-21 23:40:19 +00:00
|
|
|
case kind of
|
|
|
|
scalarType : writeln('scalar');
|
|
|
|
arrayType : begin
|
|
|
|
writeln(elements: 1, ' element array of');
|
|
|
|
PrintType(aType);
|
|
|
|
end;
|
|
|
|
pointerType : begin
|
|
|
|
writeln(' pointer to');
|
|
|
|
PrintType(pType);
|
|
|
|
end;
|
|
|
|
functionType: begin
|
|
|
|
writeln(' function returning');
|
|
|
|
PrintType(fType);
|
|
|
|
end;
|
|
|
|
enumConst : writeln('enumeration (', eval: 1, ')');
|
|
|
|
enumType : writeln('enum type');
|
|
|
|
definedType : begin
|
|
|
|
writeln('defined type of');
|
|
|
|
PrintType(dType);
|
|
|
|
end;
|
|
|
|
structType : writeln('struct: ', ord4(tp):1);
|
|
|
|
unionType : writeln('union');
|
|
|
|
end; {case}
|
|
|
|
end; {with}
|
|
|
|
end; {PrintType}
|
|
|
|
|
|
|
|
|
|
|
|
begin {PrintOneSymbol}
|
|
|
|
with ip^ do begin
|
|
|
|
writeln; {start with a blank line}
|
|
|
|
write(name^, {write id info}
|
|
|
|
': isForwardDeclared = ', isForwardDeclared,
|
|
|
|
'; class = ');
|
|
|
|
PrintClass(class);
|
|
|
|
writeln;
|
|
|
|
|
|
|
|
PrintType(iType); {print type info}
|
|
|
|
end; {with}
|
|
|
|
end; {PrintOneSymbol}
|
|
|
|
|
|
|
|
|
|
|
|
procedure PrintTable {sym: symbolTablePtr};
|
|
|
|
|
|
|
|
{ print a symbol table }
|
|
|
|
{ }
|
|
|
|
{ parameters: }
|
|
|
|
{ sym - symbol table to print }
|
|
|
|
|
|
|
|
var
|
|
|
|
i: integer; {loop variable}
|
|
|
|
ip: identPtr; {current symbol}
|
|
|
|
|
|
|
|
begin {PrintTable}
|
|
|
|
if sym <> nil then begin
|
|
|
|
writeln; {write header}
|
|
|
|
writeln('Symbols:');
|
|
|
|
writeln('========');
|
|
|
|
for i := 0 to hashSize do begin {loop over all hash buckets}
|
|
|
|
ip := sym^.buckets[i]; {trace through all symbols in this bucket}
|
|
|
|
while ip <> nil do begin
|
|
|
|
PrintOneSymbol(ip); {print a symbol}
|
|
|
|
ip := ip^.next; {next symbol}
|
|
|
|
end; {while}
|
|
|
|
end; {for}
|
|
|
|
end; {if}
|
|
|
|
end; {PrintTable}
|