static void handle_line(char **tokens, int ntokens) { char *name = tokens[0]; LLVMValueRef param; LLVMValueRef res; LLVMModuleRef M = LLVMModuleCreateWithName(name); LLVMTypeRef I64ty = LLVMInt64Type(); LLVMTypeRef I64Ptrty = LLVMPointerType(I64ty, 0); LLVMTypeRef Fty = LLVMFunctionType(I64ty, &I64Ptrty, 1, 0); LLVMValueRef F = LLVMAddFunction(M, name, Fty); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, LLVMAppendBasicBlock(F, "entry")); LLVMGetParams(F, ¶m); LLVMSetValueName(param, "in"); res = build_from_tokens(tokens + 1, ntokens - 1, builder, param); if (res) { char *irstr = LLVMPrintModuleToString(M); puts(irstr); LLVMDisposeMessage(irstr); } LLVMDisposeBuilder(builder); LLVMDisposeModule(M); }
static LLVMValueRef get_stritem_len_fn(struct llvm_ctx *ctx) { if(ctx->stritem_len_fn != NULL) return ctx->stritem_len_fn; /* returns (i32 len, i32 new_tpos) * params (word *utcbptr, i32 tpos) * * when return value "new_tpos" > tmax + 1, the result is invalid. the function * should also not be called when tpos > tmax + 1. */ LLVMTypeRef ret_types[2] = { ctx->i32t, ctx->i32t }, parm_types[2] = { LLVMPointerType(ctx->wordt, 0), ctx->i32t }, ret_type = LLVMStructTypeInContext(ctx->ctx, ret_types, 2, 0), fn_type = LLVMFunctionType(ret_type, parm_types, 2, 0); LLVMValueRef fn = LLVMAddFunction(ctx->module, "__muidl_get_stritem_len", fn_type); LLVMSetVisibility(fn, LLVMHiddenVisibility); LLVMSetLinkage(fn, LLVMInternalLinkage); V fn_args[2]; LLVMGetParams(fn, fn_args); LLVMAddAttribute(fn_args[0], LLVMNoCaptureAttribute); for(int i=0; i<2; i++) { LLVMAddAttribute(fn_args[i], LLVMInRegAttribute); } ctx->stritem_len_fn = fn; LLVMBuilderRef old_builder = ctx->builder; ctx->builder = LLVMCreateBuilderInContext(ctx->ctx); LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "EntryBlock"), loop_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "loop"), valid_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "valid"), exit_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "exit"); LLVMPositionBuilderAtEnd(ctx->builder, entry_bb); LLVMValueRef old_utcb = ctx->utcb, old_tpos = ctx->tpos; ctx->utcb = fn_args[0]; ctx->tpos = fn_args[1]; LLVMBuildBr(ctx->builder, loop_bb); LLVMPositionBuilderAtEnd(ctx->builder, exit_bb); LLVMValueRef exit_len_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "exit.len.phi"), exit_tpos_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "exit.tpos.phi"); LLVMValueRef rvals[2] = { exit_len_phi, exit_tpos_phi }; LLVMBuildAggregateRet(ctx->builder, rvals, 2); LLVMPositionBuilderAtEnd(ctx->builder, loop_bb); LLVMValueRef len_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "len.phi"), tpos_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "tpos.phi"); LLVMAddIncoming(len_phi, &ctx->zero, &entry_bb, 1); LLVMAddIncoming(tpos_phi, &ctx->tpos, &entry_bb, 1); ctx->tpos = tpos_phi; /* test: if *tpos doesn't look like a string item, conk out. */ LLVMValueRef infoword = build_utcb_load(ctx, ctx->tpos, "si.info"); LLVMValueRef is_cond = LLVMBuildICmp(ctx->builder, LLVMIntEQ, ctx->zero, LLVMBuildAnd(ctx->builder, infoword, CONST_WORD(1 << 4), "infoword.si.mask"), "infoword.si.cond"); /* anything + 100 is sure to be > tmax + 1. */ LLVMValueRef fucked_tpos = LLVMBuildAdd(ctx->builder, tpos_phi, CONST_INT(100), "f****d.tpos"); branch_set_phi(ctx, exit_len_phi, len_phi); branch_set_phi(ctx, exit_tpos_phi, fucked_tpos); LLVMBuildCondBr(ctx->builder, is_cond, valid_bb, exit_bb); LLVMPositionBuilderAtEnd(ctx->builder, valid_bb); LLVMValueRef string_length = LLVMBuildTruncOrBitCast(ctx->builder, LLVMBuildLShr(ctx->builder, infoword, CONST_INT(10), "si.info.len"), ctx->i32t, "si.info.len.int"), string_j = LLVMBuildTruncOrBitCast(ctx->builder, LLVMBuildAnd(ctx->builder, CONST_WORD(0x1f), LLVMBuildLShr(ctx->builder, infoword, CONST_WORD(4), "si.info.j.shift"), "si.info.j.masked"), ctx->i32t, "si.info.j"), string_c = LLVMBuildTruncOrBitCast(ctx->builder, LLVMBuildAnd(ctx->builder, CONST_WORD(1 << 9), infoword, "si.info.c.masked"), ctx->i32t, "si.info.c.masked.int"), c_cond = LLVMBuildICmp(ctx->builder, LLVMIntNE, string_c, CONST_WORD(0), "si.info.c.cond"), new_len = LLVMBuildAdd(ctx->builder, len_phi, LLVMBuildMul(ctx->builder, string_length, LLVMBuildAdd(ctx->builder, string_j, CONST_INT(1), "j.plus.one"), "len.incr"), "len.new"), new_tpos = LLVMBuildAdd(ctx->builder, ctx->tpos, LLVMBuildSelect(ctx->builder, c_cond, LLVMBuildAdd(ctx->builder, CONST_INT(2), string_j, "cont.tpos.bump"), CONST_INT(2), "tpos.bump"), "tpos.new"); LLVMAddIncoming(len_phi, &new_len, &valid_bb, 1); LLVMAddIncoming(tpos_phi, &new_tpos, &valid_bb, 1); LLVMAddIncoming(exit_len_phi, &new_len, &valid_bb, 1); LLVMAddIncoming(exit_tpos_phi, &new_tpos, &valid_bb, 1); LLVMBuildCondBr(ctx->builder, c_cond, loop_bb, exit_bb); LLVMDisposeBuilder(ctx->builder); ctx->builder = old_builder; ctx->utcb = old_utcb; ctx->tpos = old_tpos; return ctx->stritem_len_fn; }
LLVMValueRef get_struct_fn( struct llvm_ctx *ctx, IDL_tree ctyp, bool for_encode) { const char *s_id = IDL_IDENT(IDL_TYPE_STRUCT(ctyp).ident).repo_id; char *lookup_name = talloc_asprintf(ctx, "%c%s", for_encode ? 'e' : 'd', s_id); LLVMValueRef fn = strmap_get(&ctx->struct_decoder_fns, lookup_name); if(fn != NULL) { talloc_free(lookup_name); return fn; } const struct packed_format *fmt = packed_format_of(ctyp); assert(fmt != NULL); /* only sane for packable structs */ int namelen = strlen(s_id); char flatname[namelen + 1]; /* FIXME: make this proper, i.e. use a name mangler that works */ for(int i=0; i < namelen; i++) { flatname[i] = isalnum(s_id[i]) ? s_id[i] : '_'; } flatname[namelen] = '\0'; T types[3], rettyp = LLVMVoidTypeInContext(ctx->ctx); types[0] = LLVMPointerType(llvm_rigid_type(ctx, ctyp), 0); int nparms; if(!for_encode) { /* decoder */ types[1] = ctx->i32t; types[2] = ctx->i32t; nparms = fmt->num_bits < BITS_PER_WORD ? 3 : 2; } else if(fmt->num_bits < BITS_PER_WORD) { /* subword encoder */ rettyp = ctx->wordt; types[1] = ctx->wordt; types[2] = ctx->i32t; nparms = 3; } else { /* non-subword encoder */ types[1] = ctx->i32t; nparms = 2; } T fntype = LLVMFunctionType(rettyp, types, nparms, 0); char *fnname = g_strdup_printf("__muidl_idl_%scode__%s", for_encode ? "en" : "de", flatname); fn = LLVMAddFunction(ctx->module, fnname, fntype); LLVMSetLinkage(fn, LLVMExternalLinkage); V params[nparms]; assert(LLVMCountParams(fn) == nparms); LLVMGetParams(fn, params); LLVMAddAttribute(params[0], LLVMNoAliasAttribute); LLVMAddAttribute(params[0], LLVMNoCaptureAttribute); for(int i=0; i<nparms; i++) { LLVMAddAttribute(params[i], LLVMInRegAttribute); } g_free(fnname); bool ok = strmap_add(&ctx->struct_decoder_fns, lookup_name, fn); assert(ok || errno != EEXIST); return fn; }