Skip to content

Commit

Permalink
fcommon in WCC
Browse files Browse the repository at this point in the history
Make bss variable as `weak` symbol.
  • Loading branch information
tyfkda committed Oct 26, 2024
1 parent c0b937d commit aeede21
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 53 deletions.
21 changes: 11 additions & 10 deletions src/wcc/emit_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ typedef struct {
uint32_t p2align;
} DataSegment;

static Vector *construct_data_segment(void) {
static Vector *construct_data_segment(void) { // <DataSegment*>
// Enumerate global variables.
Vector *segments = new_vector();
#ifndef NDEBUG
Expand Down Expand Up @@ -515,7 +515,7 @@ static void emit_code_section(EmitWasm *ew) {
}

static Vector *emit_data_section(EmitWasm *ew) {
Vector *segments = construct_data_segment();
Vector *segments = construct_data_segment(); // <DataSegment*>
ew->data_segments = segments;
Vector *reloc_data = NULL;
if (segments->len > 0) {
Expand Down Expand Up @@ -606,6 +606,7 @@ static void emit_linking_section(EmitWasm *ew) {
for (int k = 0; k < 3; ++k) { // 0=unresolved, 1=resolved(data), 2=resolved(bss)
const Name *name;
GVarInfo *info;
int flags_bss = k != 2 ? 0 : cc_flags.common ? WASM_SYM_BINDING_WEAK : 0;
for (int it = 0; (it = table_iterate(&gvar_info_table, it, &name, (void**)&info)) != -1; ) {
const VarInfo *varinfo = info->varinfo;
if (varinfo->storage & VS_ENUM_MEMBER || varinfo->type->kind == TY_FUNC)
Expand All @@ -617,7 +618,7 @@ static void emit_linking_section(EmitWasm *ew) {
(k != 0 && ((info->flag & GVF_UNRESOLVED) || (varinfo->global.init == NULL) == (k == 1))))
continue;

int flags = 0;
int flags = flags_bss;
if (info->flag & GVF_UNRESOLVED)
flags |= WASM_SYM_UNDEFINED;
if (varinfo->storage & VS_STATIC)
Expand Down Expand Up @@ -671,14 +672,14 @@ static void emit_linking_section(EmitWasm *ew) {
VarInfo *varinfo = segment->gvarinfo->varinfo;
int flags = 0;
if (varinfo->global.init != NULL && varinfo->global.init->kind == IK_SINGLE) {
Expr *e = varinfo->global.init->single;
if (e->kind == EX_STR && e->str.kind == STR_CHAR) {
const Type *type = varinfo->type;
if (type->kind == TY_ARRAY && type->pa.length > 0 &&
type->pa.length == (ssize_t)e->str.len && e->str.buf[type->pa.length - 1] == '\0')
flags |= WASM_SEG_FLAG_STRINGS;
Expr *e = varinfo->global.init->single;
if (e->kind == EX_STR && e->str.kind == STR_CHAR) {
const Type *type = varinfo->type;
if (type->kind == TY_ARRAY && type->pa.length > 0 &&
type->pa.length == (ssize_t)e->str.len && e->str.buf[type->pa.length - 1] == '\0')
flags |= WASM_SEG_FLAG_STRINGS;
}
}
}
data_string(&linking_section, varinfo->name->chars, varinfo->name->bytes);
data_uleb128(&linking_section, -1, segment->p2align);
data_uleb128(&linking_section, -1, flags);
Expand Down
53 changes: 44 additions & 9 deletions src/wcc/wcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,27 @@ int compile_csource(const char *src, const char *ofn, Vector *obj_files, Options
return 0;
}

static bool parse_fopt(const char *optarg, bool value) {
static const struct {
const char *flag_name;
off_t flag_offset;
} kFlagTable[] = {
{"common", offsetof(CcFlags, common)},
};

for (size_t i = 0; i < ARRAY_SIZE(kFlagTable); ++i) {
if (strcmp(optarg, kFlagTable[i].flag_name) == 0) {
size_t len = strlen(kFlagTable[i].flag_name);
if (optarg[len] != '\0')
continue;
bool *p = (bool*)((char*)&cc_flags + kFlagTable[i].flag_offset);
*p = value;
return true;
}
}
return false;
}

static void parse_options(int argc, char *argv[], Options *opts) {
enum {
OPT_HELP = 128,
Expand All @@ -268,6 +289,7 @@ static void parse_options(int argc, char *argv[], Options *opts) {
OPT_NOSTDINC,
OPT_ISYSTEM,
OPT_IDIRAFTER,
OPT_FNO,

OPT_WARNING,
OPT_OPTIMIZE,
Expand All @@ -290,7 +312,6 @@ static void parse_options(int argc, char *argv[], Options *opts) {
{"o", required_argument}, // Specify output filename
{"x", required_argument}, // Specify code type
{"e", required_argument}, // Export names
{"W", required_argument, OPT_WARNING},
{"nodefaultlibs", no_argument, OPT_NODEFAULTLIBS},
{"nostdlib", no_argument, OPT_NOSTDLIB},
{"nostdinc", no_argument, OPT_NOSTDINC},
Expand All @@ -302,6 +323,11 @@ static void parse_options(int argc, char *argv[], Options *opts) {
{"-version", no_argument, OPT_VERSION},
{"dumpversion", no_argument, OPT_DUMP_VERSION},

// Sub command
{"fno-", required_argument, OPT_FNO},
{"f", required_argument},
{"W", required_argument},

// Suppress warnings
{"O", required_argument, OPT_OPTIMIZE},
{"g", required_argument, OPT_DEBUGINFO},
Expand Down Expand Up @@ -399,14 +425,6 @@ static void parse_options(int argc, char *argv[], Options *opts) {
error("language not recognized: %s", optarg);
}
break;
case OPT_WARNING:
if (strcmp(optarg, "error") == 0) {
cc_flags.warn_as_error = true;
} else {
// Silently ignored.
// fprintf(stderr, "Warning: unknown option for -W: %s\n", optarg);
}
break;
case OPT_NODEFAULTLIBS:
opts->nodefaultlibs = true;
break;
Expand Down Expand Up @@ -445,6 +463,23 @@ static void parse_options(int argc, char *argv[], Options *opts) {
}
break;

case 'f':
case OPT_FNO:
if (!parse_fopt(optarg, opt == 'f')) {
// Silently ignored.
// fprintf(stderr, "Warning: unknown option for -f: %s\n", optarg);
}
break;

case 'W':
if (strcmp(optarg, "error") == 0) {
cc_flags.warn_as_error = true;
} else {
// Silently ignored.
// fprintf(stderr, "Warning: unknown option for -W: %s\n", optarg);
}
break;

case OPT_OPTIMIZE:
case OPT_DEBUGINFO:
case OPT_ANSI:
Expand Down
51 changes: 19 additions & 32 deletions src/wcc/www/diswasm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1184,12 +1184,23 @@ export class DisWasm {
{
this.log(`${this.addr(subsecOffset0)};; (symtab`)

const countTable = new Map<SymInfoKind, number>([
[SymInfoKind.SYMTAB_FUNCTION, this.importFuncCount],
[SymInfoKind.SYMTAB_GLOBAL, this.importGlobalCount],
[SymInfoKind.SYMTAB_TABLE, this.importTableCount],
])

const count = this.bufferReader.readUleb128()
for (let i = 0; i < count; ++i) {
const offset = this.bufferReader.getOffset()
const kind = this.bufferReader.readu8()
const flags = this.bufferReader.readUleb128()

const flagStr = Array.from(kSymFlagNames.keys())
.filter(key => (flags & key) !== 0)
.map(key => kSymFlagNames.get(key))
.join(' ')

switch (kind) {
case SymInfoKind.SYMTAB_FUNCTION:
case SymInfoKind.SYMTAB_GLOBAL:
Expand All @@ -1198,50 +1209,26 @@ export class DisWasm {
const index = this.bufferReader.readUleb128()
let symname = ''

switch (kind) {
case SymInfoKind.SYMTAB_FUNCTION:
if (index < this.importFuncCount && !(flags & SymFlags.WASM_SYM_EXPLICIT_NAME)) {
symname = this.funcs.get(index)!.join('.')
} else {
symname = this.bufferReader.readString()
}
break
case SymInfoKind.SYMTAB_GLOBAL:
if (index < this.importGlobalCount && !(flags & SymFlags.WASM_SYM_EXPLICIT_NAME)) {
symname = this.globals.get(index)!.join('.')
} else {
symname = this.bufferReader.readString()
}
break
case SymInfoKind.SYMTAB_TABLE:
if (index < this.importTableCount && !(flags & SymFlags.WASM_SYM_EXPLICIT_NAME)) {
symname = this.tables.get(index)!.join('.')
} else {
symname = this.bufferReader.readString()
}
break
default: break
if (index < countTable.get(kind)! && !(flags & SymFlags.WASM_SYM_EXPLICIT_NAME)) {
symname = this.funcs.get(index)!.join('.')
} else {
symname = this.bufferReader.readString()
}

const flagNames: Array<string> = []
kSymFlagNames.forEach((value, key) => {
if ((flags & key) !== 0)
flagNames.push(value)
})
this.log(`${this.addr(offset)};; (${kSymInfoKindNames[kind]} (index ${index}) (name "${symname}") (flags ${flagNames.join(' ')}))`)
this.log(`${this.addr(offset)};; (${kSymInfoKindNames[kind]} (index ${index}) (name "${symname}") (flags ${flagStr}))`)
symbols.push(symname)
}
break
case SymInfoKind.SYMTAB_DATA:
{
const symname = this.bufferReader.readString()
if (flags & SymFlags.WASM_SYM_UNDEFINED) {
this.log(`${this.addr(offset)};; (${kSymInfoKindNames[kind]} (name "${symname}"))`)
this.log(`${this.addr(offset)};; (${kSymInfoKindNames[kind]} (name "${symname}") (flags ${flagStr}))`)
} else {
const index = this.bufferReader.readUleb128()
const suboffset = this.bufferReader.readUleb128()
const size = this.bufferReader.readUleb128()
this.log(`${this.addr(offset)};; (${kSymInfoKindNames[kind]} (name "${symname}") (index ${index}) (offset ${suboffset}) (size ${size}))`)
this.log(`${this.addr(offset)};; (${kSymInfoKindNames[kind]} (name "${symname}") (index ${index}) (offset ${suboffset}) (size ${size}) (flags ${flagStr}))`)
}
symbols.push(symname)
}
Expand All @@ -1250,7 +1237,7 @@ export class DisWasm {
{
const typeindex = this.bufferReader.readUleb128()
const symname = this.bufferReader.readString()
this.log(`${this.addr(offset)};; (${kSymInfoKindNames[kind]} (name "${symname}") (typeindex ${typeindex}))`)
this.log(`${this.addr(offset)};; (${kSymInfoKindNames[kind]} (name "${symname}") (typeindex ${typeindex}) (flags ${flagStr}))`)
symbols.push(symname)
}
break
Expand Down
4 changes: 2 additions & 2 deletions tests/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ test_link() {

echo 'int foo; int main(){return 0;}' > tmp_link_dupcomm1.c
echo 'int foo;' > tmp_link_dupcomm2.c
link_error 'Duplicate comm symbol' tmp_link_dupcomm1.c tmp_link_dupcomm2.c
link_success "allowed with '-fcommon' //-WCC" -fcommon tmp_link_dupcomm1.c tmp_link_dupcomm2.c
link_error 'Duplicate comm symbol' tmp_link_dupcomm1.c tmp_link_dupcomm2.c
link_success "allowed with '-fcommon'" -fcommon tmp_link_dupcomm1.c tmp_link_dupcomm2.c

# extern inline function can be called.
echo -e 'inline int sq(int x){return x * x;} \n#ifdef EXTERN\n extern inline int sq(int x);\n#endif' > tmp_link_inline1.c
Expand Down

0 comments on commit aeede21

Please sign in to comment.