aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/ast.h3
-rw-r--r--src/cli.c4
-rw-r--r--src/cli.h1
-rw-r--r--src/codegen.c8
-rw-r--r--src/codegen.h2
-rw-r--r--src/main.c2
-rw-r--r--src/parse.c73
7 files changed, 76 insertions, 17 deletions
diff --git a/src/ast.h b/src/ast.h
index 0749420..f1405c6 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -2,6 +2,7 @@
#define DUCC_AST_H
#include "ducc.h"
+#include "io.h"
typedef enum {
StorageClass_unspecified,
@@ -328,6 +329,8 @@ typedef struct {
struct AstNode {
AstNodeKind kind;
+ // TODO: currently only limited set of ast nodes have loc field.
+ SourceLocation loc;
Type* ty;
union {
IntExprNode* int_expr;
diff --git a/src/cli.c b/src/cli.c
index b14bf08..b890375 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -17,6 +17,7 @@ CliArgs* parse_cli_args(int argc, char** argv) {
bool opt_wasm = false;
bool opt_MD = false;
bool opt_MMD = false;
+ bool opt_g = false;
StrArray include_dirs;
strings_init(&include_dirs);
StrArray defines;
@@ -76,6 +77,8 @@ CliArgs* parse_cli_args(int argc, char** argv) {
opt_c = true;
} else if (c == 'E') {
opt_E = true;
+ } else if (c == 'g') {
+ opt_g = true;
} else if (strcmp(argv[i], "-MD") == 0) {
opt_MD = true;
} else if (strcmp(argv[i], "-MMD") == 0) {
@@ -106,6 +109,7 @@ CliArgs* parse_cli_args(int argc, char** argv) {
a->gcc_command = NULL;
a->generate_system_deps = opt_MD;
a->generate_user_deps = opt_MD || opt_MMD;
+ a->generate_debug_info = opt_g;
a->include_dirs = include_dirs;
a->defines = defines;
diff --git a/src/cli.h b/src/cli.h
index f4a610a..7691323 100644
--- a/src/cli.h
+++ b/src/cli.h
@@ -11,6 +11,7 @@ typedef struct {
bool preprocess_only;
bool generate_system_deps;
bool generate_user_deps;
+ bool generate_debug_info;
bool totally_deligate_to_gcc;
bool wasm;
const char* gcc_command;
diff --git a/src/codegen.c b/src/codegen.c
index bc1e3d3..7f85fbd 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -777,6 +777,9 @@ static void codegen_block_stmt(CodeGen* g, AstNode* ast) {
}
static void codegen_stmt(CodeGen* g, AstNode* ast) {
+ // TODO: support multiple files.
+ fprintf(g->out, " .loc 1 %d 0\n", ast->loc.line);
+
if (ast->kind == AstNodeKind_list) {
codegen_block_stmt(g, ast);
} else if (ast->kind == AstNodeKind_return_stmt) {
@@ -864,11 +867,14 @@ static void codegen_global_var(CodeGen* g, AstNode* var) {
}
}
-void codegen(Program* prog, FILE* out) {
+void codegen(Program* prog, const char* input_filename, FILE* out) {
CodeGen* g = codegen_new(prog, out);
fprintf(g->out, ".intel_syntax noprefix\n\n");
+ // TODO: support multiple files.
+ fprintf(g->out, ".file 1 \"%s\"\n\n", input_filename);
+
// For GNU ld:
// https://sourceware.org/binutils/docs/ld/Options.html
fprintf(g->out, ".section .note.GNU-stack,\"\",@progbits\n\n");
diff --git a/src/codegen.h b/src/codegen.h
index 95ec069..2c1d7b3 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -3,6 +3,6 @@
#include "ast.h"
-void codegen(Program* prog, FILE* out);
+void codegen(Program* prog, const char* input_filename, FILE* out);
#endif
diff --git a/src/main.c b/src/main.c
index 51e2200..b2ff9fb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -50,7 +50,7 @@ int main(int argc, char** argv) {
if (cli_args->wasm) {
codegen_wasm(prog, assembly_file);
} else {
- codegen(prog, assembly_file);
+ codegen(prog, cli_args->input_filename, assembly_file);
}
fclose(assembly_file);
diff --git a/src/parse.c b/src/parse.c
index 5601ee8..12d4fbf 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -182,6 +182,10 @@ static Token* peek_token2(Parser* p) {
return &p->tokens->data[p->pos + 1];
}
+static SourceLocation current_location(Parser* p) {
+ return peek_token(p)->loc;
+}
+
static Token* next_token(Parser* p) {
return &p->tokens->data[p->pos++];
}
@@ -2417,8 +2421,10 @@ static AstNode* parse_unlabaled_stmt(Parser* p) {
// TODO attribute-specifier-sequence? 'case' constant-expr ':'
// TODO attribute-specifier-sequence? 'default' ':'
static AstNode* parse_label(Parser* p) {
+ SourceLocation loc = current_location(p);
Token* t = peek_token(p);
+ AstNode* node;
if (t->kind == TokenKind_keyword_case) {
if (!p->current_switch) {
fatal_error("%s:%d: 'case' label not within a switch statement", t->loc.filename, t->loc.line);
@@ -2426,20 +2432,22 @@ static AstNode* parse_label(Parser* p) {
expect(p, TokenKind_keyword_case);
AstNode* value = parse_constant_expr(p);
expect(p, TokenKind_colon);
- return ast_new_case_label(eval(value), ast_new_nop());
+ node = ast_new_case_label(eval(value), ast_new_nop());
} else if (t->kind == TokenKind_keyword_default) {
if (!p->current_switch) {
fatal_error("%s:%d: 'default' label not within a switch statement", t->loc.filename, t->loc.line);
}
expect(p, TokenKind_keyword_default);
expect(p, TokenKind_colon);
- return ast_new_default_label(ast_new_nop());
+ node = ast_new_default_label(ast_new_nop());
} else {
// identifier ':'
Token* label_token = expect(p, TokenKind_ident);
expect(p, TokenKind_colon);
- return ast_new_label_stmt(label_token->value.string, ast_new_nop());
+ node = ast_new_label_stmt(label_token->value.string, ast_new_nop());
}
+ node->loc = loc;
+ return node;
}
static bool is_label_token(Parser* p) {
@@ -2477,6 +2485,7 @@ static AstNode* parse_stmt(Parser* p) {
// compound-stmt:
// '{' { block-item }* '}'
static AstNode* parse_compound_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
AstNode* list = ast_new_list(4);
expect(p, TokenKind_brace_l);
enter_scope(p);
@@ -2486,6 +2495,7 @@ static AstNode* parse_compound_stmt(Parser* p) {
}
leave_scope(p);
expect(p, TokenKind_brace_r);
+ list->loc = loc;
return list;
}
@@ -2508,18 +2518,24 @@ static AstNode* parse_block_item(Parser* p) {
// expr-stmt:
// TODO attribute-specifier-sequence? expr? ';'
static AstNode* parse_expr_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
if (consume_token_if(p, TokenKind_semicolon)) {
- return ast_new_nop();
+ AstNode* node = ast_new_nop();
+ node->loc = loc;
+ return node;
}
AstNode* e = parse_expr(p);
expect(p, TokenKind_semicolon);
- return ast_new_expr_stmt(e);
+ AstNode* node = ast_new_expr_stmt(e);
+ node->loc = loc;
+ return node;
}
// if-stmt:
// 'if' '(' expr ')' stmt ( 'else' stmt )?
static AstNode* parse_if_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
expect(p, TokenKind_keyword_if);
expect(p, TokenKind_paren_l);
AstNode* cond = parse_expr(p);
@@ -2530,12 +2546,15 @@ static AstNode* parse_if_stmt(Parser* p) {
else_body = parse_stmt(p);
}
- return ast_new_if_stmt(cond, then_body, else_body);
+ AstNode* node = ast_new_if_stmt(cond, then_body, else_body);
+ node->loc = loc;
+ return node;
}
// switch-stmt:
// 'switch' '(' expr ')' stmt
static AstNode* parse_switch_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
expect(p, TokenKind_keyword_switch);
expect(p, TokenKind_paren_l);
AstNode* expr = parse_expr(p);
@@ -2544,8 +2563,10 @@ static AstNode* parse_switch_stmt(Parser* p) {
AstNode* tmp_var = generate_temporary_lvar(p, expr->ty);
AstNode* assignment = ast_new_assign_expr(TokenKind_assign, tmp_var, expr);
AstNode* assign_stmt = ast_new_expr_stmt(assignment);
+ assign_stmt->loc = loc;
AstNode* switch_stmt = ast_new_switch_stmt(tmp_var);
+ switch_stmt->loc = loc;
AstNode* prev_switch = p->current_switch;
p->current_switch = switch_stmt;
@@ -2553,6 +2574,7 @@ static AstNode* parse_switch_stmt(Parser* p) {
p->current_switch = prev_switch;
AstNode* list = ast_new_list(2);
+ list->loc = loc;
ast_append(list, assign_stmt);
ast_append(list, switch_stmt);
return list;
@@ -2561,17 +2583,21 @@ static AstNode* parse_switch_stmt(Parser* p) {
// while-stmt:
// 'while' '(' expr ')' stmt
static AstNode* parse_while_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
expect(p, TokenKind_keyword_while);
expect(p, TokenKind_paren_l);
AstNode* cond = parse_expr(p);
expect(p, TokenKind_paren_r);
AstNode* body = parse_stmt(p);
- return ast_new_for_stmt(NULL, cond, NULL, body);
+ AstNode* node = ast_new_for_stmt(NULL, cond, NULL, body);
+ node->loc = loc;
+ return node;
}
// do-while-stmt:
// 'do' stmt 'while' '(' expr ')' ';'
static AstNode* parse_do_while_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
expect(p, TokenKind_keyword_do);
AstNode* body = parse_stmt(p);
expect(p, TokenKind_keyword_while);
@@ -2580,13 +2606,16 @@ static AstNode* parse_do_while_stmt(Parser* p) {
expect(p, TokenKind_paren_r);
expect(p, TokenKind_semicolon);
- return ast_new_do_while_stmt(cond, body);
+ AstNode* node = ast_new_do_while_stmt(cond, body);
+ node->loc = loc;
+ return node;
}
// for-stmt:
// 'for' '(' expr? ';' expr? ';' expr? ')' stmt
// 'for' '(' declaration expr? ';' expr? ')' stmt
static AstNode* parse_for_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
expect(p, TokenKind_keyword_for);
expect(p, TokenKind_paren_l);
AstNode* init = NULL;
@@ -2623,45 +2652,61 @@ static AstNode* parse_for_stmt(Parser* p) {
expect(p, TokenKind_paren_r);
AstNode* body = parse_stmt(p);
leave_scope(p);
- return ast_new_for_stmt(init, cond, update, body);
+ AstNode* node = ast_new_for_stmt(init, cond, update, body);
+ node->loc = loc;
+ return node;
}
// goto-stmt:
// 'goto' identifier ';'
static AstNode* parse_goto_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
expect(p, TokenKind_keyword_goto);
Token* label_token = expect(p, TokenKind_ident);
expect(p, TokenKind_semicolon);
- return ast_new_goto_stmt(label_token->value.string);
+ AstNode* node = ast_new_goto_stmt(label_token->value.string);
+ node->loc = loc;
+ return node;
}
// continue-stmt:
// 'continue' ';'
static AstNode* parse_continue_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
expect(p, TokenKind_keyword_continue);
expect(p, TokenKind_semicolon);
- return ast_new_continue_stmt();
+ AstNode* node = ast_new_continue_stmt();
+ node->loc = loc;
+ return node;
}
// break-stmt:
// 'break' ';'
static AstNode* parse_break_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
expect(p, TokenKind_keyword_break);
expect(p, TokenKind_semicolon);
- return ast_new_break_stmt();
+ AstNode* node = ast_new_break_stmt();
+ node->loc = loc;
+ return node;
}
// return-stmt:
// 'return' expr? ';'
static AstNode* parse_return_stmt(Parser* p) {
+ SourceLocation loc = current_location(p);
expect(p, TokenKind_keyword_return);
if (consume_token_if(p, TokenKind_semicolon)) {
- return ast_new_return_stmt(NULL);
+ AstNode* node = ast_new_return_stmt(NULL);
+ node->loc = loc;
+ return node;
}
AstNode* expr = parse_expr(p);
expect(p, TokenKind_semicolon);
- return ast_new_return_stmt(expr);
+ AstNode* node = ast_new_return_stmt(expr);
+ node->loc = loc;
+ return node;
}
// static_assert-declaration: