Skip to content

Commit

Permalink
Specify label type in assembler
Browse files Browse the repository at this point in the history
```
.type main, @function
.type var, @object
```
  • Loading branch information
tyfkda committed Mar 17, 2024
1 parent 009b5c3 commit ce82cdf
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 11 deletions.
2 changes: 2 additions & 0 deletions include/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ typedef struct {
#define STB_GLOBAL (1)

#define STT_NOTYPE (0)
#define STT_OBJECT (1)
#define STT_FUNC (2)
#define STT_SECTION (3)

#define ELF64_ST_BIND(info) ((info) >> 4)
Expand Down
8 changes: 7 additions & 1 deletion src/as/as.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,13 @@ static int output_obj(const char *ofn, Table *label_table, Vector *unresolved) {
if (!(info->flag & LF_GLOBAL) || !(info->flag & LF_DEFINED))
continue;
sym = symtab_add(&symtab, name);
sym->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE);
int type;
switch (info->kind) {
case LK_NONE: type = STT_NOTYPE; break;
case LK_FUNC: type = STT_FUNC; break;
case LK_OBJECT: type = STT_OBJECT; break;
}
sym->st_info = ELF64_ST_INFO(STB_GLOBAL, type);
sym->st_value = info->address - section_start_addresses[info->section];
sym->st_shndx = info->section + 1; // Symbol index for Local section.
}
Expand Down
1 change: 1 addition & 0 deletions src/as/inst.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ enum DirectiveType {
DT_DATA,
DT_ALIGN,
DT_P2ALIGN,
DT_TYPE,
DT_BYTE,
DT_SHORT,
DT_LONG,
Expand Down
7 changes: 4 additions & 3 deletions src/as/ir_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ static LabelInfo *new_label(int section, uintptr_t address) {
info->section = section;
info->flag = 0;
info->address = address;
info->kind = LK_NONE;
return info;
}

bool add_label_table(Table *label_table, const Name *label, int section, bool define, bool global) {
LabelInfo *add_label_table(Table *label_table, const Name *label, int section, bool define, bool global) {
LabelInfo *info = table_get(label_table, label);
if (info != NULL) {
if (define) {
if ((info->flag & LF_DEFINED) != 0) {
fprintf(stderr, "`%.*s' already defined\n", NAMES(label));
return false;
return NULL;
}
info->address = 1;
info->section = section;
Expand All @@ -42,7 +43,7 @@ bool add_label_table(Table *label_table, const Name *label, int section, bool de
info->flag |= LF_DEFINED;
if (global)
info->flag |= LF_GLOBAL;
return true;
return info;
}

IR *new_ir_label(const Name *label) {
Expand Down
9 changes: 8 additions & 1 deletion src/as/ir_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ typedef struct Vector Vector;
#define LF_GLOBAL (1 << 0)
#define LF_DEFINED (1 << 1)

enum LabelKind {
LK_NONE,
LK_FUNC,
LK_OBJECT,
};

typedef struct {
int section;
int flag;
uintptr_t address;
enum LabelKind kind;
} LabelInfo;

bool add_label_table(Table *label_table, const Name *label, int section, bool define, bool global);
LabelInfo *add_label_table(Table *label_table, const Name *label, int section, bool define, bool global);

enum UnresolvedKind {
UNRES_EXTERN,
Expand Down
55 changes: 50 additions & 5 deletions src/as/parse_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ static const char *kDirectiveTable[] = {
"data",
"align",
"p2align",
"type",
"byte",
"short",
"long",
Expand Down Expand Up @@ -403,13 +404,28 @@ static const Name *parse_label(ParseInfo *info) {
return alloc_name(start + 1, p - 1, false);
}

if (!is_label_first_chr(*p))
unsigned char *q = (unsigned char*)p;
int uc = *q;
int ucc = isutf8first(uc) - 1;
if (!(ucc > 0 || is_label_first_chr(uc)))
return NULL;

do {
++p;
} while (is_label_chr(*p));
info->p = p;
for (;;) {
uc = *++q;
if (ucc > 0) {
if (!isutf8follow(uc)) {
parse_error(info, "Illegal byte sequence");
return NULL;
}
--ucc;
continue;
}
if ((ucc = isutf8first(uc) - 1) > 0)
continue;
if (!is_label_chr(uc))
break;
}
info->p = p = (char*)q;
return alloc_name(start, p, false);
}

Expand Down Expand Up @@ -1106,6 +1122,35 @@ void handle_directive(ParseInfo *info, enum DirectiveType dir, Vector **section_
}
break;

case DT_TYPE:
{
const Name *label = parse_label(info);
if (label == NULL) {
parse_error(info, ".comm: label expected");
break;
}
if (*info->p != ',') {
parse_error(info, ".comm: `,' expected");
break;
}
info->p = skip_whitespaces(info->p + 1);
enum LabelKind kind = LK_NONE;
if (strcmp(info->p, "@function") == 0) {
kind = LK_FUNC;
} else if (strcmp(info->p, "@object") == 0) {
kind = LK_OBJECT;
} else {
parse_error(info, "illegal .type");
break;
}

LabelInfo *info = add_label_table(label_table, label, current_section, false, false);
if (info != NULL) {
info->kind = kind;
}
}
break;

case DT_BYTE:
case DT_SHORT:
case DT_LONG:
Expand Down
3 changes: 3 additions & 0 deletions src/cc/arch/aarch64/emit_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ static void emit_defun(Function *func) {
_LOCAL(label);
}
EMIT_ALIGN(4);
#if XCC_TARGET_PLATFORM != XCC_PLATFORM_APPLE
EMIT_ASM(".type", fmt("%.*s", NAMES(func->name)), "@function");
#endif
EMIT_LABEL(label);

bool no_stmt = true;
Expand Down
3 changes: 3 additions & 0 deletions src/cc/arch/riscv64/emit_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ static void emit_defun(Function *func) {
_LOCAL(label);
}
EMIT_ALIGN(2);
#if XCC_TARGET_PLATFORM != XCC_PLATFORM_APPLE
EMIT_ASM(".type", fmt("%.*s", NAMES(func->name)), "@function");
#endif
EMIT_LABEL(label);

bool no_stmt = true;
Expand Down
3 changes: 3 additions & 0 deletions src/cc/arch/x64/emit_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ static void emit_defun(Function *func) {
label = quote_label(label);
_LOCAL(label);
}
#if XCC_TARGET_PLATFORM != XCC_PLATFORM_APPLE
EMIT_ASM(".type", fmt("%.*s", NAMES(func->name)), "@function");
#endif
EMIT_LABEL(label);

bool no_stmt = true;
Expand Down
3 changes: 3 additions & 0 deletions src/cc/backend/emit_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ void emit_varinfo(const VarInfo *varinfo, const Initializer *init) {
label = quote_label(label);
_LOCAL(label);
}
#if XCC_TARGET_PLATFORM != XCC_PLATFORM_APPLE
EMIT_ASM(".type", fmt("%.*s", NAMES(name)), "@object");
#endif

if (init != NULL) {
EMIT_ALIGN(align_size(varinfo->type));
Expand Down
2 changes: 1 addition & 1 deletion src/ld/elfobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ static bool load_symtab(ElfObj *elfobj) {
for (uint32_t i = 0; i < count; ++i) {
Elf64_Sym *sym = &symbols[i];
unsigned char type = ELF64_ST_TYPE(sym->st_info);
if (type == STT_NOTYPE && str[sym->st_name] != '\0') {
if (type != STT_SECTION && str[sym->st_name] != '\0') {
const Name *name = alloc_name(&str[sym->st_name], NULL, false);
table_put(symbol_table, name, sym);
}
Expand Down

0 comments on commit ce82cdf

Please sign in to comment.