diff --git a/src/backends/llvm/llvm.c b/src/backends/llvm/llvm.c index 356b279b2754772921ae9e449c6848d3b792a2b4..1f4209c3a9616894bd96d1a7cd33dfa9e6da26ea 100644 --- a/src/backends/llvm/llvm.c +++ b/src/backends/llvm/llvm.c @@ -178,7 +178,7 @@ int h_llvm_compile(HAllocator* mm__, HParser* parser, const void* params) { * Translate the contents of the children of `parser` into their LLVM * instruction equivalents */ - if (parser->vtable->llvm(ctxt, parser->env, &res)) { + if (parser->vtable->llvm(ctxt, parser, &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); diff --git a/src/internal.h b/src/internal.h index 7646e3a6576ae73d9d54b74f02f38f5253a2ed7f..23e0b7cd0b3a8bdab8799294d9b0b7ba5bd5ef67 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, LLVMValueRef *result); + bool (*llvm)(HLLVMParserCompileContext *ctxt, HParser *p, LLVMValueRef *result); #endif bool higher; // false if primitive }; diff --git a/src/parsers/bits.c b/src/parsers/bits.c index f59849fde9d0d4d66e5ebb678fe061a4161f4633..91669726d4129c3e803dbc2f3cd577c5cd227bb7 100644 --- a/src/parsers/bits.c +++ b/src/parsers/bits.c @@ -26,22 +26,25 @@ static HParseResult* parse_bits(void* env, HParseState *state) { #ifdef HAMMER_LLVM_BACKEND -static bool bits_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { +static bool bits_llvm(HLLVMParserCompileContext *ctxt, + HParser *p, + LLVMValueRef *res) { /* Emit LLVM IR to parse ((struct bits_env *)env)->length bits */ if (!res) return false; + if (!p) 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; + struct bits_env *env = (struct bits_env *)(p->env); /* Error out on unsupported length */ - if (env_->length > 64 || env_->length == 0) return false; + if (env->length > 64 || env->length == 0) return false; /* Set up params for call to h_read_bits */ LLVMValueRef bits_args[3]; bits_args[0] = ctxt->stream; - bits_args[1] = LLVMConstInt(LLVMInt32Type(), env_->length, 0); - bits_args[2] = LLVMConstInt(LLVMInt8Type(), env_->signedp ? 1 : 0, 0); + bits_args[1] = LLVMConstInt(LLVMInt32Type(), env->length, 0); + bits_args[2] = LLVMConstInt(LLVMInt8Type(), env->signedp ? 1 : 0, 0); /* Set up basic blocks: entry, success and failure branches, then exit */ LLVMBasicBlockRef bits_bb = LLVMAppendBasicBlock(ctxt->func, "bits"); @@ -57,7 +60,7 @@ static bool bits_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef * /* Make an HParseResult out of it */ LLVMValueRef mr; - h_llvm_make_tt_suint(ctxt, env_->length, env_->signedp, bits, &mr); + h_llvm_make_tt_suint(ctxt, env->length, env->signedp, bits, &mr); /* Return mr */ *res = mr; diff --git a/src/parsers/ch.c b/src/parsers/ch.c index 2db312d6fc45a299261a36be2b2782467382fa11..9a3dbfe9a67be6b529cacbed117e2c28a1a6f568 100644 --- a/src/parsers/ch.c +++ b/src/parsers/ch.c @@ -50,52 +50,76 @@ static bool ch_ctrvm(HRVMProg *prog, void* env) { #ifdef HAMMER_LLVM_BACKEND -static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { +static bool ch_llvm(HLLVMParserCompileContext *ctxt, + HParser *p, + LLVMValueRef *res) { /* Build a new LLVM function to parse a character */ + /* Basic blocks we will be using */ + LLVMBasicBlockRef entry, success, end; + /* Args for call to h_read_bits() */ + LLVMValueRef bits_args[3]; + /* Result of call to h_read_bits() */ + LLVMValueRef bits; + /* Truncated result of call to h_read_bits() */ + LLVMValueRef r; + /* Character to check for */ + uint8_t cval; + /* Character to check for as an LLVM value */ + LLVMValueRef c; + /* Result of LLVM comparison */ + LLVMValueRef icmp; + /* Completed token */ + LLVMValueRef mr; + /* Return value (a phi) */ + LLVMValueRef rv; + /* Inputs to the phi */ + LLVMBasicBlockRef rv_phi_incoming_blocks[2]; + LLVMValueRef rv_phi_incoming_values[2]; + if (!res) return false; + if (!p) 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 * * 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"); + entry = LLVMAppendBasicBlock(ctxt->func, "ch_entry"); + success = LLVMAppendBasicBlock(ctxt->func, "ch_success"); + end = LLVMAppendBasicBlock(ctxt->func, "ch_end"); /* Basic block: entry */ LLVMBuildBr(ctxt->builder, entry); LLVMPositionBuilderAtEnd(ctxt->builder, entry); + /* Set up params for calls to h_read_bits() */ + bits_args[0] = ctxt->stream; + bits_args[1] = LLVMConstInt(LLVMInt32Type(), 8, 0); + bits_args[2] = LLVMConstInt(LLVMInt8Type(), 0, 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"); + bits = LLVMBuildCall(ctxt->builder, + LLVMGetNamedFunction(ctxt->mod, "h_read_bits"), + bits_args, 3, "read_bits"); /* %2 = trunc i64 %read_bits to i8 */ - LLVMValueRef r = LLVMBuildTrunc(ctxt->builder, - bits, LLVMInt8Type(), ""); + r = LLVMBuildTrunc(ctxt->builder, bits, LLVMInt8Type(), ""); /* * 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"); + cval = (uint8_t)(uintptr_t)(p->env); + c = LLVMConstInt(LLVMInt8Type(), cval, 0); + icmp = LLVMBuildICmp(ctxt->builder, LLVMIntEQ, c, r, "c == r"); /* * Branch so success or failure basic block, as appropriate @@ -107,7 +131,6 @@ static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *re LLVMPositionBuilderAtEnd(ctxt->builder, success); /* Make a token */ - LLVMValueRef mr; h_llvm_make_tt_suint(ctxt, 8, 0, r, &mr); /* br label %ch_end */ @@ -119,15 +142,11 @@ static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *re * %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, - entry - }; - LLVMValueRef rv_phi_incoming_values[] = { - mr, - LLVMConstNull(ctxt->llvm_parseresultptr) - }; + 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] = entry; + rv_phi_incoming_values[1] = LLVMConstNull(ctxt->llvm_parseresultptr); LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2); /* Pass rv out to caller */ *res = rv; diff --git a/src/parsers/charset.c b/src/parsers/charset.c index f77d9e78e9e6736950ea81cd295793ba27f6ad24..49dd5601d92549711db6197594c6327bc6476ed2 100644 --- a/src/parsers/charset.c +++ b/src/parsers/charset.c @@ -79,7 +79,9 @@ static bool cs_ctrvm(HRVMProg *prog, void *env) { #ifdef HAMMER_LLVM_BACKEND -static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { +static bool cs_llvm(HLLVMParserCompileContext *ctxt, + HParser *p, + LLVMValueRef *res) { /* * LLVM to build a function to parse a charset; the args are a stream and an * arena. @@ -104,6 +106,7 @@ static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *re LLVMBasicBlockRef rv_phi_incoming_blocks[2]; if (!res) return false; + if (!p) return false; if (!ctxt) return false; /* Set up our basic blocks */ @@ -126,7 +129,7 @@ static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *re r = LLVMBuildTrunc(ctxt->builder, bits, LLVMInt8Type(), ""); /* We have a char, need to check if it's in the charset */ - cs = (HCharset)env; + cs = (HCharset)(p->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); diff --git a/src/parsers/end.c b/src/parsers/end.c index 11dcd33fd152188113bbb2eae10a12ff65cbfb10..6355334c3df9a3baed50c7b7c693ab14b447dc53 100644 --- a/src/parsers/end.c +++ b/src/parsers/end.c @@ -28,7 +28,9 @@ static bool end_ctrvm(HRVMProg *prog, void *env) { #ifdef HAMMER_LLVM_BACKEND -static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { +static bool end_llvm(HLLVMParserCompileContext *ctxt, + HParser *p, + LLVMValueRef *res) { /* Basic blocks for parsing end */ LLVMBasicBlockRef entry, success, end; /* Indices for GEP */ @@ -45,6 +47,7 @@ static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *r LLVMValueRef rv_phi_incoming_values[2]; if (!res) return false; + if (!p) return false; if (!ctxt) return false; /* Set up some basic blocks */ diff --git a/src/parsers/epsilon.c b/src/parsers/epsilon.c index 2fd163a98a70772e87a0ebf98b83ca8542bf479f..b9021d6c46848def867edd8dd23c9055239c8352 100644 --- a/src/parsers/epsilon.c +++ b/src/parsers/epsilon.c @@ -21,7 +21,9 @@ static bool epsilon_ctrvm(HRVMProg *prog, void* env) { #ifdef HAMMER_LLVM_BACKEND -static bool epsilon_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { +static bool epsilon_llvm(HLLVMParserCompileContext *ctxt, + HParser *p, + LLVMValueRef *res) { /* Epsilon basic block */ LLVMBasicBlockRef epsilon_bb; /* Args for make_result() */ @@ -30,6 +32,7 @@ static bool epsilon_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRe LLVMValueRef result_ptr; if (!res) return false; + if (!p) return false; if (!ctxt) return false; epsilon_bb = LLVMAppendBasicBlock(ctxt->func, "epsilon"); diff --git a/src/parsers/nothing.c b/src/parsers/nothing.c index df9e3f79786fb9275e6dadd479db8a0e3cb611c6..f5e427b1cfd8bf3cba9f63d0e247b276609c869b 100644 --- a/src/parsers/nothing.c +++ b/src/parsers/nothing.c @@ -27,13 +27,16 @@ static bool nothing_ctrvm(HRVMProg *prog, void* env) { #ifdef HAMMER_LLVM_BACKEND -static bool nothing_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { +static bool nothing_llvm(HLLVMParserCompileContext *ctxt, + HParser *p, + LLVMValueRef *res) { /* Nothing entry bb */ LLVMBasicBlockRef entry; /* Nothing result */ LLVMValueRef rv; if (!res) return false; + if (!p) return false; if (!ctxt) return false; /* This one just always returns NULL */ diff --git a/src/parsers/token.c b/src/parsers/token.c index 8b031989ff38308a638856a76f105b15ce3c63bf..f63bbbee9da7bc6f60456c38815d7b750391228c 100644 --- a/src/parsers/token.c +++ b/src/parsers/token.c @@ -285,14 +285,19 @@ static bool token_llvm_with_sequential_comparisons( #define TOKEN_LENGTH_USE_GLOBAL_CUTOFF 4 -static bool token_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) { +static bool token_llvm(HLLVMParserCompileContext *ctxt, + HParser *p, + LLVMValueRef *res) { HToken *t; if (!res) return false; + if (!p) return false; if (!ctxt) return false; /* Get the token */ - t = (HToken *)env; + t = (HToken *)(p->env); + if (!t) return false; + /* * Check its length; we have two possible code-generation strategies * here: treat it like chars sequentially and emit a series of read/