Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • hammer/hammer
  • mlp/hammer
  • xentrac/hammer
  • pesco/hammer
  • denleylam/hammer
  • nobody/hammer
  • letitiali/hammer
  • kia/hammer-sandbox
  • vyrus001/hammer
9 results
Select Git revision
Show changes
#include <assert.h>
#ifdef HAMMER_LLVM_BACKEND
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#include <llvm-c/Core.h>
#pragma GCC diagnostic pop
#include "../backends/llvm/llvm.h"
#endif
#include "parser_internal.h"
struct bits_env {
......@@ -17,6 +24,82 @@ static HParseResult* parse_bits(void* env, HParseState *state) {
return make_result(state->arena, result);
}
#ifdef HAMMER_LLVM_BACKEND
static bool bits_llvm(HAllocator *mm__,
LLVMBuilderRef builder, LLVMValueRef func, LLVMModuleRef mod,
void* env) {
/* %result = alloca %struct.HParsedToken_*, align 8 */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
LLVMValueRef result = LLVMBuildAlloca(builder, llvm_parsedtoken, "result");
#pragma GCC diagnostic pop
/* store i8* %env, i8** %1, align 8 */
/* store %struct.HParseState_* %state, %struct.HParseState_** %2, align 8 */
/* %3 = load i8** %1, align 8 */
/* %4 = bitcast i8* %3 to %struct.bits_env* */
/* store %struct.bits_env* %4, %struct.bits_env** %env, align 8 */
/* %5 = load %struct.HParseState_** %2, align 8 */
/* %6 = getelementptr inbounds %struct.HParseState_* %5, i32 0, i32 2 */
/* %7 = load %struct.HArena_** %6, align 8 */
/* %8 = call noalias i8* @h_arena_malloc(%struct.HArena_* %7, i64 48) */
/* %9 = bitcast i8* %8 to %struct.HParsedToken_* */
/* store %struct.HParsedToken_* %9, %struct.HParsedToken_** %result, align 8 */
/* %10 = load %struct.bits_env** %env_, align 8 */
/* %11 = getelementptr inbounds %struct.bits_env* %10, i32 0, i32 1 */
/* %12 = load i8* %11, align 1 */
/* %13 = zext i8 %12 to i32 */
/* %14 = icmp ne i32 %13, 0 */
/* %15 = select i1 %14, i32 4, i32 8 */
/* %16 = load %struct.HParsedToken_** %result, align 8 */
/* %17 = getelementptr inbounds %struct.HParsedToken_* %16, i32 0, i32 0 */
/* store i32 %15, i32* %17, align 4 */
/* %18 = load %struct.bits_env** %env_, align 8 */
/* %19 = getelementptr inbounds %struct.bits_env* %18, i32 0, i32 1 */
/* %20 = load i8* %19, align 1 */
/* %21 = icmp ne i8 %20, 0 */
/* br i1 %21, label %22, label %33 */
/* ; <label>:22 ; preds = %0 */
/* %23 = load %struct.HParseState_** %2, align 8 */
/* %24 = getelementptr inbounds %struct.HParseState_* %23, i32 0, i32 1 */
/* %25 = load %struct.bits_env** %env_, align 8 */
/* %26 = getelementptr inbounds %struct.bits_env* %25, i32 0, i32 0 */
/* %27 = load i8* %26, align 1 */
/* %28 = zext i8 %27 to i32 */
/* %29 = call i64 @h_read_bits(%struct.HInputStream_* %24, i32 %28, i8 signext 1) */
/* %30 = load %struct.HParsedToken_** %result, align 8 */
/* %31 = getelementptr inbounds %struct.HParsedToken_* %30, i32 0, i32 1 */
/* %32 = bitcast %union.anon* %31 to i64* */
/* store i64 %29, i64* %32, align 8 */
/* br label %44 */
/* ; <label>:33 ; preds = %0 */
/* %34 = load %struct.HParseState_** %2, align 8 */
/* %35 = getelementptr inbounds %struct.HParseState_* %34, i32 0, i32 1 */
/* %36 = load %struct.bits_env** %env_, align 8 */
/* %37 = getelementptr inbounds %struct.bits_env* %36, i32 0, i32 0 */
/* %38 = load i8* %37, align 1 */
/* %39 = zext i8 %38 to i32 */
/* %40 = call i64 @h_read_bits(%struct.HInputStream_* %35, i32 %39, i8 signext 0) */
/* %41 = load %struct.HParsedToken_** %result, align 8 */
/* %42 = getelementptr inbounds %struct.HParsedToken_* %41, i32 0, i32 1 */
/* %43 = bitcast %union.anon* %42 to i64* */
/* store i64 %40, i64* %43, align 8 */
/* br label %44 */
/* ; <label>:44 ; preds = %33, %22 */
/* %45 = load %struct.HParseState_** %2, align 8 */
/* %46 = getelementptr inbounds %struct.HParseState_* %45, i32 0, i32 2 */
/* %47 = load %struct.HArena_** %46, align 8 */
/* %48 = load %struct.HParsedToken_** %result, align 8 */
/* %49 = call %struct.HParseResult_* @make_result(%struct.HArena_* %47, %struct.HParsedToken_* %48) */
/* ret %struct.HParseResult_* %49 */
return true;
}
#endif
static HParsedToken *reshape_bits(const HParseResult *p, void* signedp_p) {
// signedp == NULL iff unsigned
bool signedp = (signedp_p != NULL);
......@@ -102,6 +185,9 @@ static const HParserVtable bits_vt = {
.isValidCF = h_true,
.desugar = desugar_bits,
.compile_to_rvm = bits_ctrvm,
#ifdef HAMMER_LLVM_BACKEND
.llvm = bits_llvm,
#endif
.higher = false,
};
......
#include <stdint.h>
#include <assert.h>
#ifdef HAMMER_LLVM_BACKEND
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#include <llvm-c/Core.h>
#pragma GCC diagnostic pop
#include "../backends/llvm/llvm.h"
#endif
#include "parser_internal.h"
static HParseResult* parse_ch(void* env, HParseState *state) {
......@@ -41,12 +48,83 @@ static bool ch_ctrvm(HRVMProg *prog, void* env) {
return true;
}
#ifdef HAMMER_LLVM_BACKEND
static bool ch_llvm(HAllocator *mm__, LLVMBuilderRef builder, LLVMValueRef func, LLVMModuleRef mod, void* env) {
// Build a new LLVM function to parse a character
// Set up params for calls to h_read_bits() and h_arena_malloc()
LLVMValueRef bits_args[3];
LLVMValueRef stream = LLVMGetFirstParam(func);
stream = LLVMBuildBitCast(builder, stream, llvm_inputstreamptr, "stream");
bits_args[0] = stream;
bits_args[1] = LLVMConstInt(LLVMInt32Type(), 8, 0);
bits_args[2] = LLVMConstInt(LLVMInt8Type(), 0, 0);
LLVMValueRef arena = LLVMGetLastParam(func);
// Set up basic blocks: entry, success and failure branches, then exit
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(func, "ch_entry");
LLVMBasicBlockRef success = LLVMAppendBasicBlock(func, "ch_success");
LLVMBasicBlockRef end = LLVMAppendBasicBlock(func, "ch_end");
// Basic block: entry
LLVMPositionBuilderAtEnd(builder, entry);
// Call to h_read_bits()
// %read_bits = call i64 @h_read_bits(%struct.HInputStream_* %8, i32 8, i8 signext 0)
LLVMValueRef bits = LLVMBuildCall(builder, LLVMGetNamedFunction(mod, "h_read_bits"), bits_args, 3, "read_bits");
// %2 = trunc i64 %read_bits to i8
LLVMValueRef r = LLVMBuildTrunc(builder, bits, LLVMInt8Type(), ""); // do we actually need this?
// 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(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
LLVMBuildCondBr(builder, icmp, success, end);
// Basic block: success
LLVMPositionBuilderAtEnd(builder, success);
/* Make a token */
LLVMValueRef mr;
h_llvm_make_tt_suint(mod, builder, stream, arena, r, &mr);
// br label %ch_end
LLVMBuildBr(builder, end);
// Basic block: end
LLVMPositionBuilderAtEnd(builder, end);
// %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ], [ null, %ch_entry ]
LLVMValueRef rv = LLVMBuildPhi(builder, llvm_parseresultptr, "rv");
LLVMBasicBlockRef rv_phi_incoming_blocks[] = {
success,
entry
};
LLVMValueRef rv_phi_incoming_values[] = {
mr,
LLVMConstNull(llvm_parseresultptr)
};
LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2);
// ret %struct.HParseResult_.3* %rv
LLVMBuildRet(builder, rv);
return true;
}
#endif /* defined(HAMMER_LLVM_BACKEND) */
static const HParserVtable ch_vt = {
.parse = parse_ch,
.isValidRegular = h_true,
.isValidCF = h_true,
.desugar = desugar_ch,
.compile_to_rvm = ch_ctrvm,
#ifdef HAMMER_LLVM_BACKEND
.llvm = ch_llvm,
#endif
.higher = false,
};
......
#include <assert.h>
#include <string.h>
#include "../internal.h"
#ifdef HAMMER_LLVM_BACKEND
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#include <llvm-c/Core.h>
#pragma GCC diagnostic pop
#include "../backends/llvm/llvm.h"
#endif /* defined(HAMMER_LLVM_BACKEND) */
#include "parser_internal.h"
static HParseResult* parse_charset(void *env, HParseState *state) {
......@@ -70,12 +77,89 @@ static bool cs_ctrvm(HRVMProg *prog, void *env) {
return true;
}
#ifdef HAMMER_LLVM_BACKEND
static bool cs_llvm(HAllocator *mm__, LLVMBuilderRef builder, LLVMValueRef func,
LLVMModuleRef mod, void* env) {
/*
* LLVM to build a function to parse a charset; the args are a stream and an
* arena.
*/
bool ok;
LLVMValueRef stream = LLVMGetFirstParam(func);
stream = LLVMBuildBitCast(builder, stream, llvm_inputstreamptr, "stream");
LLVMValueRef arena = LLVMGetLastParam(func);
/* Set up our basic blocks */
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(func, "cs_entry");
LLVMBasicBlockRef success = LLVMAppendBasicBlock(func, "cs_success");
LLVMBasicBlockRef fail = LLVMAppendBasicBlock(func, "cs_fail");
LLVMBasicBlockRef end = LLVMAppendBasicBlock(func, "cs_end");
/* Basic block: entry */
LLVMPositionBuilderAtEnd(builder, entry);
/* First we read the char */
LLVMValueRef bits_args[3];
bits_args[0] = stream;
bits_args[1] = LLVMConstInt(LLVMInt32Type(), 8, 0);
bits_args[2] = LLVMConstInt(LLVMInt8Type(), 0, 0);
LLVMValueRef bits = LLVMBuildCall(builder, LLVMGetNamedFunction(mod, "h_read_bits"), bits_args, 3, "read_bits");
LLVMValueRef r = LLVMBuildTrunc(builder, bits, LLVMInt8Type(), ""); // TODO Necessary? (same question in ch_llvm())
/* We have a char, need to check if it's in the charset */
HCharset cs = (HCharset)env;
/* Branch to either success or end, conditional on whether r is in cs */
ok = h_llvm_make_charset_membership_test(mm__, mod, func, builder, r, cs, success, fail);
/* Basic block: success */
LLVMPositionBuilderAtEnd(builder, success);
LLVMValueRef mr;
h_llvm_make_tt_suint(mod, builder, stream, arena, r, &mr);
/* br label %ch_end */
LLVMBuildBr(builder, end);
/* Basic block: fail */
LLVMPositionBuilderAtEnd(builder, fail);
/*
* We just branch straight to end; this exists so that the phi node in
* end knows where all the incoming edges are from, rather than needing
* some basic block constructed in h_llvm_make_charset_membership_test()
*/
LLVMBuildBr(builder, end);
/* Basic block: end */
LLVMPositionBuilderAtEnd(builder, end);
// %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ], [ null, %ch_entry ]
LLVMValueRef rv = LLVMBuildPhi(builder, llvm_parseresultptr, "rv");
LLVMBasicBlockRef rv_phi_incoming_blocks[] = {
success,
fail
};
LLVMValueRef rv_phi_incoming_values[] = {
mr,
LLVMConstNull(llvm_parseresultptr)
};
LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2);
// ret %struct.HParseResult_.3* %rv
LLVMBuildRet(builder, rv);
return ok;
}
#endif /* defined(HAMMER_LLVM_BACKEND) */
static const HParserVtable charset_vt = {
.parse = parse_charset,
.isValidRegular = h_true,
.isValidCF = h_true,
.desugar = desugar_charset,
.compile_to_rvm = cs_ctrvm,
#ifdef HAMMER_LLVM_BACKEND
.llvm = cs_llvm,
#endif
.higher = false,
};
......
#ifndef _GNU_SOURCE
#define _GNU_SOURCE // to obtain asprintf/vasprintf
#endif
#include "platform.h"
#include <stdio.h>
......
......@@ -116,7 +116,7 @@ static inline bool append_buf_c(struct result_buf *buf, char v) {
}
/** append a formatted string to the result buffer */
static inline bool append_buf_formatted(struct result_buf *buf, char* format, ...)
static inline bool append_buf_formatted(struct result_buf *buf, const char* format, ...)
{
char* tmpbuf;
int len;
......
......@@ -21,10 +21,19 @@ static void test_ch(gconstpointer backend) {
}
static void test_ch_range(gconstpointer backend) {
const HParser *range_ = h_ch_range('a', 'c');
g_check_parse_match(range_, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1, "u0x62");
g_check_parse_failed(range_, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1);
const HParser *range_1 = h_ch_range('a', 'c');
const HParser *range_2 = h_ch_range('a', 'z');
const HParser *range_3 = h_ch_range('A', 'z');
const HParser *range_all = h_ch_range(0, 255);
g_check_parse_match(range_1, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1, "u0x62");
g_check_parse_failed(range_1, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1);
g_check_parse_match(range_2, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1, "u0x62");
g_check_parse_failed(range_2, (HParserBackend)GPOINTER_TO_INT(backend), "C", 1);
g_check_parse_match(range_3, (HParserBackend)GPOINTER_TO_INT(backend), "B", 1, "u0x42");
g_check_parse_failed(range_3, (HParserBackend)GPOINTER_TO_INT(backend), "2", 1);
/* range_all never fails anything */
g_check_parse_match(range_all, (HParserBackend)GPOINTER_TO_INT(backend), "B", 1, "u0x42");
}
//@MARK_START
......@@ -213,18 +222,71 @@ static void test_action(gconstpointer backend) {
static void test_in(gconstpointer backend) {
uint8_t options[3] = { 'a', 'b', 'c' };
uint8_t odds[128];
uint8_t _1_mod_4[64];
uint8_t scattered[3] = { 'A', 'b', 'z' };
int i;
const HParser *in_ = h_in(options, 3);
g_check_parse_match(in_, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1, "u0x62");
g_check_parse_failed(in_, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1);
for (i = 0; i < 128; ++i) odds[i] = (uint8_t)(2*i + 1);
const HParser *odds_ = h_in(odds, 128);
g_check_parse_match(odds_, (HParserBackend)GPOINTER_TO_INT(backend), "c", 1, "u0x63");
g_check_parse_match(odds_, (HParserBackend)GPOINTER_TO_INT(backend), "E", 1, "u0x45");
g_check_parse_failed(odds_, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1);
g_check_parse_failed(odds_, (HParserBackend)GPOINTER_TO_INT(backend), "F", 1);
for (i = 0; i < 64; ++i) _1_mod_4[i] = (uint8_t)(4*i + 1);
const HParser *_1_mod_4_ = h_in(_1_mod_4, 64);
g_check_parse_match(_1_mod_4_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "u0x61");
g_check_parse_match(_1_mod_4_, (HParserBackend)GPOINTER_TO_INT(backend), "E", 1, "u0x45");
g_check_parse_failed(_1_mod_4_, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1);
g_check_parse_failed(_1_mod_4_, (HParserBackend)GPOINTER_TO_INT(backend), "c", 1);
g_check_parse_failed(_1_mod_4_, (HParserBackend)GPOINTER_TO_INT(backend), "F", 1);
const HParser *scattered_ = h_in(scattered, 3);
g_check_parse_match(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "A", 1, "u0x41");
g_check_parse_match(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1, "u0x62");
g_check_parse_match(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "z", 1, "u0x7a");
g_check_parse_failed(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "y", 1);
g_check_parse_failed(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "F", 1);
}
static void test_not_in(gconstpointer backend) {
uint8_t options[3] = { 'a', 'b', 'c' };
uint8_t odds[128];
uint8_t _1_mod_4[64];
uint8_t scattered[3] = { 'A', 'b', 'z' };
int i;
const HParser *not_in_ = h_not_in(options, 3);
g_check_parse_match(not_in_, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1, "u0x64");
g_check_parse_failed(not_in_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1);
for (i = 0; i < 128; ++i) odds[i] = (uint8_t)(2*i + 1);
const HParser *odds_ = h_not_in(odds, 128);
g_check_parse_match(odds_, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1, "u0x64");
g_check_parse_match(odds_, (HParserBackend)GPOINTER_TO_INT(backend), "F", 1, "u0x46");
g_check_parse_failed(odds_, (HParserBackend)GPOINTER_TO_INT(backend), "c", 1);
g_check_parse_failed(odds_, (HParserBackend)GPOINTER_TO_INT(backend), "E", 1);
for (i = 0; i < 64; ++i) _1_mod_4[i] = (uint8_t)(4*i + 1);
const HParser *_1_mod_4_ = h_not_in(_1_mod_4, 64);
g_check_parse_match(_1_mod_4_, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1, "u0x62");
g_check_parse_match(_1_mod_4_, (HParserBackend)GPOINTER_TO_INT(backend), "F", 1, "u0x46");
g_check_parse_failed(_1_mod_4_, (HParserBackend)GPOINTER_TO_INT(backend), "e", 1);
g_check_parse_failed(_1_mod_4_, (HParserBackend)GPOINTER_TO_INT(backend), "A", 1);
const HParser *scattered_ = h_not_in(scattered, 3);
g_check_parse_match(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "B", 1, "u0x42");
g_check_parse_match(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "u0x61");
g_check_parse_match(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "y", 1, "u0x79");
g_check_parse_failed(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "A", 1);
g_check_parse_failed(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1);
g_check_parse_failed(scattered_, (HParserBackend)GPOINTER_TO_INT(backend), "z", 1);
}
static void test_end_p(gconstpointer backend) {
......@@ -961,4 +1023,11 @@ void register_parser_tests(void) {
g_test_add_data_func("/core/parser/glr/ambiguous", GINT_TO_POINTER(PB_GLR), test_ambiguous);
g_test_add_data_func("/core/parser/glr/result_length", GINT_TO_POINTER(PB_GLR), test_result_length);
g_test_add_data_func("/core/parser/glr/token_position", GINT_TO_POINTER(PB_GLR), test_token_position);
#ifdef HAMMER_LLVM_BACKEND
g_test_add_data_func("/core/parser/llvm/ch", GINT_TO_POINTER(PB_LLVM), test_ch);
g_test_add_data_func("/core/parser/llvm/ch_range", GINT_TO_POINTER(PB_LLVM), test_ch_range);
g_test_add_data_func("/core/parser/llvm/in", GINT_TO_POINTER(PB_LLVM), test_in);
g_test_add_data_func("/core/parser/llvm/not_in", GINT_TO_POINTER(PB_LLVM), test_not_in);
#endif /* defined(HAMMER_LLVM_BACKEND) */
}
......@@ -167,7 +167,10 @@ static void test_charset_bits(void) {
.free = NULL,
};
test_charset_bits__buf[32] = 0xAB;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
HCharset cs = new_charset(&alloc);
#pragma GCC diagnostic pop
for(size_t i=0; i<32; i++)
g_check_cmp_uint32(test_charset_bits__buf[i], ==, 0);
g_check_cmp_uint32(test_charset_bits__buf[32], ==, 0xAB);
......