Skip to content

Commit

Permalink
Handle fcommon option
Browse files Browse the repository at this point in the history
  * If `-fno-common` or by default, then put variable into `.bss` section
  * Add `.zero` dhirective
  • Loading branch information
tyfkda committed Oct 1, 2024
1 parent 470ca3e commit 3f656aa
Show file tree
Hide file tree
Showing 15 changed files with 185 additions and 38 deletions.
12 changes: 12 additions & 0 deletions src/as/arch/aarch64/ir_asm_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ bool calc_label_address(uintptr_t start_address, Vector *sections, Table *label_
case IR_BSS:
address += ir->bss;
break;
case IR_ZERO:
address += ir->zero;
break;
case IR_ALIGN:
ir->address = address = ALIGN(address, ir->align);
if ((size_t)ir->align > section->align) {
Expand Down Expand Up @@ -263,6 +266,7 @@ bool resolve_relative_address(Vector *sections, Table *label_table, Vector *unre
case IR_LABEL:
case IR_DATA:
case IR_BSS:
case IR_ZERO:
case IR_ALIGN:
break;
}
Expand Down Expand Up @@ -290,6 +294,14 @@ void emit_irs(Vector *sections) {
case IR_BSS:
sec_add_bss(section, ir->bss);
break;
case IR_ZERO:
if (section->flag & SF_BSS) {
sec_add_bss(section, ir->zero);
} else {
void *buf = calloc_or_die(ir->zero);
sec_add_data(section, buf, ir->zero);
}
break;
case IR_ALIGN:
sec_align_size(section, ir->align);
break;
Expand Down
12 changes: 12 additions & 0 deletions src/as/arch/riscv64/ir_asm_riscv64.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ bool calc_label_address(uintptr_t start_address, Vector *sections, Table *label_
case IR_BSS:
address += ir->bss;
break;
case IR_ZERO:
address += ir->zero;
break;
case IR_ALIGN:
ir->address = address = ALIGN(address, ir->align);
if ((size_t)ir->align > section->align) {
Expand Down Expand Up @@ -340,6 +343,7 @@ bool resolve_relative_address(Vector *sections, Table *label_table, Vector *unre
case IR_LABEL:
case IR_DATA:
case IR_BSS:
case IR_ZERO:
case IR_ALIGN:
break;
}
Expand Down Expand Up @@ -367,6 +371,14 @@ void emit_irs(Vector *sections) {
case IR_BSS:
sec_add_bss(section, ir->bss);
break;
case IR_ZERO:
if (section->flag & SF_BSS) {
sec_add_bss(section, ir->zero);
} else {
void *buf = calloc_or_die(ir->zero);
sec_add_data(section, buf, ir->zero);
}
break;
case IR_ALIGN:
sec_align_size(section, ir->align);
break;
Expand Down
12 changes: 12 additions & 0 deletions src/as/arch/x64/ir_asm_x64.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ bool calc_label_address(uintptr_t start_address, Vector *sections, Table *label_
case IR_BSS:
address += ir->bss;
break;
case IR_ZERO:
address += ir->zero;
break;
case IR_ALIGN:
ir->address = address = ALIGN(address, ir->align);
if ((size_t)ir->align > section->align) {
Expand Down Expand Up @@ -259,6 +262,7 @@ bool resolve_relative_address(Vector *sections, Table *label_table, Vector *unre
case IR_LABEL:
case IR_DATA:
case IR_BSS:
case IR_ZERO:
case IR_ALIGN:
break;
}
Expand Down Expand Up @@ -286,6 +290,14 @@ void emit_irs(Vector *sections) {
case IR_BSS:
sec_add_bss(section, ir->bss);
break;
case IR_ZERO:
if (section->flag & SF_BSS) {
sec_add_bss(section, ir->zero);
} else {
void *buf = calloc_or_die(ir->zero);
sec_add_data(section, buf, ir->zero);
}
break;
case IR_ALIGN:
sec_align_size(section, ir->align);
break;
Expand Down
7 changes: 7 additions & 0 deletions src/as/ir_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ IR *new_ir_bss(size_t size) {
return ir;
}

IR *new_ir_zero(size_t size) {
IR *ir = calloc_or_die(sizeof(*ir));
ir->kind = IR_ZERO;
ir->zero = size;
return ir;
}

IR *new_ir_align(int align) {
IR *ir = calloc_or_die(sizeof(*ir));
ir->kind = IR_ALIGN;
Expand Down
3 changes: 3 additions & 0 deletions src/as/ir_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ enum IrKind {
IR_CODE,
IR_DATA,
IR_BSS,
IR_ZERO,
IR_ALIGN,
IR_EXPR_BYTE,
IR_EXPR_SHORT,
Expand All @@ -73,6 +74,7 @@ typedef struct {
int64_t addend; // Calculated in `resolve_relative_address`
} expr;
size_t bss;
size_t zero;
int align;
int section;
};
Expand All @@ -83,6 +85,7 @@ IR *new_ir_label(const Name *label);
IR *new_ir_code(const Code *code);
IR *new_ir_data(const void *data, size_t size);
IR *new_ir_bss(size_t size);
IR *new_ir_zero(size_t size);
IR *new_ir_align(int align);
IR *new_ir_expr(enum IrKind kind, const Expr *expr);

Expand Down
15 changes: 15 additions & 0 deletions src/as/parse_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static const char *kDirectiveTable[] = {
"section",
"text",
"data",
"bss",
"align",
"p2align",
"type",
Expand All @@ -46,6 +47,7 @@ static const char *kDirectiveTable[] = {
"long",
"quad",
"comm",
"zero",
"globl",
"local",
"extern",
Expand Down Expand Up @@ -883,6 +885,15 @@ void handle_directive(ParseInfo *info, enum DirectiveType dir) {
}
break;

case DT_ZERO:
{
int64_t num;
if (!immediate(&info->p, &num))
parse_error(info, ".zero: number expected");
vec_push(irs, new_ir_zero(num));
}
break;

case DT_TEXT:
set_current_section(info, kSecText, kSegText, SF_EXECUTABLE);
break;
Expand All @@ -891,6 +902,10 @@ void handle_directive(ParseInfo *info, enum DirectiveType dir) {
set_current_section(info, kSecData, kSegData, SF_WRITABLE);
break;

case DT_BSS:
set_current_section(info, kSecBss, kSegBss, SF_BSS | SF_WRITABLE);
break;

case DT_ALIGN:
{
int64_t align;
Expand Down
2 changes: 2 additions & 0 deletions src/as/parse_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum DirectiveType {
DT_SECTION,
DT_TEXT,
DT_DATA,
DT_BSS,
DT_ALIGN,
DT_P2ALIGN,
DT_TYPE,
Expand All @@ -28,6 +29,7 @@ enum DirectiveType {
DT_LONG,
DT_QUAD,
DT_COMM,
DT_ZERO,
DT_GLOBL,
DT_LOCAL,
DT_EXTERN,
Expand Down
12 changes: 11 additions & 1 deletion src/cc/backend/emit_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,10 @@ static void emit_varinfo(const VarInfo *varinfo, const Initializer *init) {
_RODATA();
else
_DATA();
} else {
if (!cc_flags.common) {
_BSS();
}
}

char *label = fmt_name(name);
Expand All @@ -268,7 +272,13 @@ static void emit_varinfo(const VarInfo *varinfo, const Initializer *init) {
size = 1;

size_t align = align_size(varinfo->type);
_COMM(label, size, align);
if (cc_flags.common) {
_COMM(label, size, align);
} else {
EMIT_ALIGN(align_size(varinfo->type));
EMIT_LABEL(label);
_ZERO(num(size));
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/cc/backend/emit_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ bool function_not_returned(FuncBackend *fnbe);
#define _SECTION(x) EMIT_ASM(".section", x)
#define _TEXT() EMIT_ASM(".text")
#define _DATA() EMIT_ASM(".data")
#define _BSS() EMIT_ASM(".bss")
#define _ZERO(x) EMIT_ASM(".zero", x)

#define EMIT_ALIGN(x) emit_align_p2(x)

Expand Down
42 changes: 39 additions & 3 deletions src/cc/cc1.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,40 @@ static void compile1(FILE *ifp, const char *filename, Vector *decls) {
parse(decls);
}

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;
}

int main(int argc, char *argv[]) {
enum {
OPT_WARNING = 128,
OPT_FNO = 128,
};

static const struct option options[] = {
{"W", required_argument, OPT_WARNING},
{"-version", no_argument, 'V'},

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

{NULL},
};
int opt;
Expand All @@ -61,14 +87,24 @@ int main(int argc, char *argv[]) {
case 'V':
show_version("cc1");
return 0;
case OPT_WARNING:

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;

default:
fprintf(stderr, "Warning: unknown option: %s\n", argv[optind - 1]);
break;
Expand Down
1 change: 1 addition & 0 deletions src/cc/frontend/fe_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ int compile_error_count;

CcFlags cc_flags = {
.warn_as_error = false,
.common = false,
};

LoopScope loop_scope;
Expand Down
1 change: 1 addition & 0 deletions src/cc/frontend/fe_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum ParseErrorLevel {

typedef struct {
bool warn_as_error; // Treat warnings as errors
bool common;
} CcFlags;

extern CcFlags cc_flags;
Expand Down
Loading

0 comments on commit 3f656aa

Please sign in to comment.