diff --git a/src/backends/llvm/llvm.c b/src/backends/llvm/llvm.c index 1e673b67f3954360ede0f8aae1fbd205fd97f1f1..356b279b2754772921ae9e449c6848d3b792a2b4 100644 --- a/src/backends/llvm/llvm.c +++ b/src/backends/llvm/llvm.c @@ -106,9 +106,30 @@ void h_llvm_declare_common(HLLVMParserCompileContext *ctxt) { } int h_llvm_compile(HAllocator* mm__, HParser* parser, const void* params) { + /* Globals for the LLVM build process */ HLLVMParserCompileContext *ctxt; - // Boilerplate to set up a translation unit, aka a module. - const char* name = params ? (const char*)params : "parse"; + /* Return result from the top-level parser */ + LLVMValueRef res; + /* Execution engine, eventually */ + LLVMExecutionEngineRef engine = NULL; + /* LLVM error message, if any */ + char *error = NULL; + /* LLVM IR dump, if any */ + char *dump = NULL; + /* Finished LLVM parser, eventually */ + HLLVMParser *llvm_parser = NULL; + /* LLVM parse function return type */ + LLVMTypeRef ret_type; + /* Preamble and postamble blocks */ + LLVMBasicBlockRef preamble, postamble; + char *preamble_name = NULL, *postamble_name = NULL; + int preamble_name_len = 0, postamble_name_len = 0; + /* Boilerplate to set up a translation unit, aka a module. */ + const char *name = params ? (const char*)params : "parse"; + /* Types of parameters to use in the function declaration */ + LLVMTypeRef parser_param_types[2]; + /* Return value */ + int rv; /* Build a parser compilation context */ ctxt = h_new(HLLVMParserCompileContext, 1); @@ -117,18 +138,27 @@ int h_llvm_compile(HAllocator* mm__, HParser* parser, const void* params) { ctxt->mod = LLVMModuleCreateWithName(name); h_llvm_declare_common(ctxt); - // Boilerplate to set up the parser function to add to the module. It takes an HInputStream* and - // returns an HParseResult. - LLVMTypeRef param_types[] = { - ctxt->llvm_inputstreamptr, - ctxt->llvm_arenaptr - }; - LLVMTypeRef ret_type = LLVMFunctionType(ctxt->llvm_parseresultptr, param_types, 2, 0); + /* + * Boilerplate to set up the parser function to add to the module. It + * takes an HInputStream* and returns an HParseResult. + */ + parser_param_types[0] = ctxt->llvm_inputstreamptr; + parser_param_types[1] = ctxt->llvm_arenaptr; + ret_type = LLVMFunctionType(ctxt->llvm_parseresultptr, + parser_param_types, 2, 0); ctxt->func = LLVMAddFunction(ctxt->mod, name, ret_type); - // Parse function is now declared; time to define it + /* Parse function is now declared; time to define it */ ctxt->builder = LLVMCreateBuilder(); - LLVMBasicBlockRef preamble = LLVMAppendBasicBlock(ctxt->func, "preamble"); + /* + * In case we need to build more for internal parsers, we use the address + * of the HParser for forming names. + */ + preamble_name_len = snprintf(NULL, 0, "preamble_%p", (void *)parser); + preamble_name = h_new(char, preamble_name_len + 1); + snprintf(preamble_name, preamble_name_len + 1, "preamble_%p", + (void *)parser); + preamble = LLVMAppendBasicBlock(ctxt->func, preamble_name); LLVMPositionBuilderAtEnd(ctxt->builder, preamble); /* @@ -144,38 +174,72 @@ int h_llvm_compile(HAllocator* mm__, HParser* parser, const void* params) { ctxt->llvm_inputstreamptr, "stream"); ctxt->arena = LLVMGetLastParam(ctxt->func); - // Translate the contents of the children of `parser` into their LLVM instruction equivalents - if (parser->vtable->llvm(ctxt, parser->env)) { - // But first, verification - char *error = NULL; + /* + * Translate the contents of the children of `parser` into their LLVM + * instruction equivalents + */ + if (parser->vtable->llvm(ctxt, parser->env, &res)) { + /* Okay, we got it - set up a postamble basic block */ + postamble_name_len = snprintf(NULL, 0, "postamble_%p", (void *)parser); + postamble_name = h_new(char, postamble_name_len + 1); + snprintf(postamble_name, postamble_name_len + 1, "postamble_%p", + (void *)parser); + postamble = LLVMAppendBasicBlock(ctxt->func, postamble_name); + /* Branch from last basic block in the parser to the postamble */ + LLVMBuildBr(ctxt->builder, postamble); + LLVMPositionBuilderAtEnd(ctxt->builder, postamble); + /* ...and return the result, since this is the top level */ + LLVMBuildRet(ctxt->builder, res); + /* Finished building the Big Damn Function, now we compile the module */ + + /* First, verification */ LLVMVerifyModule(ctxt->mod, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); error = NULL; - // OK, link that sonofabitch + /* OK, link that sonofabitch */ LLVMLinkInMCJIT(); LLVMInitializeNativeTarget(); LLVMInitializeNativeAsmPrinter(); - LLVMExecutionEngineRef engine = NULL; LLVMCreateExecutionEngineForModule(&engine, ctxt->mod, &error); - if (error) { + + if (!error) { + /* Do IR dump */ + dump = LLVMPrintModuleToString(ctxt->mod); + fprintf(stderr, "\n\n%s\n\n", dump); + /* + * Package up the pointers that comprise the module and stash it in + * the original HParser + */ + llvm_parser = h_new(HLLVMParser, 1); + llvm_parser->mod = ctxt->mod; + llvm_parser->func = ctxt->func; + llvm_parser->engine = engine; + llvm_parser->builder = ctxt->builder; + llvm_parser->compile_ctxt = ctxt; + parser->backend_data = llvm_parser; + /* Sweet lemony-fresh victory is mine! */ + rv = 0; + } else { fprintf(stderr, "error: %s\n", error); LLVMDisposeMessage(error); - return -1; + rv = -1; } - char* dump = LLVMPrintModuleToString(ctxt->mod); - fprintf(stderr, "\n\n%s\n\n", dump); - // Package up the pointers that comprise the module and stash it in the original HParser - HLLVMParser *llvm_parser = h_new(HLLVMParser, 1); - llvm_parser->mod = ctxt->mod; - llvm_parser->func = ctxt->func; - llvm_parser->engine = engine; - llvm_parser->builder = ctxt->builder; - llvm_parser->compile_ctxt = ctxt; - parser->backend_data = llvm_parser; - return 0; } else { - return -1; + rv = -1; + } + + /* Cleanup */ + if (preamble_name) { + h_free(preamble_name); + preamble_name = NULL; + } + + if (postamble_name) { + h_free(postamble_name); + postamble_name = NULL; } + + return rv; } void h_llvm_free(HParser *parser) { diff --git a/src/internal.h b/src/internal.h index 9a9b0214f62705ce71b84ce0d6f620a1bd587bbf..7646e3a6576ae73d9d54b74f02f38f5253a2ed7f 100644 --- a/src/internal.h +++ b/src/internal.h @@ -505,7 +505,7 @@ struct HParserVtable_ { bool (*compile_to_rvm)(HRVMProg *prog, void* env); // FIXME: forgot what the bool return value was supposed to mean. void (*desugar)(HAllocator *mm__, HCFStack *stk__, void *env); #ifdef HAMMER_LLVM_BACKEND - bool (*llvm)(HLLVMParserCompileContext *ctxt, void *env); + bool (*llvm)(HLLVMParserCompileContext *ctxt, void *env, LLVMValueRef *result); #endif bool higher; // false if primitive }; diff --git a/src/parsers/bits.c b/src/parsers/bits.c index bd9fa8e064e7431a1b84a3de520ce35fc43fd7f7..f59849fde9d0d4d66e5ebb678fe061a4161f4633 100644 --- a/src/parsers/bits.c +++ b/src/parsers/bits.c @@ -26,9 +26,12 @@ static HParseResult* parse_bits(void* env, HParseState *state) { #ifdef HAMMER_LLVM_BACKEND -static bool bits_llvm(HLLVMParserCompileContext *ctxt, void* env) { +static bool bits_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { /* Emit LLVM IR to parse ((struct bits_env *)env)->length bits */ + if (!res) return false; + /* This will get set to non-NULL only when we return true */ + *res = NULL; if (!ctxt) return false; struct bits_env *env_ = env; @@ -57,7 +60,7 @@ static bool bits_llvm(HLLVMParserCompileContext *ctxt, void* env) { h_llvm_make_tt_suint(ctxt, env_->length, env_->signedp, bits, &mr); /* Return mr */ - LLVMBuildRet(ctxt->builder, mr); + *res = mr; return true; } diff --git a/src/parsers/ch.c b/src/parsers/ch.c index e22ed8c105673fd7b989b60e623e83ee9bead050..2db312d6fc45a299261a36be2b2782467382fa11 100644 --- a/src/parsers/ch.c +++ b/src/parsers/ch.c @@ -50,55 +50,75 @@ static bool ch_ctrvm(HRVMProg *prog, void* env) { #ifdef HAMMER_LLVM_BACKEND -static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env) { - // Build a new LLVM function to parse a character +static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { + /* Build a new LLVM function to parse a character */ - // Set up params for calls to h_read_bits() and h_arena_malloc() + if (!res) return false; + if (!ctxt) return false; + + /* Set up params for calls to h_read_bits() and h_arena_malloc() */ LLVMValueRef bits_args[3]; bits_args[0] = ctxt->stream; bits_args[1] = LLVMConstInt(LLVMInt32Type(), 8, 0); bits_args[2] = LLVMConstInt(LLVMInt8Type(), 0, 0); - // Set up basic blocks: entry, success and failure branches, then exit + /* + * Set up basic blocks: entry, success and failure branches, then exit + * + * TODO should these basic block names reflect the particular HParser to + * make the IR dump more comprehensible? + */ LLVMBasicBlockRef entry = LLVMAppendBasicBlock(ctxt->func, "ch_entry"); LLVMBasicBlockRef success = LLVMAppendBasicBlock(ctxt->func, "ch_success"); LLVMBasicBlockRef end = LLVMAppendBasicBlock(ctxt->func, "ch_end"); - // Basic block: entry + /* Basic block: entry */ LLVMBuildBr(ctxt->builder, entry); LLVMPositionBuilderAtEnd(ctxt->builder, entry); - // Call to h_read_bits() - // %read_bits = call i64 @h_read_bits(%struct.HInputStream_* %8, i32 8, i8 signext 0) + /* + * Call to h_read_bits() + * + * %read_bits = call i64 @h_read_bits(%struct.HInputStream_* %8, + * i32 8, i8 signext 0) + */ LLVMValueRef bits = LLVMBuildCall(ctxt->builder, LLVMGetNamedFunction(ctxt->mod, "h_read_bits"), bits_args, 3, "read_bits"); - // %2 = trunc i64 %read_bits to i8 + /* %2 = trunc i64 %read_bits to i8 */ LLVMValueRef r = LLVMBuildTrunc(ctxt->builder, - bits, LLVMInt8Type(), ""); // do we actually need this? + bits, LLVMInt8Type(), ""); - // Check if h_read_bits succeeded - // %"c == r" = icmp eq i8 -94, %2 ; the -94 comes from c_ + /* + * Check if h_read_bits succeeded + * + * %"c == r" = icmp eq i8 -94, %2 ; the -94 comes from c_ + */ uint8_t c_ = (uint8_t)(uintptr_t)(env); LLVMValueRef c = LLVMConstInt(LLVMInt8Type(), c_, 0); LLVMValueRef icmp = LLVMBuildICmp(ctxt->builder, LLVMIntEQ, c, r, "c == r"); - // Branch so success or failure basic block, as appropriate - // br i1 %"c == r", label %ch_success, label %ch_fail + /* + * Branch so success or failure basic block, as appropriate + * br i1 %"c == r", label %ch_success, label %ch_fail + */ LLVMBuildCondBr(ctxt->builder, icmp, success, end); - // Basic block: success + /* Basic block: success */ LLVMPositionBuilderAtEnd(ctxt->builder, success); /* Make a token */ LLVMValueRef mr; h_llvm_make_tt_suint(ctxt, 8, 0, r, &mr); - // br label %ch_end + /* br label %ch_end */ LLVMBuildBr(ctxt->builder, end); - // Basic block: end + /* Basic block: end */ LLVMPositionBuilderAtEnd(ctxt->builder, end); - // %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ], [ null, %ch_entry ] + /* + * %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ], + * [ null, %ch_entry ] + */ LLVMValueRef rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv"); LLVMBasicBlockRef rv_phi_incoming_blocks[] = { success, @@ -109,8 +129,9 @@ static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env) { LLVMConstNull(ctxt->llvm_parseresultptr) }; LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2); - // ret %struct.HParseResult_.3* %rv - LLVMBuildRet(ctxt->builder, rv); + /* Pass rv out to caller */ + *res = rv; + return true; } diff --git a/src/parsers/charset.c b/src/parsers/charset.c index 907fe927a79184c3c292a96630a49fc83fc0b1e3..f77d9e78e9e6736950ea81cd295793ba27f6ad24 100644 --- a/src/parsers/charset.c +++ b/src/parsers/charset.c @@ -79,36 +79,54 @@ static bool cs_ctrvm(HRVMProg *prog, void *env) { #ifdef HAMMER_LLVM_BACKEND -static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env) { +static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { /* * LLVM to build a function to parse a charset; the args are a stream and an * arena. */ - bool ok; + /* Current status */ + bool ok; + /* Our charset (passed in env) */ + HCharset cs; + /* Basic blocks for the charset */ + LLVMBasicBlockRef entry, success, fail, end; + /* Args to h_read_bits() */ + LLVMValueRef bits_args[3]; + /* Result from h_read_bits() */ + LLVMValueRef bits; + /* Cast result from h_read_bits() */ + LLVMValueRef r; + /* Result */ + LLVMValueRef rv; + /* Phis for rv */ + LLVMValueRef rv_phi_incoming_values[2]; + LLVMBasicBlockRef rv_phi_incoming_blocks[2]; + + if (!res) return false; if (!ctxt) return false; /* Set up our basic blocks */ - LLVMBasicBlockRef entry = LLVMAppendBasicBlock(ctxt->func, "cs_entry"); - LLVMBasicBlockRef success = LLVMAppendBasicBlock(ctxt->func, "cs_success"); - LLVMBasicBlockRef fail = LLVMAppendBasicBlock(ctxt->func, "cs_fail"); - LLVMBasicBlockRef end = LLVMAppendBasicBlock(ctxt->func, "cs_end"); + /* TODO should we use distinct names for different HParsers? */ + entry = LLVMAppendBasicBlock(ctxt->func, "cs_entry"); + success = LLVMAppendBasicBlock(ctxt->func, "cs_success"); + fail = LLVMAppendBasicBlock(ctxt->func, "cs_fail"); + end = LLVMAppendBasicBlock(ctxt->func, "cs_end"); /* Basic block: entry */ LLVMBuildBr(ctxt->builder, entry); LLVMPositionBuilderAtEnd(ctxt->builder, entry); /* First we read the char */ - LLVMValueRef bits_args[3]; bits_args[0] = ctxt->stream; bits_args[1] = LLVMConstInt(LLVMInt32Type(), 8, 0); bits_args[2] = LLVMConstInt(LLVMInt8Type(), 0, 0); - LLVMValueRef bits = LLVMBuildCall(ctxt->builder, - LLVMGetNamedFunction(ctxt->mod, "h_read_bits"), bits_args, 3, "read_bits"); - LLVMValueRef r = - LLVMBuildTrunc(ctxt->builder, bits, LLVMInt8Type(), ""); // TODO Necessary? (same question in ch_llvm()) + bits = LLVMBuildCall(ctxt->builder, + LLVMGetNamedFunction(ctxt->mod, "h_read_bits"), + bits_args, 3, "read_bits"); + r = LLVMBuildTrunc(ctxt->builder, bits, LLVMInt8Type(), ""); /* We have a char, need to check if it's in the charset */ - HCharset cs = (HCharset)env; + cs = (HCharset)env; /* Branch to either success or end, conditional on whether r is in cs */ ok = h_llvm_make_charset_membership_test(ctxt, r, cs, success, fail); @@ -132,19 +150,18 @@ static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env) { /* Basic block: end */ LLVMPositionBuilderAtEnd(ctxt->builder, end); - // %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ], [ null, %ch_entry ] - LLVMValueRef rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv"); - LLVMBasicBlockRef rv_phi_incoming_blocks[] = { - success, - fail - }; - LLVMValueRef rv_phi_incoming_values[] = { - mr, - LLVMConstNull(ctxt->llvm_parseresultptr) - }; + /* + * %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ], + * [ null, %ch_entry ] + */ + rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv"); + rv_phi_incoming_blocks[0] = success; + rv_phi_incoming_values[0] = mr; + rv_phi_incoming_blocks[1] = fail; + rv_phi_incoming_values[1] = LLVMConstNull(ctxt->llvm_parseresultptr); LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2); - // ret %struct.HParseResult_.3* %rv - LLVMBuildRet(ctxt->builder, rv); + /* Pass rv back out to caller */ + *res = rv; return ok; } diff --git a/src/parsers/end.c b/src/parsers/end.c index 3643f6c7f109c93dd60d143c2c94c06adc06846f..11dcd33fd152188113bbb2eae10a12ff65cbfb10 100644 --- a/src/parsers/end.c +++ b/src/parsers/end.c @@ -28,13 +28,30 @@ static bool end_ctrvm(HRVMProg *prog, void *env) { #ifdef HAMMER_LLVM_BACKEND -static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) { +static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { + /* Basic blocks for parsing end */ + LLVMBasicBlockRef entry, success, end; + /* Indices for GEP */ + LLVMValueRef gep_indices[2]; + /* Args to make_result() */ + LLVMValueRef make_result_args[2]; + /* Return from make_result() */ + LLVMValueRef result_ptr; + /* Result of this parser */ + LLVMValueRef rv; + /* Incoming basic blocks for phi */ + LLVMBasicBlockRef rv_phi_incoming_blocks[2]; + /* Incoming values for phi */ + LLVMValueRef rv_phi_incoming_values[2]; + + if (!res) return false; if (!ctxt) return false; /* Set up some basic blocks */ - LLVMBasicBlockRef entry = LLVMAppendBasicBlock(ctxt->func, "end_entry"); - LLVMBasicBlockRef success = LLVMAppendBasicBlock(ctxt->func, "end_success"); - LLVMBasicBlockRef end = LLVMAppendBasicBlock(ctxt->func, "end_end"); + /* TODO distinct names for different HParsers? */ + entry = LLVMAppendBasicBlock(ctxt->func, "end_entry"); + success = LLVMAppendBasicBlock(ctxt->func, "end_success"); + end = LLVMAppendBasicBlock(ctxt->func, "end_end"); /* Basic block: entry */ LLVMBuildBr(ctxt->builder, entry); @@ -45,7 +62,7 @@ static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) { * comparing the index and length fields; build a struct GEP to * get at their values. */ - LLVMValueRef gep_indices[2]; + /* The struct itself */ gep_indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0); /* The index field (see HInputStream in internal.h */ @@ -53,16 +70,19 @@ static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) { /* GEP */ LLVMValueRef index_ptr = LLVMBuildGEP(ctxt->builder, ctxt->stream, gep_indices, 2, "index_ptr"); + /* The length field (see HInputStream in internal.h */ gep_indices[1] = LLVMConstInt(LLVMInt32Type(), 3, 0); /* GEP */ LLVMValueRef length_ptr = LLVMBuildGEP(ctxt->builder, ctxt->stream, gep_indices, 2, "length_ptr"); + /* Now load them */ LLVMValueRef index = LLVMBuildLoad(ctxt->builder, index_ptr, "index"); LLVMValueRef length = LLVMBuildLoad(ctxt->builder, length_ptr, "length"); + /* Compare */ LLVMValueRef icmp = LLVMBuildICmp(ctxt->builder, LLVMIntEQ, index, length, "index == length"); /* Branch on comparison */ @@ -71,11 +91,9 @@ static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) { /* Basic block: success */ LLVMPositionBuilderAtEnd(ctxt->builder, success); /* Set up a call to h_arena_malloc() to get an HParseResult */ - LLVMValueRef make_result_args[] = { - ctxt->arena, - LLVMConstNull(ctxt->llvm_parsedtokenptr) - }; - LLVMValueRef result_ptr = LLVMBuildCall(ctxt->builder, + make_result_args[0] = ctxt->arena; + make_result_args[1] = LLVMConstNull(ctxt->llvm_parsedtokenptr); + result_ptr = LLVMBuildCall(ctxt->builder, LLVMGetNamedFunction(ctxt->mod, "make_result"), make_result_args, 2, "result_ptr"); @@ -85,18 +103,14 @@ static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) { /* Basic block: end */ LLVMPositionBuilderAtEnd(ctxt->builder, end); /* Set up a phi depending on whether we have a token or not */ - LLVMValueRef rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv"); - LLVMBasicBlockRef rv_phi_incoming_blocks[] = { - success, - entry - }; - LLVMValueRef rv_phi_incoming_values[] = { - result_ptr, - LLVMConstNull(ctxt->llvm_parseresultptr) - }; + rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv"); + rv_phi_incoming_blocks[0] = success; + rv_phi_incoming_values[0] = result_ptr; + rv_phi_incoming_blocks[1] = entry; + rv_phi_incoming_values[1] = LLVMConstNull(ctxt->llvm_parseresultptr); LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2); - /* Return it */ - LLVMBuildRet(ctxt->builder, rv); + /* Pass it back out to the caller */ + *res = rv; return true; } diff --git a/src/parsers/epsilon.c b/src/parsers/epsilon.c index 4c5abc406a390b3fce592a6b041bca5518ebb0ae..2fd163a98a70772e87a0ebf98b83ca8542bf479f 100644 --- a/src/parsers/epsilon.c +++ b/src/parsers/epsilon.c @@ -21,10 +21,18 @@ static bool epsilon_ctrvm(HRVMProg *prog, void* env) { #ifdef HAMMER_LLVM_BACKEND -static bool epsilon_llvm(HLLVMParserCompileContext *ctxt, void* env) { +static bool epsilon_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { + /* Epsilon basic block */ + LLVMBasicBlockRef epsilon_bb; + /* Args for make_result() */ + LLVMValueRef make_result_args[2]; + /* Return value from make_result() */ + LLVMValueRef result_ptr; + + if (!res) return false; if (!ctxt) return false; - LLVMBasicBlockRef epsilon_bb = LLVMAppendBasicBlock(ctxt->func, "epsilon"); + epsilon_bb = LLVMAppendBasicBlock(ctxt->func, "epsilon"); /* Basic block: epsilon */ LLVMBuildBr(ctxt->builder, epsilon_bb); @@ -34,15 +42,13 @@ static bool epsilon_llvm(HLLVMParserCompileContext *ctxt, void* env) { * For epsilon we make a null-token parse result like with end, but we * do it unconditionally. */ - LLVMValueRef make_result_args[] = { - ctxt->arena, - LLVMConstNull(ctxt->llvm_parsedtokenptr) - }; - LLVMValueRef result_ptr = LLVMBuildCall(ctxt->builder, + make_result_args[0] = ctxt->arena; + make_result_args[1] = LLVMConstNull(ctxt->llvm_parsedtokenptr); + result_ptr = LLVMBuildCall(ctxt->builder, LLVMGetNamedFunction(ctxt->mod, "make_result"), make_result_args, 2, "result_ptr"); - /* Return it */ - LLVMBuildRet(ctxt->builder, result_ptr); + /* Pass it back out */ + *res = result_ptr; return true; } diff --git a/src/parsers/nothing.c b/src/parsers/nothing.c index e4f97fb41cd1993a54941bef1a8ddc4838db9ee0..df9e3f79786fb9275e6dadd479db8a0e3cb611c6 100644 --- a/src/parsers/nothing.c +++ b/src/parsers/nothing.c @@ -27,15 +27,22 @@ static bool nothing_ctrvm(HRVMProg *prog, void* env) { #ifdef HAMMER_LLVM_BACKEND -static bool nothing_llvm(HLLVMParserCompileContext *ctxt, void* env) { +static bool nothing_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { + /* Nothing entry bb */ + LLVMBasicBlockRef entry; + /* Nothing result */ + LLVMValueRef rv; + + if (!res) return false; if (!ctxt) return false; /* This one just always returns NULL */ - LLVMBasicBlockRef entry = LLVMAppendBasicBlock(ctxt->func, "nothing_entry"); + entry = LLVMAppendBasicBlock(ctxt->func, "nothing_entry"); LLVMBuildBr(ctxt->builder, entry); LLVMPositionBuilderAtEnd(ctxt->builder, entry); - - LLVMBuildRet(ctxt->builder, LLVMConstNull(ctxt->llvm_parseresultptr)); + rv = LLVMConstNull(ctxt->llvm_parseresultptr); + /* Pass it back out */ + *res = rv; return true; } diff --git a/src/parsers/token.c b/src/parsers/token.c index 3899abe8d5abf0e45ba9ac72b544095f1019bfa2..8b031989ff38308a638856a76f105b15ce3c63bf 100644 --- a/src/parsers/token.c +++ b/src/parsers/token.c @@ -80,7 +80,10 @@ static bool token_ctrvm(HRVMProg *prog, void *env) { * the LLVM module globals. We use this for longer tokens. */ -static bool token_llvm_with_global(HLLVMParserCompileContext *ctxt, HToken *t) { +static bool token_llvm_with_global( + HLLVMParserCompileContext *ctxt, + HToken *t, + LLVMValueRef *res) { LLVMValueRef bits_args[3], bits, i, i_init, i_incr, str, str_const, len; LLVMValueRef r, c, mr, icmp_i_len, icmp_c_r, rv; LLVMValueRef c_gep_indices[2], c_gep; @@ -186,8 +189,8 @@ static bool token_llvm_with_global(HLLVMParserCompileContext *ctxt, HToken *t) { LLVMConstNull(ctxt->llvm_parseresultptr) }; LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2); - /* Return it */ - LLVMBuildRet(ctxt->builder, rv); + /* Pass it back out */ + *res = rv; return true; } @@ -197,7 +200,10 @@ static bool token_llvm_with_global(HLLVMParserCompileContext *ctxt, HToken *t) { * suitable for short tokens. This also handles the zero-length token case. */ -static bool token_llvm_with_sequential_comparisons(HLLVMParserCompileContext *ctxt, HToken *t) { +static bool token_llvm_with_sequential_comparisons( + HLLVMParserCompileContext *ctxt, + HToken *t, + LLVMValueRef *res) { HAllocator *mm__; LLVMValueRef bits, r, c, icmp, mr, rv; LLVMValueRef bits_args[3]; @@ -271,16 +277,18 @@ static bool token_llvm_with_sequential_comparisons(HLLVMParserCompileContext *ct /* Free the stuff we allocated to build the phi */ h_free(bbs_into_phi); h_free(values_into_phi); - /* Return it */ - LLVMBuildRet(ctxt->builder, rv); + /* Pass it back out */ + *res = rv; return true; } #define TOKEN_LENGTH_USE_GLOBAL_CUTOFF 4 -static bool token_llvm(HLLVMParserCompileContext *ctxt, void* env) { +static bool token_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { HToken *t; + + if (!res) return false; if (!ctxt) return false; /* Get the token */ @@ -297,9 +305,9 @@ static bool token_llvm(HLLVMParserCompileContext *ctxt, void* env) { */ if (t->len > TOKEN_LENGTH_USE_GLOBAL_CUTOFF && t->len > 0) { - return token_llvm_with_global(ctxt, t); + return token_llvm_with_global(ctxt, t, res); } else { - return token_llvm_with_sequential_comparisons(ctxt, t); + return token_llvm_with_sequential_comparisons(ctxt, t, res); } }