Skip to content

Commit

Permalink
Verify LLVM module before writing, and add new flag to disable it (fo…
Browse files Browse the repository at this point in the history
…r debugging)
  • Loading branch information
dosisod committed Jan 2, 2022
1 parent 656c08e commit c185a69
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 14 deletions.
1 change: 1 addition & 0 deletions skull/build_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ typedef struct {
_Bool optimize1;
_Bool optimize2;
_Bool optimize3;
_Bool llvm_no_verify;
} BuildData;

extern BuildData BUILD_DATA;
3 changes: 3 additions & 0 deletions skull/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ static bool parse_long_option(const char *arg) {
else if (strcmp(arg, "werror") == 0) {
set_bool_flag(&BUILD_DATA.werror, "--werror");
}
else if (strcmp(arg, "llvm-no-verify") == 0) {
set_bool_flag(&BUILD_DATA.llvm_no_verify, "--llvm-no-verify");
}
else {
fprintf(stderr, "skull: unknown option \"--%s\"\n", arg);
return true;
Expand Down
4 changes: 2 additions & 2 deletions skull/codegen/llvm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ static Expr gen_node(const AstNode **node) {
case AST_NODE_EXPR:
gen_expr_func_call((*node)->expr->lhs.func_call); break;
case AST_NODE_NOOP: gen_stmt_noop(&(*node)->token->location); break;
case AST_NODE_BREAK: gen_stmt_break(); break;
case AST_NODE_CONTINUE: gen_stmt_continue(); break;
case AST_NODE_BREAK: return gen_stmt_break();
case AST_NODE_CONTINUE: return gen_stmt_continue();
default: break;
}

Expand Down
20 changes: 16 additions & 4 deletions skull/codegen/llvm/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,24 @@ static void gen_control_if_(
LLVMPositionBuilderAtEnd(SKULL_STATE_LLVM.builder, end);
}

void gen_stmt_break(void) {
LLVMBuildBr(SKULL_STATE_LLVM.builder, SKULL_STATE_LLVM.current_while_end);
Expr gen_stmt_break(void) {
return (Expr){
.value = LLVMBuildBr(
SKULL_STATE_LLVM.builder,
SKULL_STATE_LLVM.current_while_end
),
.type = TYPE_VOID
};
}

void gen_stmt_continue(void) {
LLVMBuildBr(SKULL_STATE_LLVM.builder, SKULL_STATE_LLVM.current_while_cond);
Expr gen_stmt_continue(void) {
return (Expr){
.value = LLVMBuildBr(
SKULL_STATE_LLVM.builder,
SKULL_STATE_LLVM.current_while_cond
),
.type = TYPE_VOID
};
}

/*
Expand Down
4 changes: 2 additions & 2 deletions skull/codegen/llvm/flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ typedef struct Location Location;

Expr gen_stmt_return(const AstNode *);
Expr gen_stmt_unreachable(void);
Expr gen_stmt_break(void);
Expr gen_stmt_continue(void);
void gen_stmt_implicit_main_return(const Location *);
void gen_stmt_noop(const Location *);
void gen_stmt_break(void);
void gen_stmt_continue(void);
void gen_control_while(const AstNode *);
void gen_control_if(const AstNode **);
26 changes: 24 additions & 2 deletions skull/codegen/llvm/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <sys/wait.h>
#include <unistd.h>

#include <llvm-c/Analysis.h>
#include <llvm-c/Core.h>
#include <llvm-c/DebugInfo.h>
#include <llvm-c/Target.h>
Expand All @@ -21,6 +22,7 @@
#include "skull/common/str.h"

static bool create_ll_file(const char *);
static bool verify_llvm(void);
static bool optimize_llvm(void);
static int run_llc(void);
static int run_cc(char *);
Expand All @@ -34,6 +36,10 @@ static int check_directory(char *);
Write LLVM code to `filename`, return whether error occured.
*/
bool write_file_llvm(const char *filename) {
if (BUILD_DATA.debug) LLVMDIBuilderFinalize(DEBUG_INFO.builder);

if (!BUILD_DATA.llvm_no_verify && verify_llvm()) return true;

if (BUILD_DATA.optimize1 || BUILD_DATA.optimize2 || BUILD_DATA.optimize3) {
if (optimize_llvm()) return true;
}
Expand All @@ -51,6 +57,24 @@ bool write_file_llvm(const char *filename) {
return err || run_cc(binary_name);
}

static bool verify_llvm(void) {
char *err_msg = NULL;

const bool err = LLVMVerifyModule(
SKULL_STATE_LLVM.module,
LLVMReturnStatusAction,
&err_msg
);

if (err) {
fprintf(stderr, "skull: error while verifying LLVM: %s\n", err_msg);
}

LLVMDisposeMessage(err_msg);

return err;
}

static bool optimize_llvm(void) {
LLVMInitializeAllTargetInfos();

Expand Down Expand Up @@ -100,8 +124,6 @@ static bool optimize_llvm(void) {
}

static bool create_ll_file(const char *filename) {
if (BUILD_DATA.debug) LLVMDIBuilderFinalize(DEBUG_INFO.builder);

if (strcmp(filename, "-") == 0) {
char *msg = LLVMPrintModuleToString(SKULL_STATE_LLVM.module);
printf("%s", msg);
Expand Down
3 changes: 1 addition & 2 deletions test/sh/flow/break.sk.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ define i64 @.break() {
entry:
br label %while_cond

while_cond: ; preds = %while_loop, %entry
while_cond: ; preds = %entry
br i1 true, label %while_loop, label %while_end

while_loop: ; preds = %while_cond
br label %while_end
br label %while_cond

while_end: ; preds = %while_loop, %while_cond
ret i64 0
Expand Down
3 changes: 1 addition & 2 deletions test/sh/flow/continue.sk.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ define i64 @.continue() {
entry:
br label %while_cond

while_cond: ; preds = %while_loop, %while_loop, %entry
while_cond: ; preds = %while_loop, %entry
br i1 true, label %while_loop, label %while_end

while_loop: ; preds = %while_cond
br label %while_cond
br label %while_cond

while_end: ; preds = %while_cond
ret i64 0
Expand Down
1 change: 1 addition & 0 deletions test/sh/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ test_skull "duplicate_arg.sh -O2" "-O2 -O2"
test_skull "duplicate_arg.sh -O3" "-O3 -O3"
test_skull "duplicate_arg.sh --c-backend" "--c-backend --c-backend"
test_skull "duplicate_arg.sh --werror" "--werror --werror"
test_skull "duplicate_arg.sh --llvm-no-verify" "--llvm-no-verify --llvm-no-verify"
test_skull "warn_dash_dash_no_args.sh" "--"
test_skull "dash_o_expect_filename.sh" "-o"
test_skull "dash_o_no_binary.sh" "./test/sh/skull/dummy.sk -o -"
Expand Down

0 comments on commit c185a69

Please sign in to comment.