diff options
| -rw-r--r-- | CMakeLists.txt | 1 | ||||
| -rw-r--r-- | doc/langref.html.in | 26 | ||||
| -rw-r--r-- | src-self-hosted/value.zig | 8 | ||||
| -rw-r--r-- | src/bigint.cpp | 11 | ||||
| -rw-r--r-- | src/codegen.cpp | 2 | ||||
| -rw-r--r-- | src/link.cpp | 32 | ||||
| -rw-r--r-- | src/main.cpp | 5 | ||||
| -rw-r--r-- | src/target.cpp | 17 | ||||
| -rw-r--r-- | src/translate_c.cpp | 778 | ||||
| -rw-r--r-- | src/zig_clang.cpp | 45 | ||||
| -rw-r--r-- | src/zig_clang.h | 15 | ||||
| -rw-r--r-- | std/debug.zig | 2 | ||||
| -rw-r--r-- | std/math/big.zig | 2 | ||||
| -rw-r--r-- | std/math/big/int.zig | 645 | ||||
| -rw-r--r-- | std/math/big/rational.zig | 896 | ||||
| -rw-r--r-- | std/special/compiler_rt.zig | 16 | ||||
| -rw-r--r-- | std/special/compiler_rt/divti3.zig | 6 | ||||
| -rw-r--r-- | std/special/compiler_rt/modti3.zig | 6 | ||||
| -rw-r--r-- | std/special/compiler_rt/muloti4.zig | 10 | ||||
| -rw-r--r-- | std/special/compiler_rt/multi3.zig | 6 | ||||
| -rw-r--r-- | std/special/compiler_rt/udivmodti4.zig | 5 | ||||
| -rw-r--r-- | std/special/compiler_rt/udivti3.zig | 5 | ||||
| -rw-r--r-- | std/special/compiler_rt/umodti3.zig | 6 | ||||
| -rw-r--r-- | test/stage1/behavior/bit_shifting.zig | 8 | ||||
| -rw-r--r-- | test/stage1/behavior/math.zig | 7 |
25 files changed, 1846 insertions, 714 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8588c3ae9e..2c34f334f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -521,6 +521,7 @@ set(ZIG_STD_FILES "math/atanh.zig" "math/big.zig" "math/big/int.zig" + "math/big/rational.zig" "math/cbrt.zig" "math/ceil.zig" "math/complex.zig" diff --git a/doc/langref.html.in b/doc/langref.html.in index 1d80c73a3e..a73e5d94d9 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -7360,20 +7360,30 @@ fn List(comptime T: type) type { <pre>{#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}</pre> <p> This function truncates bits from an integer type, resulting in a smaller - integer type. + or same-sized integer type. </p> <p> - The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in - {#link|ReleaseFast#} mode: + The following produces safety-checked {#link|Undefined Behavior#}: </p> - <pre>{#syntax#}const a: u16 = 0xabcd; -const b: u8 = u8(a);{#endsyntax#}</pre> + {#code_begin|test_err|cast truncated bits#} +test "integer cast panic" { + var a: u16 = 0xabcd; + var b: u8 = @intCast(u8, a); +} + {#code_end#} <p> However this is well defined and working code: </p> - <pre>{#syntax#}const a: u16 = 0xabcd; -const b: u8 = @truncate(u8, a); -// b is now 0xcd{#endsyntax#}</pre> + {#code_begin|test|truncate#} +const std = @import("std"); +const assert = std.debug.assert; + +test "integer truncation" { + var a: u16 = 0xabcd; + var b: u8 = @truncate(u8, a); + assert(b == 0xcd); +} + {#code_end#} <p> This function always truncates the significant bits of the integer, regardless of endianness on the target platform. diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index d8c0f7b5c8..f1c7fc0b50 100644 --- a/src-self-hosted/value.zig +++ b/src-self-hosted/value.zig @@ -538,21 +538,21 @@ pub const Value = struct { switch (self.base.typ.id) { Type.Id.Int => { const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context); - if (self.big_int.len == 0) { + if (self.big_int.len() == 0) { return llvm.ConstNull(type_ref); } - const unsigned_val = if (self.big_int.len == 1) blk: { + const unsigned_val = if (self.big_int.len() == 1) blk: { break :blk llvm.ConstInt(type_ref, self.big_int.limbs[0], @boolToInt(false)); } else if (@sizeOf(std.math.big.Limb) == @sizeOf(u64)) blk: { break :blk llvm.ConstIntOfArbitraryPrecision( type_ref, - @intCast(c_uint, self.big_int.len), + @intCast(c_uint, self.big_int.len()), @ptrCast([*]u64, self.big_int.limbs.ptr), ); } else { @compileError("std.math.Big.Int.Limb size does not match LLVM"); }; - return if (self.big_int.positive) unsigned_val else llvm.ConstNeg(unsigned_val); + return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val); }, Type.Id.ComptimeInt => unreachable, else => unreachable, diff --git a/src/bigint.cpp b/src/bigint.cpp index d3178c35c6..dcd9dfc0bd 100644 --- a/src/bigint.cpp +++ b/src/bigint.cpp @@ -1410,12 +1410,19 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) { } dest->digit_count = op1->digit_count - digit_shift_count; - dest->data.digits = allocate<uint64_t>(dest->digit_count); + uint64_t *digits; + if (dest->digit_count == 1) { + digits = &dest->data.digit; + } else { + digits = allocate<uint64_t>(dest->digit_count); + dest->data.digits = digits; + } + uint64_t carry = 0; for (size_t op_digit_index = op1->digit_count - 1;;) { uint64_t digit = op1_digits[op_digit_index]; size_t dest_digit_index = op_digit_index - digit_shift_count; - dest->data.digits[dest_digit_index] = carry | (digit >> leftover_shift_count); + digits[dest_digit_index] = carry | (digit >> leftover_shift_count); carry = digit << (64 - leftover_shift_count); if (dest_digit_index == 0) { break; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 568344fc09..7d21787809 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -424,7 +424,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { } static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) { - if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) { + if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows && g->is_dynamic) { LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass); } } diff --git a/src/link.cpp b/src/link.cpp index d6093581f7..78e549c80b 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1101,6 +1101,16 @@ static void construct_linker_job_wasm(LinkJob *lj) { for (size_t i = 0; i < g->link_objects.length; i += 1) { lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); } + + if (g->out_type == OutTypeExe) { + if (g->libc_link_lib == nullptr) { + Buf *builtin_a_path = build_a(g, "builtin"); + lj->args.append(buf_ptr(builtin_a_path)); + } + + Buf *compiler_rt_o_path = build_compiler_rt(g); + lj->args.append(buf_ptr(compiler_rt_o_path)); + } } static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) { @@ -1416,18 +1426,6 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) { } } -static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) { - if (platform->major < major) { - return true; - } else if (platform->major > major) { - return false; - } - if (platform->minor < minor) { - return true; - } - return false; -} - static void construct_linker_job_macho(LinkJob *lj) { CodeGen *g = lj->codegen; @@ -1552,16 +1550,6 @@ static void construct_linker_job_macho(LinkJob *lj) { lj->args.append("dynamic_lookup"); } - if (platform.kind == MacOS) { - if (darwin_version_lt(&platform, 10, 5)) { - lj->args.append("-lgcc_s.10.4"); - } else if (darwin_version_lt(&platform, 10, 6)) { - lj->args.append("-lgcc_s.10.5"); - } - } else { - zig_panic("TODO"); - } - for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) { lj->args.append("-framework"); lj->args.append(buf_ptr(g->darwin_frameworks.at(i))); diff --git a/src/main.cpp b/src/main.cpp index bd3d574956..85e5b0c042 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1144,14 +1144,15 @@ int main(int argc, char **argv) { codegen_print_timing_report(g, stdout); if (cmd == CmdRun) { + const char *exec_path = buf_ptr(&g->output_file_path); ZigList<const char*> args = {0}; + + args.append(exec_path); if (runtime_args_start != -1) { for (int i = runtime_args_start; i < argc; ++i) { args.append(argv[i]); } } - - const char *exec_path = buf_ptr(&g->output_file_path); args.append(nullptr); os_execv(exec_path, args.items); diff --git a/src/target.cpp b/src/target.cpp index dda8188765..3b4265359c 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -894,10 +894,25 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { case CIntTypeCount: zig_unreachable(); } + case OsIOS: + switch (id) { + case CIntTypeShort: + case CIntTypeUShort: + return 16; + case CIntTypeInt: + case CIntTypeUInt: + return 32; + case CIntTypeLong: + case CIntTypeULong: + case CIntTypeLongLong: + case CIntTypeULongLong: + return 64; + case CIntTypeCount: + zig_unreachable(); + } case OsAnanas: case OsCloudABI: case OsDragonFly: - case OsIOS: case OsKFreeBSD: case OsLv2: case OsSolaris: diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 8abd66c0ff..5307e3030d 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -112,7 +112,7 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren static TransScopeBlock *trans_scope_block_find(TransScope *scope); -static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl); +static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl); static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl); static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl); @@ -122,9 +122,9 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st TransScope **out_node_scope); static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node); static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval); -static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc); +static AstNode *trans_qual_type(Context *c, clang::QualType qt, ZigClangSourceLocation source_loc); static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval); -static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc); +static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, ZigClangSourceLocation source_loc); static ZigClangSourceLocation bitcast(clang::SourceLocation src) { ZigClangSourceLocation dest; @@ -143,7 +143,7 @@ static clang::QualType bitcast(ZigClangQualType src) { } ATTRIBUTE_PRINTF(3, 4) -static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) { +static void emit_warning(Context *c, ZigClangSourceLocation sl, const char *format, ...) { if (!c->warnings_on) { return; } @@ -153,7 +153,6 @@ static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, cons Buf *msg = buf_vprintf(format, ap); va_end(ap); - ZigClangSourceLocation sl = bitcast(clang_sl); const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager, ZigClangSourceManager_getSpellingLoc(c->source_manager, sl)); Buf *path; @@ -489,11 +488,6 @@ static Buf *string_ref_to_buf(llvm::StringRef string_ref) { return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size()); } -static const char *decl_name(const clang::Decl *decl) { - const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl); - return (const char *)named_decl->getName().bytes_begin(); -} - static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) { AstNode *node = trans_create_node(c, NodeTypeIntLiteral); node->data.int_literal.bigint = allocate<BigInt>(1); @@ -539,7 +533,7 @@ static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const } static AstNode *get_expr_type(Context *c, const clang::Expr *expr) { - return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getBeginLoc()); + return trans_qual_type(c, get_expr_qual_type(c, expr), bitcast(expr->getBeginLoc())); } static bool qual_types_equal(clang::QualType t1, clang::QualType t2) { @@ -598,7 +592,7 @@ static bool qual_type_is_fn_ptr(clang::QualType qt) { return false; } -static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) { +static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, ZigClangSourceLocation source_loc) { const clang::Type *ty = qt.getTypePtr(); switch (ty->getTypeClass()) { case clang::Type::Builtin: @@ -622,7 +616,7 @@ static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, c { const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); - const char *type_name = decl_name(typedef_decl); + const char *type_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl); if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) { return 8; } else if (strcmp(type_name, "uint16_t") == 0 || strcmp(type_name, "int16_t") == 0) { @@ -643,7 +637,7 @@ static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, c static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt, - const clang::SourceLocation &source_loc) + ZigClangSourceLocation source_loc) { uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc); if (int_bit_width != 0) { @@ -688,7 +682,7 @@ static bool qual_type_child_is_fn_proto(const clang::QualType &qt) { return false; } -static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type, +static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location, clang::QualType dest_type, clang::QualType src_type, AstNode *expr) { // The only way void pointer casts are valid C code, is if @@ -788,7 +782,7 @@ static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) { } } -static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) { +static bool type_is_opaque(Context *c, const clang::Type *ty, ZigClangSourceLocation source_loc) { switch (ty->getTypeClass()) { case clang::Type::Builtin: { const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); @@ -812,7 +806,7 @@ static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::Sourc } } -static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) { +static AstNode *trans_type(Context *c, const clang::Type *ty, ZigClangSourceLocation source_loc) { switch (ty->getTypeClass()) { case clang::Type::Builtin: { @@ -1129,8 +1123,8 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc } case clang::Type::Record: { - const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty); - return resolve_record_decl(c, record_ty->getDecl()); + const ZigClangRecordType *record_ty = reinterpret_cast<const ZigClangRecordType*>(ty); + return resolve_record_decl(c, ZigClangRecordType_getDecl(record_ty)); } case clang::Type::Enum: { @@ -1217,7 +1211,7 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc zig_unreachable(); } -static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) { +static AstNode *trans_qual_type(Context *c, clang::QualType qt, ZigClangSourceLocation source_loc) { return trans_type(c, qt.getTypePtr(), source_loc); } @@ -1289,7 +1283,7 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::Re static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const clang::IntegerLiteral *stmt) { clang::Expr::EvalResult result; if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) { - emit_warning(c, stmt->getBeginLoc(), "invalid integer literal"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "invalid integer literal"); return nullptr; } AstNode *node = trans_create_node_apint(c, result.Val.getInt()); @@ -1301,10 +1295,10 @@ static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const cl if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen, *reinterpret_cast<clang::ASTContext *>(c->ctx))) { - emit_warning(c, expr->getBeginLoc(), "invalid constant expression"); + emit_warning(c, bitcast(expr->getBeginLoc()), "invalid constant expression"); return nullptr; } - AstNode *node = trans_ap_value(c, &result.Val, expr->getType(), expr->getBeginLoc()); + AstNode *node = trans_ap_value(c, &result.Val, expr->getType(), bitcast(expr->getBeginLoc())); return maybe_suppress_result(c, result_used, node); } @@ -1417,7 +1411,7 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type, clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr) { - const clang::SourceLocation &rhs_location = rhs_expr->getBeginLoc(); + ZigClangSourceLocation rhs_location = bitcast(rhs_expr->getBeginLoc()); AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location); // lhs >> u5(rh) @@ -1434,13 +1428,13 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::Qual static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) { switch (stmt->getOpcode()) { case clang::BO_PtrMemD: - emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemD"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C binary operators: BO_PtrMemD"); return nullptr; case clang::BO_PtrMemI: - emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemI"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C binary operators: BO_PtrMemI"); return nullptr; case clang::BO_Cmp: - emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_Cmp"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C binary operators: BO_Cmp"); return nullptr; case clang::BO_Mul: { AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), @@ -1584,7 +1578,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope, const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) { - const clang::SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc(); + ZigClangSourceLocation rhs_location = bitcast(stmt->getRHS()->getBeginLoc()); AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); @@ -1733,13 +1727,13 @@ static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_use else return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult); case clang::BO_DivAssign: - emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_DivAssign"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C compound assign operators: BO_DivAssign"); return nullptr; case clang::BO_RemAssign: - emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_RemAssign"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C compound assign operators: BO_RemAssign"); return nullptr; case clang::BO_Cmp: - emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_Cmp"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C compound assign operators: BO_Cmp"); return nullptr; case clang::BO_AddAssign: if (qual_type_has_wrapping_overflow(c, stmt->getType())) @@ -1798,7 +1792,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); if (target_node == nullptr) return nullptr; - AstNode *node = trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), + AstNode *node = trans_c_cast(c, bitcast(stmt->getExprLoc()), stmt->getType(), stmt->getSubExpr()->getType(), target_node); return maybe_suppress_result(c, result_used, node); } @@ -1832,160 +1826,160 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra case clang::CK_NoOp: return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); case clang::CK_Dependent: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dependent"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_Dependent"); return nullptr; case clang::CK_LValueBitCast: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_LValueBitCast"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_LValueBitCast"); return nullptr; case clang::CK_BaseToDerived: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerived"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_BaseToDerived"); return nullptr; case clang::CK_DerivedToBase: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBase"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_DerivedToBase"); return nullptr; case clang::CK_UncheckedDerivedToBase: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UncheckedDerivedToBase"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_UncheckedDerivedToBase"); return nullptr; case clang::CK_Dynamic: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dynamic"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_Dynamic"); return nullptr; case clang::CK_ToUnion: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToUnion"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_ToUnion"); return nullptr; case clang::CK_NullToMemberPointer: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NullToMemberPointer"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_NullToMemberPointer"); return nullptr; case clang::CK_BaseToDerivedMemberPointer: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_BaseToDerivedMemberPointer"); return nullptr; case clang::CK_DerivedToBaseMemberPointer: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_DerivedToBaseMemberPointer"); return nullptr; case clang::CK_MemberPointerToBoolean: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_MemberPointerToBoolean"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_MemberPointerToBoolean"); return nullptr; case clang::CK_ReinterpretMemberPointer: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ReinterpretMemberPointer"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_ReinterpretMemberPointer"); return nullptr; case clang::CK_UserDefinedConversion: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UserDefinedConversion"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_UserDefinedConversion"); return nullptr; case clang::CK_ConstructorConversion: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ConstructorConversion"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion"); return nullptr; case clang::CK_IntegralToPointer: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToPointer"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToPointer"); return nullptr; case clang::CK_PointerToIntegral: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_PointerToIntegral"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_PointerToIntegral"); return nullptr; case clang::CK_PointerToBoolean: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_PointerToBoolean"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_PointerToBoolean"); return nullptr; case clang::CK_ToVoid: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ToVoid"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ToVoid"); return nullptr; case clang::CK_VectorSplat: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_VectorSplat"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat"); return nullptr; case clang::CK_IntegralToBoolean: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToBoolean"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToBoolean"); return nullptr; case clang::CK_IntegralToFloating: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToFloating"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToFloating"); return nullptr; case clang::CK_FixedPointCast: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FixedPointCast"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointCast"); return nullptr; case clang::CK_FixedPointToBoolean: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FixedPointToBoolean"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean"); return nullptr; case clang::CK_FloatingToIntegral: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingToIntegral"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToIntegral"); return nullptr; case clang::CK_FloatingToBoolean: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingToBoolean"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean"); return nullptr; case clang::CK_BooleanToSignedIntegral: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BooleanToSignedIntegral"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BooleanToSignedIntegral"); return nullptr; case clang::CK_FloatingCast: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingCast"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingCast"); return nullptr; case clang::CK_CPointerToObjCPointerCast: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_CPointerToObjCPointerCast"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_CPointerToObjCPointerCast"); return nullptr; case clang::CK_BlockPointerToObjCPointerCast: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BlockPointerToObjCPointerCast"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BlockPointerToObjCPointerCast"); return nullptr; case clang::CK_AnyPointerToBlockPointerCast: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AnyPointerToBlockPointerCast"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AnyPointerToBlockPointerCast"); return nullptr; case clang::CK_ObjCObjectLValueCast: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ObjCObjectLValueCast"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ObjCObjectLValueCast"); return nullptr; case clang::CK_FloatingRealToComplex: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingRealToComplex"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingRealToComplex"); return nullptr; case clang::CK_FloatingComplexToReal: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToReal"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToReal"); return nullptr; case clang::CK_FloatingComplexToBoolean: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToBoolean"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToBoolean"); return nullptr; case clang::CK_FloatingComplexCast: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexCast"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexCast"); return nullptr; case clang::CK_FloatingComplexToIntegralComplex: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToIntegralComplex"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToIntegralComplex"); return nullptr; case clang::CK_IntegralRealToComplex: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralRealToComplex"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralRealToComplex"); return nullptr; case clang::CK_IntegralComplexToReal: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToReal"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToReal"); return nullptr; case clang::CK_IntegralComplexToBoolean: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToBoolean"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToBoolean"); return nullptr; case clang::CK_IntegralComplexCast: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexCast"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexCast"); return nullptr; case clang::CK_IntegralComplexToFloatingComplex: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToFloatingComplex"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToFloatingComplex"); return nullptr; case clang::CK_ARCProduceObject: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCProduceObject"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCProduceObject"); return nullptr; case clang::CK_ARCConsumeObject: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCConsumeObject"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCConsumeObject"); return nullptr; case clang::CK_ARCReclaimReturnedObject: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCReclaimReturnedObject"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCReclaimReturnedObject"); return nullptr; case clang::CK_ARCExtendBlockObject: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCExtendBlockObject"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCExtendBlockObject"); return nullptr; case clang::CK_AtomicToNonAtomic: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AtomicToNonAtomic"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AtomicToNonAtomic"); return nullptr; case clang::CK_NonAtomicToAtomic: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_NonAtomicToAtomic"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_NonAtomicToAtomic"); return nullptr; case clang::CK_CopyAndAutoreleaseBlockObject: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_CopyAndAutoreleaseBlockObject"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_CopyAndAutoreleaseBlockObject"); return nullptr; case clang::CK_BuiltinFnToFnPtr: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BuiltinFnToFnPtr"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BuiltinFnToFnPtr"); return nullptr; case clang::CK_ZeroToOCLOpaqueType: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ZeroToOCLOpaqueType"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ZeroToOCLOpaqueType"); return nullptr; case clang::CK_AddressSpaceConversion: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AddressSpaceConversion"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AddressSpaceConversion"); return nullptr; case clang::CK_IntToOCLSampler: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntToOCLSampler"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntToOCLSampler"); return nullptr; } zig_unreachable(); @@ -1993,7 +1987,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) { const clang::ValueDecl *value_decl = stmt->getDecl(); - Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl)); + Buf *c_symbol_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)value_decl)); Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name); if (lrval == TransLValue) { c->ptr_params.put(zig_symbol_name, true); @@ -2148,7 +2142,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc return trans_create_node_ptr_deref(c, unwrapped); } case clang::UO_Plus: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Plus"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Plus"); return nullptr; case clang::UO_Minus: { @@ -2174,7 +2168,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc node->data.bin_op_expr.bin_op = BinOpTypeSubWrap; return node; } else { - emit_warning(c, stmt->getBeginLoc(), "C negation with non float non integer"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "C negation with non float non integer"); return nullptr; } } @@ -2197,15 +2191,15 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node); } case clang::UO_Real: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Real"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Real"); return nullptr; case clang::UO_Imag: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Imag"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Imag"); return nullptr; case clang::UO_Extension: return trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue); case clang::UO_Coawait: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Coawait"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Coawait"); return nullptr; } zig_unreachable(); @@ -2235,11 +2229,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const clang::D } else { init_node = trans_create_node(c, NodeTypeUndefinedLiteral); } - AstNode *type_node = trans_qual_type(c, qual_type, stmt->getBeginLoc()); + AstNode *type_node = trans_qual_type(c, qual_type, bitcast(stmt->getBeginLoc())); if (type_node == nullptr) return ErrorUnexpected; - Buf *c_symbol_name = buf_create_from_str(decl_name(var_decl)); + Buf *c_symbol_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)var_decl)); TransScopeVar *var_scope = trans_scope_var_create(c, scope, c_symbol_name); scope = &var_scope->base; @@ -2251,223 +2245,223 @@ static int trans_local_declaration(Context *c, TransScope *scope, const clang::D continue; } case clang::Decl::AccessSpec: - emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind AccessSpec"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle decl kind AccessSpec"); return ErrorUnexpected; case clang::Decl::Block: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Block"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Block"); return ErrorUnexpected; case clang::Decl::Captured: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Captured"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Captured"); return ErrorUnexpected; case clang::Decl::ClassScopeFunctionSpecialization: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassScopeFunctionSpecialization"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassScopeFunctionSpecialization"); return ErrorUnexpected; case clang::Decl::Empty: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Empty"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Empty"); return ErrorUnexpected; case clang::Decl::Export: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Export"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Export"); return ErrorUnexpected; case clang::Decl::ExternCContext: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExternCContext"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ExternCContext"); return ErrorUnexpected; case clang::Decl::FileScopeAsm: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C FileScopeAsm"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FileScopeAsm"); return ErrorUnexpected; case clang::Decl::Friend: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Friend"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Friend"); return ErrorUnexpected; case clang::Decl::FriendTemplate: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C FriendTemplate"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FriendTemplate"); return ErrorUnexpected; case clang::Decl::Import: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Import"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Import"); return ErrorUnexpected; case clang::Decl::LinkageSpec: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C LinkageSpec"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C LinkageSpec"); return ErrorUnexpected; case clang::Decl::Label: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Label"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Label"); return ErrorUnexpected; case clang::Decl::Namespace: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Namespace"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Namespace"); return ErrorUnexpected; case clang::Decl::NamespaceAlias: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C NamespaceAlias"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C NamespaceAlias"); return ErrorUnexpected; case clang::Decl::ObjCCompatibleAlias: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCCompatibleAlias"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCCompatibleAlias"); return ErrorUnexpected; case clang::Decl::ObjCCategory: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCCategory"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCCategory"); return ErrorUnexpected; case clang::Decl::ObjCCategoryImpl: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCCategoryImpl"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCCategoryImpl"); return ErrorUnexpected; case clang::Decl::ObjCImplementation: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCImplementation"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCImplementation"); return ErrorUnexpected; case clang::Decl::ObjCInterface: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCInterface"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCInterface"); return ErrorUnexpected; case clang::Decl::ObjCProtocol: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProtocol"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCProtocol"); return ErrorUnexpected; case clang::Decl::ObjCMethod: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCMethod"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCMethod"); return ErrorUnexpected; case clang::Decl::ObjCProperty: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProperty"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCProperty"); return ErrorUnexpected; case clang::Decl::BuiltinTemplate: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C BuiltinTemplate"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C BuiltinTemplate"); return ErrorUnexpected; case clang::Decl::ClassTemplate: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassTemplate"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassTemplate"); return ErrorUnexpected; case clang::Decl::FunctionTemplate: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C FunctionTemplate"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FunctionTemplate"); return ErrorUnexpected; case clang::Decl::TypeAliasTemplate: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeAliasTemplate"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TypeAliasTemplate"); return ErrorUnexpected; case clang::Decl::VarTemplate: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C VarTemplate"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VarTemplate"); return ErrorUnexpected; case clang::Decl::TemplateTemplateParm: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C TemplateTemplateParm"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TemplateTemplateParm"); return ErrorUnexpected; case clang::Decl::Enum: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Enum"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Enum"); return ErrorUnexpected; case clang::Decl::Record: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Record"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Record"); return ErrorUnexpected; case clang::Decl::CXXRecord: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXRecord"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXRecord"); return ErrorUnexpected; case clang::Decl::ClassTemplateSpecialization: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassTemplateSpecialization"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassTemplateSpecialization"); return ErrorUnexpected; case clang::Decl::ClassTemplatePartialSpecialization: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassTemplatePartialSpecialization"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassTemplatePartialSpecialization"); return ErrorUnexpected; case clang::Decl::TemplateTypeParm: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C TemplateTypeParm"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TemplateTypeParm"); return ErrorUnexpected; case clang::Decl::ObjCTypeParam: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCTypeParam"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCTypeParam"); return ErrorUnexpected; case clang::Decl::TypeAlias: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeAlias"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TypeAlias"); return ErrorUnexpected; case clang::Decl::Typedef: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Typedef"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Typedef"); return ErrorUnexpected; case clang::Decl::UnresolvedUsingTypename: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedUsingTypename"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UnresolvedUsingTypename"); return ErrorUnexpected; case clang::Decl::Using: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Using"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Using"); return ErrorUnexpected; case clang::Decl::UsingDirective: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C UsingDirective"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UsingDirective"); return ErrorUnexpected; case clang::Decl::UsingPack: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C UsingPack"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UsingPack"); return ErrorUnexpected; case clang::Decl::UsingShadow: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C UsingShadow"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UsingShadow"); return ErrorUnexpected; case clang::Decl::ConstructorUsingShadow: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ConstructorUsingShadow"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ConstructorUsingShadow"); return ErrorUnexpected; case clang::Decl::Binding: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Binding"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Binding"); return ErrorUnexpected; case clang::Decl::Field: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Field"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Field"); return ErrorUnexpected; case clang::Decl::ObjCAtDefsField: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtDefsField"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAtDefsField"); return ErrorUnexpected; case clang::Decl::ObjCIvar: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIvar"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCIvar"); return ErrorUnexpected; case clang::Decl::Function: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Function"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Function"); return ErrorUnexpected; case clang::Decl::CXXDeductionGuide: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDeductionGuide"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDeductionGuide"); return ErrorUnexpected; case clang::Decl::CXXMethod: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXMethod"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXMethod"); return ErrorUnexpected; case clang::Decl::CXXConstructor: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstructor"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXConstructor"); return ErrorUnexpected; case clang::Decl::CXXConversion: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConversion"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXConversion"); return ErrorUnexpected; case clang::Decl::CXXDestructor: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDestructor"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDestructor"); return ErrorUnexpected; case clang::Decl::MSProperty: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSProperty"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C MSProperty"); return ErrorUnexpected; case clang::Decl::NonTypeTemplateParm: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C NonTypeTemplateParm"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C NonTypeTemplateParm"); return ErrorUnexpected; case clang::Decl::Decomposition: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C Decomposition"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Decomposition"); return ErrorUnexpected; case clang::Decl::ImplicitParam: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImplicitParam"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ImplicitParam"); return ErrorUnexpected; case clang::Decl::OMPCapturedExpr: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCapturedExpr"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPCapturedExpr"); return ErrorUnexpected; case clang::Decl::ParmVar: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ParmVar"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ParmVar"); return ErrorUnexpected; case clang::Decl::VarTemplateSpecialization: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C VarTemplateSpecialization"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VarTemplateSpecialization"); return ErrorUnexpected; case clang::Decl::VarTemplatePartialSpecialization: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C VarTemplatePartialSpecialization"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VarTemplatePartialSpecialization"); return ErrorUnexpected; case clang::Decl::EnumConstant: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C EnumConstant"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C EnumConstant"); return ErrorUnexpected; case clang::Decl::IndirectField: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C IndirectField"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C IndirectField"); return ErrorUnexpected; case clang::Decl::OMPDeclareReduction: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDeclareReduction"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPDeclareReduction"); return ErrorUnexpected; case clang::Decl::UnresolvedUsingValue: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedUsingValue"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UnresolvedUsingValue"); return ErrorUnexpected; case clang::Decl::OMPRequires: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPRequires"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPRequires"); return ErrorUnexpected; case clang::Decl::OMPThreadPrivate: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPThreadPrivate"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPThreadPrivate"); return ErrorUnexpected; case clang::Decl::ObjCPropertyImpl: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCPropertyImpl"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCPropertyImpl"); return ErrorUnexpected; case clang::Decl::PragmaComment: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C PragmaComment"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C PragmaComment"); return ErrorUnexpected; case clang::Decl::PragmaDetectMismatch: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C PragmaDetectMismatch"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C PragmaDetectMismatch"); return ErrorUnexpected; case clang::Decl::StaticAssert: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C StaticAssert"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C StaticAssert"); return ErrorUnexpected; case clang::Decl::TranslationUnit: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C TranslationUnit"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TranslationUnit"); return ErrorUnexpected; } zig_unreachable(); @@ -2689,7 +2683,7 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty); switch (elaborated_ty->getKeyword()) { case clang::ETK_Enum: { - AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginLoc()); + AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), bitcast(expr->getBeginLoc())); return to_enum_zero_cmp(c, res, enum_type); } case clang::ETK_Struct: @@ -2846,7 +2840,7 @@ static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope container_node = trans_create_node_unwrap_null(c, container_node); } - const char *name = decl_name(stmt->getMemberDecl()); + const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)stmt->getMemberDecl()); AstNode *node = trans_create_node_field_access_str(c, container_node, name); return maybe_suppress_result(c, result_used, node); @@ -2875,7 +2869,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran if (sub_expr_node == nullptr) return nullptr; - AstNode *cast = trans_c_cast(c, stmt->getBeginLoc(), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node); + AstNode *cast = trans_c_cast(c, bitcast(stmt->getBeginLoc()), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node); if (cast == nullptr) return nullptr; @@ -2885,7 +2879,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryExprOrTypeTraitExpr *stmt) { - AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getBeginLoc()); + AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), bitcast(stmt->getBeginLoc())); if (type_node == nullptr) return nullptr; @@ -3092,7 +3086,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang:: *out_node = nullptr; if (stmt->getRHS() != nullptr) { - emit_warning(c, stmt->getBeginLoc(), "TODO support GNU switch case a ... b extension"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support GNU switch case a ... b extension"); return ErrorUnexpected; } @@ -3177,13 +3171,13 @@ static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransSc return maybe_suppress_result(c, result_used, node); } case clang::StringLiteral::UTF16: - emit_warning(c, stmt->getBeginLoc(), "TODO support UTF16 string literals"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF16 string literals"); return nullptr; case clang::StringLiteral::UTF32: - emit_warning(c, stmt->getBeginLoc(), "TODO support UTF32 string literals"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF32 string literals"); return nullptr; case clang::StringLiteral::Wide: - emit_warning(c, stmt->getBeginLoc(), "TODO support wide string literals"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support wide string literals"); return nullptr; } zig_unreachable(); @@ -3328,505 +3322,505 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st return wrap_stmt(out_node, out_child_scope, scope, trans_stmt_expr(c, result_used, scope, (const clang::StmtExpr *)stmt, out_node_scope)); case clang::Stmt::NoStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C NoStmtClass"); return ErrorUnexpected; case clang::Stmt::GCCAsmStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C GCCAsmStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C GCCAsmStmtClass"); return ErrorUnexpected; case clang::Stmt::MSAsmStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSAsmStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C MSAsmStmtClass"); return ErrorUnexpected; case clang::Stmt::AttributedStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C AttributedStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C AttributedStmtClass"); return ErrorUnexpected; case clang::Stmt::CXXCatchStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXCatchStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXCatchStmtClass"); return ErrorUnexpected; case clang::Stmt::CXXForRangeStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXForRangeStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXForRangeStmtClass"); return ErrorUnexpected; case clang::Stmt::CXXTryStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTryStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXTryStmtClass"); return ErrorUnexpected; case clang::Stmt::CapturedStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CapturedStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CapturedStmtClass"); return ErrorUnexpected; case clang::Stmt::CoreturnStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoreturnStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CoreturnStmtClass"); return ErrorUnexpected; case clang::Stmt::CoroutineBodyStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoroutineBodyStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CoroutineBodyStmtClass"); return ErrorUnexpected; case clang::Stmt::BinaryConditionalOperatorClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C BinaryConditionalOperatorClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C BinaryConditionalOperatorClass"); return ErrorUnexpected; case clang::Stmt::AddrLabelExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C AddrLabelExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C AddrLabelExprClass"); return ErrorUnexpected; case clang::Stmt::ArrayInitIndexExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitIndexExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ArrayInitIndexExprClass"); return ErrorUnexpected; case clang::Stmt::ArrayInitLoopExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitLoopExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ArrayInitLoopExprClass"); return ErrorUnexpected; case clang::Stmt::ArrayTypeTraitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayTypeTraitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ArrayTypeTraitExprClass"); return ErrorUnexpected; case clang::Stmt::AsTypeExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C AsTypeExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C AsTypeExprClass"); return ErrorUnexpected; case clang::Stmt::AtomicExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C AtomicExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C AtomicExprClass"); return ErrorUnexpected; case clang::Stmt::BlockExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C BlockExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C BlockExprClass"); return ErrorUnexpected; case clang::Stmt::CXXBindTemporaryExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBindTemporaryExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXBindTemporaryExprClass"); return ErrorUnexpected; case clang::Stmt::CXXBoolLiteralExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBoolLiteralExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXBoolLiteralExprClass"); return ErrorUnexpected; case clang::Stmt::CXXConstructExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstructExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXConstructExprClass"); return ErrorUnexpected; case clang::Stmt::CXXTemporaryObjectExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTemporaryObjectExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXTemporaryObjectExprClass"); return ErrorUnexpected; case clang::Stmt::CXXDefaultArgExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultArgExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDefaultArgExprClass"); return ErrorUnexpected; case clang::Stmt::CXXDefaultInitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultInitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDefaultInitExprClass"); return ErrorUnexpected; case clang::Stmt::CXXDeleteExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDeleteExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDeleteExprClass"); return ErrorUnexpected; case clang::Stmt::CXXDependentScopeMemberExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDependentScopeMemberExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDependentScopeMemberExprClass"); return ErrorUnexpected; case clang::Stmt::CXXFoldExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFoldExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXFoldExprClass"); return ErrorUnexpected; case clang::Stmt::CXXInheritedCtorInitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXInheritedCtorInitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXInheritedCtorInitExprClass"); return ErrorUnexpected; case clang::Stmt::CXXNewExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNewExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXNewExprClass"); return ErrorUnexpected; case clang::Stmt::CXXNoexceptExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNoexceptExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXNoexceptExprClass"); return ErrorUnexpected; case clang::Stmt::CXXNullPtrLiteralExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNullPtrLiteralExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXNullPtrLiteralExprClass"); return ErrorUnexpected; case clang::Stmt::CXXPseudoDestructorExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXPseudoDestructorExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXPseudoDestructorExprClass"); return ErrorUnexpected; case clang::Stmt::CXXScalarValueInitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXScalarValueInitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXScalarValueInitExprClass"); return ErrorUnexpected; case clang::Stmt::CXXStdInitializerListExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStdInitializerListExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXStdInitializerListExprClass"); return ErrorUnexpected; case clang::Stmt::CXXThisExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThisExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXThisExprClass"); return ErrorUnexpected; case clang::Stmt::CXXThrowExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThrowExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXThrowExprClass"); return ErrorUnexpected; case clang::Stmt::CXXTypeidExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTypeidExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXTypeidExprClass"); return ErrorUnexpected; case clang::Stmt::CXXUnresolvedConstructExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUnresolvedConstructExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXUnresolvedConstructExprClass"); return ErrorUnexpected; case clang::Stmt::CXXUuidofExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUuidofExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXUuidofExprClass"); return ErrorUnexpected; case clang::Stmt::CUDAKernelCallExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CUDAKernelCallExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CUDAKernelCallExprClass"); return ErrorUnexpected; case clang::Stmt::CXXMemberCallExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXMemberCallExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXMemberCallExprClass"); return ErrorUnexpected; case clang::Stmt::CXXOperatorCallExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXOperatorCallExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXOperatorCallExprClass"); return ErrorUnexpected; case clang::Stmt::UserDefinedLiteralClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C UserDefinedLiteralClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UserDefinedLiteralClass"); return ErrorUnexpected; case clang::Stmt::CXXFunctionalCastExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFunctionalCastExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXFunctionalCastExprClass"); return ErrorUnexpected; case clang::Stmt::CXXConstCastExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstCastExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXConstCastExprClass"); return ErrorUnexpected; case clang::Stmt::CXXDynamicCastExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDynamicCastExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDynamicCastExprClass"); return ErrorUnexpected; case clang::Stmt::CXXReinterpretCastExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXReinterpretCastExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXReinterpretCastExprClass"); return ErrorUnexpected; case clang::Stmt::CXXStaticCastExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStaticCastExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXStaticCastExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCBridgedCastExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBridgedCastExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCBridgedCastExprClass"); return ErrorUnexpected; case clang::Stmt::CharacterLiteralClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CharacterLiteralClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CharacterLiteralClass"); return ErrorUnexpected; case clang::Stmt::ChooseExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ChooseExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ChooseExprClass"); return ErrorUnexpected; case clang::Stmt::CompoundLiteralExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CompoundLiteralExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CompoundLiteralExprClass"); return ErrorUnexpected; case clang::Stmt::ConvertVectorExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ConvertVectorExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ConvertVectorExprClass"); return ErrorUnexpected; case clang::Stmt::CoawaitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoawaitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CoawaitExprClass"); return ErrorUnexpected; case clang::Stmt::CoyieldExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoyieldExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CoyieldExprClass"); return ErrorUnexpected; case clang::Stmt::DependentCoawaitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentCoawaitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C DependentCoawaitExprClass"); return ErrorUnexpected; case clang::Stmt::DependentScopeDeclRefExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentScopeDeclRefExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C DependentScopeDeclRefExprClass"); return ErrorUnexpected; case clang::Stmt::DesignatedInitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C DesignatedInitExprClass"); return ErrorUnexpected; case clang::Stmt::DesignatedInitUpdateExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitUpdateExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C DesignatedInitUpdateExprClass"); return ErrorUnexpected; case clang::Stmt::ExpressionTraitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExpressionTraitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ExpressionTraitExprClass"); return ErrorUnexpected; case clang::Stmt::ExtVectorElementExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExtVectorElementExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ExtVectorElementExprClass"); return ErrorUnexpected; case clang::Stmt::FixedPointLiteralClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C FixedPointLiteralClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FixedPointLiteralClass"); return ErrorUnexpected; case clang::Stmt::FloatingLiteralClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C FloatingLiteralClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FloatingLiteralClass"); return ErrorUnexpected; case clang::Stmt::ExprWithCleanupsClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExprWithCleanupsClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ExprWithCleanupsClass"); return ErrorUnexpected; case clang::Stmt::FunctionParmPackExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C FunctionParmPackExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FunctionParmPackExprClass"); return ErrorUnexpected; case clang::Stmt::GNUNullExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C GNUNullExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C GNUNullExprClass"); return ErrorUnexpected; case clang::Stmt::GenericSelectionExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C GenericSelectionExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C GenericSelectionExprClass"); return ErrorUnexpected; case clang::Stmt::ImaginaryLiteralClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImaginaryLiteralClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ImaginaryLiteralClass"); return ErrorUnexpected; case clang::Stmt::ImplicitValueInitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImplicitValueInitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ImplicitValueInitExprClass"); return ErrorUnexpected; case clang::Stmt::InitListExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C InitListExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C InitListExprClass"); return ErrorUnexpected; case clang::Stmt::LambdaExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C LambdaExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C LambdaExprClass"); return ErrorUnexpected; case clang::Stmt::MSPropertyRefExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertyRefExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C MSPropertyRefExprClass"); return ErrorUnexpected; case clang::Stmt::MSPropertySubscriptExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertySubscriptExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C MSPropertySubscriptExprClass"); return ErrorUnexpected; case clang::Stmt::MaterializeTemporaryExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C MaterializeTemporaryExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C MaterializeTemporaryExprClass"); return ErrorUnexpected; case clang::Stmt::NoInitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoInitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C NoInitExprClass"); return ErrorUnexpected; case clang::Stmt::OMPArraySectionExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPArraySectionExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPArraySectionExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCArrayLiteralClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCArrayLiteralClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCArrayLiteralClass"); return ErrorUnexpected; case clang::Stmt::ObjCAvailabilityCheckExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAvailabilityCheckExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAvailabilityCheckExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCBoolLiteralExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoolLiteralExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCBoolLiteralExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCBoxedExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoxedExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCBoxedExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCDictionaryLiteralClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCDictionaryLiteralClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCDictionaryLiteralClass"); return ErrorUnexpected; case clang::Stmt::ObjCEncodeExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCEncodeExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCEncodeExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCIndirectCopyRestoreExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIndirectCopyRestoreExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCIndirectCopyRestoreExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCIsaExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIsaExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCIsaExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCIvarRefExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIvarRefExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCIvarRefExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCMessageExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCMessageExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCMessageExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCPropertyRefExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCPropertyRefExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCPropertyRefExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCProtocolExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProtocolExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCProtocolExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCSelectorExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSelectorExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCSelectorExprClass"); return ErrorUnexpected; case clang::Stmt::ObjCStringLiteralClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCStringLiteralClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCStringLiteralClass"); return ErrorUnexpected; case clang::Stmt::ObjCSubscriptRefExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSubscriptRefExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCSubscriptRefExprClass"); return ErrorUnexpected; case clang::Stmt::OffsetOfExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OffsetOfExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OffsetOfExprClass"); return ErrorUnexpected; case clang::Stmt::OpaqueValueExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OpaqueValueExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OpaqueValueExprClass"); return ErrorUnexpected; case clang::Stmt::UnresolvedLookupExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedLookupExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UnresolvedLookupExprClass"); return ErrorUnexpected; case clang::Stmt::UnresolvedMemberExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedMemberExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UnresolvedMemberExprClass"); return ErrorUnexpected; case clang::Stmt::PackExpansionExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C PackExpansionExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C PackExpansionExprClass"); return ErrorUnexpected; case clang::Stmt::ParenListExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ParenListExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ParenListExprClass"); return ErrorUnexpected; case clang::Stmt::PseudoObjectExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C PseudoObjectExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C PseudoObjectExprClass"); return ErrorUnexpected; case clang::Stmt::ShuffleVectorExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ShuffleVectorExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ShuffleVectorExprClass"); return ErrorUnexpected; case clang::Stmt::SizeOfPackExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C SizeOfPackExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C SizeOfPackExprClass"); return ErrorUnexpected; case clang::Stmt::SubstNonTypeTemplateParmExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C SubstNonTypeTemplateParmExprClass"); return ErrorUnexpected; case clang::Stmt::SubstNonTypeTemplateParmPackExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmPackExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C SubstNonTypeTemplateParmPackExprClass"); return ErrorUnexpected; case clang::Stmt::TypeTraitExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeTraitExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TypeTraitExprClass"); return ErrorUnexpected; case clang::Stmt::TypoExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypoExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TypoExprClass"); return ErrorUnexpected; case clang::Stmt::VAArgExprClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C VAArgExprClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VAArgExprClass"); return ErrorUnexpected; case clang::Stmt::GotoStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C GotoStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C GotoStmtClass"); return ErrorUnexpected; case clang::Stmt::IndirectGotoStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C IndirectGotoStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C IndirectGotoStmtClass"); return ErrorUnexpected; case clang::Stmt::LabelStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C LabelStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C LabelStmtClass"); return ErrorUnexpected; case clang::Stmt::MSDependentExistsStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSDependentExistsStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C MSDependentExistsStmtClass"); return ErrorUnexpected; case clang::Stmt::OMPAtomicDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPAtomicDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPAtomicDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPBarrierDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPBarrierDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPBarrierDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPCancelDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancelDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPCancelDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPCancellationPointDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancellationPointDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPCancellationPointDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPCriticalDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCriticalDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPCriticalDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPFlushDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPFlushDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPFlushDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPDistributeDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPDistributeDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPDistributeParallelForDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPDistributeParallelForDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPDistributeParallelForSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPDistributeSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPDistributeSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPForDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPForDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPForSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPForSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPParallelForDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPParallelForDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPParallelForSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPParallelForSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetParallelForSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetParallelForSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetTeamsDistributeDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTaskLoopDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTaskLoopDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTaskLoopSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTaskLoopSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTeamsDistributeDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTeamsDistributeDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTeamsDistributeSimdDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPMasterDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPMasterDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPMasterDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPOrderedDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPOrderedDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPOrderedDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPParallelDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPParallelDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPParallelSectionsDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelSectionsDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPParallelSectionsDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPSectionDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPSectionDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPSectionsDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionsDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPSectionsDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPSingleDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSingleDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPSingleDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetDataDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDataDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetDataDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetEnterDataDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetEnterDataDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetEnterDataDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetExitDataDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetExitDataDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetExitDataDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetParallelDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetParallelDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetParallelForDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetParallelForDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetTeamsDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetTeamsDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTargetUpdateDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetUpdateDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTargetUpdateDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTaskDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTaskDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTaskgroupDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskgroupDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTaskgroupDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTaskwaitDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskwaitDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTaskwaitDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTaskyieldDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskyieldDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTaskyieldDirectiveClass"); return ErrorUnexpected; case clang::Stmt::OMPTeamsDirectiveClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDirectiveClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPTeamsDirectiveClass"); return ErrorUnexpected; case clang::Stmt::ObjCAtCatchStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtCatchStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAtCatchStmtClass"); return ErrorUnexpected; case clang::Stmt::ObjCAtFinallyStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtFinallyStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAtFinallyStmtClass"); return ErrorUnexpected; case clang::Stmt::ObjCAtSynchronizedStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtSynchronizedStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAtSynchronizedStmtClass"); return ErrorUnexpected; case clang::Stmt::ObjCAtThrowStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtThrowStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAtThrowStmtClass"); return ErrorUnexpected; case clang::Stmt::ObjCAtTryStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtTryStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAtTryStmtClass"); return ErrorUnexpected; case clang::Stmt::ObjCAutoreleasePoolStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAutoreleasePoolStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAutoreleasePoolStmtClass"); return ErrorUnexpected; case clang::Stmt::ObjCForCollectionStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCForCollectionStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCForCollectionStmtClass"); return ErrorUnexpected; case clang::Stmt::SEHExceptStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHExceptStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C SEHExceptStmtClass"); return ErrorUnexpected; case clang::Stmt::SEHFinallyStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHFinallyStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C SEHFinallyStmtClass"); return ErrorUnexpected; case clang::Stmt::SEHLeaveStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHLeaveStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C SEHLeaveStmtClass"); return ErrorUnexpected; case clang::Stmt::SEHTryStmtClass: - emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHTryStmtClass"); + emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C SEHTryStmtClass"); return ErrorUnexpected; } zig_unreachable(); @@ -3855,16 +3849,16 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt * } static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { - Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); + Buf *fn_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)fn_decl)); if (get_global(c, fn_name)) { // we already saw this function return; } - AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), fn_decl->getLocation()); + AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), bitcast(fn_decl->getLocation())); if (proto_node == nullptr) { - emit_warning(c, fn_decl->getLocation(), "unable to resolve prototype of function '%s'", buf_ptr(fn_name)); + emit_warning(c, bitcast(fn_decl->getLocation()), "unable to resolve prototype of function '%s'", buf_ptr(fn_name)); return; } @@ -3878,10 +3872,10 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { } else if (sc == clang::SC_Extern || sc == clang::SC_Static) { proto_node->data.fn_proto.visib_mod = c->visib_mod; } else if (sc == clang::SC_PrivateExtern) { - emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern"); + emit_warning(c, bitcast(fn_decl->getLocation()), "unsupported storage class: private extern"); return; } else { - emit_warning(c, fn_decl->getLocation(), "unsupported storage class: unknown"); + emit_warning(c, bitcast(fn_decl->getLocation()), "unsupported storage class: unknown"); return; } @@ -3890,7 +3884,7 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { AstNode *param_node = proto_node->data.fn_proto.params.at(i); const clang::ParmVarDecl *param = fn_decl->getParamDecl(i); - const char *name = decl_name(param); + const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)param); Buf *proto_param_name; if (strlen(name) != 0) { @@ -3920,7 +3914,7 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { AstNode *actual_body_node; TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node); if (result_scope == nullptr) { - emit_warning(c, fn_decl->getLocation(), "unable to translate function"); + emit_warning(c, bitcast(fn_decl->getLocation()), "unable to translate function"); return; } assert(actual_body_node != nullptr); @@ -3971,7 +3965,7 @@ static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *t } clang::QualType child_qt = typedef_decl->getUnderlyingType(); - Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); + Buf *type_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl)); if (buf_eql_str(type_name, "uint8_t")) { return resolve_typdef_as_builtin(c, typedef_decl, "u8"); @@ -4007,9 +4001,9 @@ static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *t AstNode *symbol_node = trans_create_node_symbol(c, type_name); c->decl_table.put(typedef_decl->getCanonicalDecl(), symbol_node); - AstNode *type_node = trans_qual_type(c, child_qt, typedef_decl->getLocation()); + AstNode *type_node = trans_qual_type(c, child_qt, bitcast(typedef_decl->getLocation())); if (type_node == nullptr) { - emit_warning(c, typedef_decl->getLocation(), "typedef %s - unresolved child type", buf_ptr(type_name)); + emit_warning(c, bitcast(typedef_decl->getLocation()), "typedef %s - unresolved child type", buf_ptr(type_name)); c->decl_table.put(typedef_decl, nullptr); // TODO add global var with type_name equal to @compileError("unable to resolve C type") return nullptr; @@ -4040,7 +4034,7 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) return existing_entry->value; } - const char *raw_name = decl_name(enum_decl); + const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_decl); bool is_anonymous = (raw_name[0] == 0); Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name)); @@ -4062,7 +4056,7 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) pure_enum = false; } } - AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation()); + AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), bitcast(enum_decl->getLocation())); assert(tag_int_type); AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl); @@ -4084,7 +4078,7 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) { const clang::EnumConstantDecl *enum_const = *it; - Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); + Buf *enum_val_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_const)); Buf *field_name; if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) { field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name)); @@ -4102,7 +4096,7 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) // in C each enum value is in the global namespace. so we put them there too. // at this point we can rely on the enum emitting successfully if (is_anonymous) { - Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); + Buf *enum_val_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_const)); add_global_var(c, enum_val_name, int_node); } else { AstNode *field_access_node = trans_create_node_field_access(c, @@ -4123,62 +4117,63 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) } } -static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl, +static AstNode *demote_struct_to_opaque(Context *c, const ZigClangRecordDecl *record_decl, Buf *full_type_name, Buf *bare_name) { AstNode *opaque_node = trans_create_node_opaque(c); if (full_type_name == nullptr) { - c->decl_table.put(record_decl->getCanonicalDecl(), opaque_node); + c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), opaque_node); return opaque_node; } AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); add_global_weak_alias(c, bare_name, full_type_name); add_global_var(c, full_type_name, opaque_node); - c->decl_table.put(record_decl->getCanonicalDecl(), symbol_node); + c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), symbol_node); return symbol_node; } -static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) { - auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl()); +static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl) { + auto existing_entry = c->decl_table.maybe_get(ZigClangRecordDecl_getCanonicalDecl(record_decl)); if (existing_entry) { return existing_entry->value; } - const char *raw_name = decl_name(record_decl); + const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)record_decl); const char *container_kind_name; ContainerKind container_kind; - if (record_decl->isUnion()) { + if (ZigClangRecordDecl_isUnion(record_decl)) { container_kind_name = "union"; container_kind = ContainerKindUnion; - } else if (record_decl->isStruct()) { + } else if (ZigClangRecordDecl_isStruct(record_decl)) { container_kind_name = "struct"; container_kind = ContainerKindStruct; } else { - emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct or union", raw_name); - c->decl_table.put(record_decl->getCanonicalDecl(), nullptr); + emit_warning(c, ZigClangRecordDecl_getLocation(record_decl), + "skipping record %s, not a struct or union", raw_name); + c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), nullptr); return nullptr; } - bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0; + bool is_anonymous = ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) || raw_name[0] == 0; Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); Buf *full_type_name = (bare_name == nullptr) ? nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name)); - clang::RecordDecl *record_def = record_decl->getDefinition(); + const ZigClangRecordDecl *record_def = ZigClangRecordDecl_getDefinition(record_decl); if (record_def == nullptr) { return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); } // count fields and validate uint32_t field_count = 0; - for (auto it = record_def->field_begin(), - it_end = record_def->field_end(); + for (auto it = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_begin(), + it_end = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_end(); it != it_end; ++it, field_count += 1) { const clang::FieldDecl *field_decl = *it; if (field_decl->isBitField()) { - emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield", + emit_warning(c, bitcast(field_decl->getLocation()), "%s %s demoted to opaque type - has bitfield", container_kind_name, is_anonymous ? "(anon)" : buf_ptr(bare_name)); return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); @@ -4195,24 +4190,25 @@ static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_ // must be before fields in case a circular reference happens if (is_anonymous) { - c->decl_table.put(record_decl->getCanonicalDecl(), struct_node); + c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), struct_node); } else { - c->decl_table.put(record_decl->getCanonicalDecl(), trans_create_node_symbol(c, full_type_name)); + c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), trans_create_node_symbol(c, full_type_name)); } uint32_t i = 0; - for (auto it = record_def->field_begin(), - it_end = record_def->field_end(); + for (auto it = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_begin(), + it_end = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_end(); it != it_end; ++it, i += 1) { const clang::FieldDecl *field_decl = *it; AstNode *field_node = trans_create_node(c, NodeTypeStructField); - field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl)); - field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation()); + field_node->data.struct_field.name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)field_decl)); + field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), + bitcast(field_decl->getLocation())); if (field_node->data.struct_field.type == nullptr) { - emit_warning(c, field_decl->getLocation(), + emit_warning(c, bitcast(field_decl->getLocation()), "%s %s demoted to opaque type - unresolved type", container_kind_name, is_anonymous ? "(anon)" : buf_ptr(bare_name)); @@ -4232,7 +4228,7 @@ static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_ } } -static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) { +static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, ZigClangSourceLocation source_loc) { switch (ap_value->getKind()) { case clang::APValue::Int: return trans_create_node_apint(c, ap_value->getInt()); @@ -4331,25 +4327,25 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual } static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) { - Buf *name = buf_create_from_str(decl_name(var_decl)); + Buf *name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)var_decl)); switch (var_decl->getTLSKind()) { case clang::VarDecl::TLS_None: break; case clang::VarDecl::TLS_Static: - emit_warning(c, var_decl->getLocation(), + emit_warning(c, bitcast(var_decl->getLocation()), "ignoring variable '%s' - static thread local storage", buf_ptr(name)); return; case clang::VarDecl::TLS_Dynamic: - emit_warning(c, var_decl->getLocation(), + emit_warning(c, bitcast(var_decl->getLocation()), "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name)); return; } clang::QualType qt = var_decl->getType(); - AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation()); + AstNode *var_type = trans_qual_type(c, qt, bitcast(var_decl->getLocation())); if (var_type == nullptr) { - emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name)); + emit_warning(c, bitcast(var_decl->getLocation()), "ignoring variable '%s' - unresolved type", buf_ptr(name)); return; } @@ -4362,11 +4358,11 @@ static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) { if (var_decl->hasInit()) { clang::APValue *ap_value = var_decl->evaluateValue(); if (ap_value == nullptr) { - emit_warning(c, var_decl->getLocation(), + emit_warning(c, bitcast(var_decl->getLocation()), "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name)); return; } - init_node = trans_ap_value(c, ap_value, qt, var_decl->getLocation()); + init_node = trans_ap_value(c, ap_value, qt, bitcast(var_decl->getLocation())); if (init_node == nullptr) return; } else { @@ -4385,7 +4381,7 @@ static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) { return; } - emit_warning(c, var_decl->getLocation(), + emit_warning(c, bitcast(var_decl->getLocation()), "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name)); return; } @@ -4405,13 +4401,13 @@ static bool decl_visitor(void *context, const ZigClangDecl *zdecl) { resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl)); break; case clang::Decl::Record: - resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl)); + resolve_record_decl(c, (const ZigClangRecordDecl *)(decl)); break; case clang::Decl::Var: visit_var_decl(c, static_cast<const clang::VarDecl *>(decl)); break; default: - emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName()); + emit_warning(c, bitcast(decl->getLocation()), "ignoring %s decl", decl->getDeclKindName()); } return true; @@ -4846,10 +4842,10 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) { clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity); const char *raw_name = macro->getName()->getNameStart(); clang::SourceRange range = macro->getSourceRange(); - clang::SourceLocation begin_loc = range.getBegin(); - clang::SourceLocation end_loc = range.getEnd(); + ZigClangSourceLocation begin_loc = bitcast(range.getBegin()); + ZigClangSourceLocation end_loc = bitcast(range.getEnd()); - if (begin_loc == end_loc) { + if (ZigClangSourceLocation_eq(begin_loc, end_loc)) { // this means it is a macro without a value // we don't care about such things continue; @@ -4859,7 +4855,7 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) { continue; } - const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, bitcast(begin_loc)); + const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, begin_loc); process_macro(c, &ctok, name, begin_c); } } diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 230c3c3116..7c0c787e43 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -212,3 +212,48 @@ bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *contex return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context, reinterpret_cast<bool (*)(void *, const clang::Decl *)>(Fn)); } + +const ZigClangRecordDecl *ZigClangRecordType_getDecl(const ZigClangRecordType *record_ty) { + const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordType *>(record_ty)->getDecl(); + return reinterpret_cast<const ZigClangRecordDecl *>(record_decl); +} + +const ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const ZigClangRecordDecl *record_decl) { + const clang::TagDecl *tag_decl = reinterpret_cast<const clang::RecordDecl*>(record_decl)->getCanonicalDecl(); + return reinterpret_cast<const ZigClangTagDecl *>(tag_decl); +} + +const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) { + const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl); + const clang::RecordDecl *definition = record_decl->getDefinition(); + return reinterpret_cast<const ZigClangRecordDecl *>(definition); +} + +bool ZigClangRecordDecl_isUnion(const ZigClangRecordDecl *record_decl) { + return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isUnion(); +} + +bool ZigClangRecordDecl_isStruct(const ZigClangRecordDecl *record_decl) { + return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isStruct(); +} + +bool ZigClangRecordDecl_isAnonymousStructOrUnion(const ZigClangRecordDecl *record_decl) { + return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isAnonymousStructOrUnion(); +} + +const char *ZigClangDecl_getName_bytes_begin(const ZigClangDecl *zig_decl) { + const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zig_decl); + const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl); + return (const char *)named_decl->getName().bytes_begin(); +} + +ZigClangSourceLocation ZigClangRecordDecl_getLocation(const ZigClangRecordDecl *zig_record_decl) { + const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl); + return bitcast(record_decl->getLocation()); +} + +bool ZigClangSourceLocation_eq(ZigClangSourceLocation zig_a, ZigClangSourceLocation zig_b) { + clang::SourceLocation a = bitcast(zig_a); + clang::SourceLocation b = bitcast(zig_b); + return a == b; +} diff --git a/src/zig_clang.h b/src/zig_clang.h index c7d749cbd9..03c20c62d6 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -16,6 +16,7 @@ // ATTENTION: If you modify this file, be sure to update the corresponding // extern function declarations in the self-hosted compiler. +// Note: not yet, we don't have the corresponding clang.zig yet. struct ZigClangSourceLocation { unsigned ID; @@ -86,6 +87,7 @@ struct ZigClangStorageClass; struct ZigClangStringLiteral; struct ZigClangStringRef; struct ZigClangSwitchStmt; +struct ZigClangTagDecl; struct ZigClangType; struct ZigClangTypedefNameDecl; struct ZigClangTypedefType; @@ -256,4 +258,17 @@ ZIG_EXTERN_C ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit * ZIG_EXTERN_C ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *); ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *, void *context, bool (*Fn)(void *context, const ZigClangDecl *decl)); + +ZIG_EXTERN_C const ZigClangRecordDecl *ZigClangRecordType_getDecl(const ZigClangRecordType *record_ty); + +ZIG_EXTERN_C const ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const ZigClangRecordDecl *record_decl); +ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const ZigClangRecordDecl *record_decl); +ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const ZigClangRecordDecl *record_decl); +ZIG_EXTERN_C bool ZigClangRecordDecl_isAnonymousStructOrUnion(const ZigClangRecordDecl *record_decl); +ZIG_EXTERN_C const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *); +ZIG_EXTERN_C ZigClangSourceLocation ZigClangRecordDecl_getLocation(const ZigClangRecordDecl *); + +ZIG_EXTERN_C const char *ZigClangDecl_getName_bytes_begin(const ZigClangDecl *decl); + +ZIG_EXTERN_C bool ZigClangSourceLocation_eq(ZigClangSourceLocation a, ZigClangSourceLocation b); #endif diff --git a/std/debug.zig b/std/debug.zig index ec3f609022..90b4ff31d5 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1178,7 +1178,7 @@ pub const DwarfInfo = struct { }; pub const DebugInfo = switch (builtin.os) { - builtin.Os.macosx => struct { + builtin.Os.macosx, builtin.Os.ios => struct { symbols: []const MachoSymbol, strings: []const u8, ofiles: OFileTable, diff --git a/std/math/big.zig b/std/math/big.zig index 94b6d864e7..44b5ce675f 100644 --- a/std/math/big.zig +++ b/std/math/big.zig @@ -1,5 +1,7 @@ pub use @import("big/int.zig"); +pub use @import("big/rational.zig"); test "math.big" { _ = @import("big/int.zig"); + _ = @import("big/rational.zig"); } diff --git a/std/math/big/int.zig b/std/math/big/int.zig index 8800c2c7a9..aced892e18 100644 --- a/std/math/big/int.zig +++ b/std/math/big/int.zig @@ -22,13 +22,18 @@ comptime { } pub const Int = struct { - allocator: *Allocator, - positive: bool, + const sign_bit: usize = 1 << (usize.bit_count - 1); + + allocator: ?*Allocator, // - little-endian ordered // - len >= 1 always // - zero value -> len == 1 with limbs[0] == 0 limbs: []Limb, - len: usize, + // High bit is the sign bit. 1 is negative, 0 positive. + // Remaining bits indicate the number of used limbs. + // + // If Zig gets smarter about packing data, this can be rewritten as a u1 and usize - 1 field. + metadata: usize, const default_capacity = 4; @@ -45,54 +50,98 @@ pub const Int = struct { pub fn initCapacity(allocator: *Allocator, capacity: usize) !Int { return Int{ .allocator = allocator, - .positive = true, + .metadata = 1, .limbs = block: { var limbs = try allocator.alloc(Limb, math.max(default_capacity, capacity)); limbs[0] = 0; break :block limbs; }, - .len = 1, }; } + pub fn len(self: Int) usize { + return self.metadata & ~sign_bit; + } + + pub fn isPositive(self: Int) bool { + return self.metadata & sign_bit == 0; + } + + pub fn setSign(self: *Int, positive: bool) void { + if (positive) { + self.metadata &= ~sign_bit; + } else { + self.metadata |= sign_bit; + } + } + + pub fn setLen(self: *Int, new_len: usize) void { + self.metadata &= sign_bit; + self.metadata |= new_len; + } + + // Initialize an Int directly from a fixed set of limb values. This is considered read-only + // and cannot be used as a receiver argument to any functions. If this tries to allocate + // at any point a panic will occur due to the null allocator. + pub fn initFixed(limbs: []const Limb) Int { + var self = Int{ + .allocator = null, + .metadata = limbs.len, + // Cast away the const, invalid use to pass as a pointer argument. + .limbs = @intToPtr([*]Limb, @ptrToInt(limbs.ptr))[0..limbs.len], + }; + + self.normalize(limbs.len); + return self; + } + pub fn ensureCapacity(self: *Int, capacity: usize) !void { + self.assertWritable(); if (capacity <= self.limbs.len) { return; } - self.limbs = try self.allocator.realloc(self.limbs, capacity); + self.limbs = try self.allocator.?.realloc(self.limbs, capacity); + } + + fn assertWritable(self: Int) void { + if (self.allocator == null) { + @panic("provided Int value is read-only but must be writable"); + } } pub fn deinit(self: *Int) void { - self.allocator.free(self.limbs); + self.assertWritable(); + self.allocator.?.free(self.limbs); self.* = undefined; } pub fn clone(other: Int) !Int { + other.assertWritable(); return Int{ .allocator = other.allocator, - .positive = other.positive, + .metadata = other.metadata, .limbs = block: { - var limbs = try other.allocator.alloc(Limb, other.len); - mem.copy(Limb, limbs[0..], other.limbs[0..other.len]); + var limbs = try other.allocator.?.alloc(Limb, other.len()); + mem.copy(Limb, limbs[0..], other.limbs[0..other.len()]); break :block limbs; }, - .len = other.len, }; } pub fn copy(self: *Int, other: Int) !void { - if (self == &other) { + self.assertWritable(); + if (self.limbs.ptr == other.limbs.ptr) { return; } - self.positive = other.positive; - try self.ensureCapacity(other.len); - mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len]); - self.len = other.len; + try self.ensureCapacity(other.len()); + mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len()]); + self.metadata = other.metadata; } pub fn swap(self: *Int, other: *Int) void { + self.assertWritable(); mem.swap(Int, self, other); } @@ -103,25 +152,25 @@ pub const Int = struct { debug.warn("\n"); } - pub fn negate(r: *Int) void { - r.positive = !r.positive; + pub fn negate(self: *Int) void { + self.metadata ^= sign_bit; } - pub fn abs(r: *Int) void { - r.positive = true; + pub fn abs(self: *Int) void { + self.metadata &= ~sign_bit; } - pub fn isOdd(r: Int) bool { - return r.limbs[0] & 1 != 0; + pub fn isOdd(self: Int) bool { + return self.limbs[0] & 1 != 0; } - pub fn isEven(r: Int) bool { - return !r.isOdd(); + pub fn isEven(self: Int) bool { + return !self.isOdd(); } // Returns the number of bits required to represent the absolute value of self. fn bitCountAbs(self: Int) usize { - return (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1])); + return (self.len() - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len() - 1])); } // Returns the number of bits required to represent the integer in twos-complement form. @@ -137,11 +186,11 @@ pub const Int = struct { // If the entire value has only one bit set (e.g. 0b100000000) then the negation in twos // complement requires one less bit. - if (!self.positive) block: { + if (!self.isPositive()) block: { bits += 1; - if (@popCount(self.limbs[self.len - 1]) == 1) { - for (self.limbs[0 .. self.len - 1]) |limb| { + if (@popCount(self.limbs[self.len() - 1]) == 1) { + for (self.limbs[0 .. self.len() - 1]) |limb| { if (@popCount(limb) != 0) { break :block; } @@ -158,11 +207,11 @@ pub const Int = struct { if (self.eqZero()) { return true; } - if (!is_signed and !self.positive) { + if (!is_signed and !self.isPositive()) { return false; } - const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and is_signed); + const req_bits = self.bitCountTwosComp() + @boolToInt(self.isPositive() and is_signed); return bit_count >= req_bits; } @@ -174,11 +223,12 @@ pub const Int = struct { // the minus sign. This is used for determining the number of characters needed to print the // value. It is inexact and will exceed the given value by 1-2 digits. pub fn sizeInBase(self: Int, base: usize) usize { - const bit_count = usize(@boolToInt(!self.positive)) + self.bitCountAbs(); + const bit_count = usize(@boolToInt(!self.isPositive())) + self.bitCountAbs(); return (bit_count / math.log2(base)) + 1; } pub fn set(self: *Int, value: var) Allocator.Error!void { + self.assertWritable(); const T = @typeOf(value); switch (@typeInfo(T)) { @@ -186,19 +236,19 @@ pub const Int = struct { const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T; try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb)); - self.positive = value >= 0; - self.len = 0; + self.metadata = 0; + self.setSign(value >= 0); var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value); if (info.bits <= Limb.bit_count) { self.limbs[0] = Limb(w_value); - self.len = 1; + self.metadata += 1; } else { var i: usize = 0; while (w_value != 0) : (i += 1) { self.limbs[i] = @truncate(Limb, w_value); - self.len += 1; + self.metadata += 1; // TODO: shift == 64 at compile-time fails. Fails on u128 limbs. w_value >>= Limb.bit_count / 2; @@ -212,8 +262,8 @@ pub const Int = struct { const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1; try self.ensureCapacity(req_limbs); - self.positive = value >= 0; - self.len = req_limbs; + self.metadata = req_limbs; + self.setSign(value >= 0); if (w_value <= maxInt(Limb)) { self.limbs[0] = w_value; @@ -254,17 +304,17 @@ pub const Int = struct { if (@sizeOf(UT) <= @sizeOf(Limb)) { r = @intCast(UT, self.limbs[0]); } else { - for (self.limbs[0..self.len]) |_, ri| { - const limb = self.limbs[self.len - ri - 1]; + for (self.limbs[0..self.len()]) |_, ri| { + const limb = self.limbs[self.len() - ri - 1]; r <<= Limb.bit_count; r |= limb; } } if (!T.is_signed) { - return if (self.positive) @intCast(T, r) else error.NegativeIntoUnsigned; + return if (self.isPositive()) @intCast(T, r) else error.NegativeIntoUnsigned; } else { - if (self.positive) { + if (self.isPositive()) { return @intCast(T, r); } else { if (math.cast(T, r)) |ok| { @@ -304,6 +354,7 @@ pub const Int = struct { } pub fn setString(self: *Int, base: u8, value: []const u8) !void { + self.assertWritable(); if (base < 2 or base > 16) { return error.InvalidBase; } @@ -315,25 +366,18 @@ pub const Int = struct { i += 1; } - // TODO values less than limb size should guarantee non allocating - var base_buffer: [512]u8 = undefined; - const base_al = &std.heap.FixedBufferAllocator.init(base_buffer[0..]).allocator; - const base_ap = try Int.initSet(base_al, base); - - var d_buffer: [512]u8 = undefined; - var d_fba = std.heap.FixedBufferAllocator.init(d_buffer[0..]); - const d_al = &d_fba.allocator; - + const ap_base = Int.initFixed(([]Limb{base})[0..]); try self.set(0); + for (value[i..]) |ch| { const d = try charToDigit(ch, base); - d_fba.end_index = 0; - const d_ap = try Int.initSet(d_al, d); - try self.mul(self.*, base_ap); - try self.add(self.*, d_ap); + const ap_d = Int.initFixed(([]Limb{d})[0..]); + + try self.mul(self.*, ap_base); + try self.add(self.*, ap_d); } - self.positive = positive; + self.setSign(positive); } /// TODO make this call format instead of the other way around @@ -355,7 +399,7 @@ pub const Int = struct { if (base & (base - 1) == 0) { const base_shift = math.log2_int(Limb, base); - for (self.limbs[0..self.len]) |limb| { + for (self.limbs[0..self.len()]) |limb| { var shift: usize = 0; while (shift < Limb.bit_count) : (shift += base_shift) { const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & Limb(base - 1)); @@ -382,11 +426,11 @@ pub const Int = struct { } var q = try self.clone(); - q.positive = true; + q.abs(); var r = try Int.init(allocator); var b = try Int.initSet(allocator, limb_base); - while (q.len >= 2) { + while (q.len() >= 2) { try Int.divTrunc(&q, &r, q, b); var r_word = r.limbs[0]; @@ -399,7 +443,7 @@ pub const Int = struct { } { - debug.assert(q.len == 1); + debug.assert(q.len() == 1); var r_word = q.limbs[0]; while (r_word != 0) { @@ -410,7 +454,7 @@ pub const Int = struct { } } - if (!self.positive) { + if (!self.isPositive()) { try digits.append('-'); } @@ -428,22 +472,24 @@ pub const Int = struct { comptime FmtError: type, output: fn (@typeOf(context), []const u8) FmtError!void, ) FmtError!void { + self.assertWritable(); // TODO look at fmt and support other bases - const str = self.toString(self.allocator, 10) catch @panic("TODO make this non allocating"); - defer self.allocator.free(str); + // TODO support read-only fixed integers + const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating"); + defer self.allocator.?.free(str); return output(context, str); } // returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively. pub fn cmpAbs(a: Int, b: Int) i8 { - if (a.len < b.len) { + if (a.len() < b.len()) { return -1; } - if (a.len > b.len) { + if (a.len() > b.len()) { return 1; } - var i: usize = a.len - 1; + var i: usize = a.len() - 1; while (i != 0) : (i -= 1) { if (a.limbs[i] != b.limbs[i]) { break; @@ -461,17 +507,17 @@ pub const Int = struct { // returns -1, 0, 1 if a < b, a == b or a > b respectively. pub fn cmp(a: Int, b: Int) i8 { - if (a.positive != b.positive) { - return if (a.positive) i8(1) else -1; + if (a.isPositive() != b.isPositive()) { + return if (a.isPositive()) i8(1) else -1; } else { const r = cmpAbs(a, b); - return if (a.positive) r else -r; + return if (a.isPositive()) r else -r; } } // if a == 0 pub fn eqZero(a: Int) bool { - return a.len == 1 and a.limbs[0] == 0; + return a.len() == 1 and a.limbs[0] == 0; } // if |a| == |b| @@ -484,28 +530,12 @@ pub const Int = struct { return cmp(a, b) == 0; } - // Normalize for a possible single carry digit. - // - // [1, 2, 3, 4, 0] -> [1, 2, 3, 4] - // [1, 2, 3, 4, 5] -> [1, 2, 3, 4, 5] - // [0] -> [0] - fn norm1(r: *Int, length: usize) void { - debug.assert(length > 0); - debug.assert(length <= r.limbs.len); - - if (r.limbs[length - 1] == 0) { - r.len = if (length > 1) length - 1 else 1; - } else { - r.len = length; - } - } - // Normalize a possible sequence of leading zeros. // // [1, 2, 3, 4, 0] -> [1, 2, 3, 4] // [1, 2, 0, 0, 0] -> [1, 2] // [0, 0, 0, 0, 0] -> [0] - fn normN(r: *Int, length: usize) void { + fn normalize(r: *Int, length: usize) void { debug.assert(length > 0); debug.assert(length <= r.limbs.len); @@ -517,11 +547,21 @@ pub const Int = struct { } // Handle zero - r.len = if (j != 0) j else 1; + r.setLen(if (j != 0) j else 1); + } + + // Cannot be used as a result argument to any function. + fn readOnlyPositive(a: Int) Int { + return Int{ + .allocator = null, + .metadata = a.len(), + .limbs = a.limbs, + }; } // r = a + b pub fn add(r: *Int, a: Int, b: Int) Allocator.Error!void { + r.assertWritable(); if (a.eqZero()) { try r.copy(b); return; @@ -530,38 +570,26 @@ pub const Int = struct { return; } - if (a.positive != b.positive) { - if (a.positive) { + if (a.isPositive() != b.isPositive()) { + if (a.isPositive()) { // (a) + (-b) => a - b - const bp = Int{ - .allocator = undefined, - .positive = true, - .limbs = b.limbs, - .len = b.len, - }; - try r.sub(a, bp); + try r.sub(a, readOnlyPositive(b)); } else { // (-a) + (b) => b - a - const ap = Int{ - .allocator = undefined, - .positive = true, - .limbs = a.limbs, - .len = a.len, - }; - try r.sub(b, ap); + try r.sub(b, readOnlyPositive(a)); } } else { - if (a.len >= b.len) { - try r.ensureCapacity(a.len + 1); - lladd(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); - r.norm1(a.len + 1); + if (a.len() >= b.len()) { + try r.ensureCapacity(a.len() + 1); + lladd(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); + r.normalize(a.len() + 1); } else { - try r.ensureCapacity(b.len + 1); - lladd(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); - r.norm1(b.len + 1); + try r.ensureCapacity(b.len() + 1); + lladd(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); + r.normalize(b.len() + 1); } - r.positive = a.positive; + r.setSign(a.isPositive()); } } @@ -591,53 +619,42 @@ pub const Int = struct { // r = a - b pub fn sub(r: *Int, a: Int, b: Int) !void { - if (a.positive != b.positive) { - if (a.positive) { + r.assertWritable(); + if (a.isPositive() != b.isPositive()) { + if (a.isPositive()) { // (a) - (-b) => a + b - const bp = Int{ - .allocator = undefined, - .positive = true, - .limbs = b.limbs, - .len = b.len, - }; - try r.add(a, bp); + try r.add(a, readOnlyPositive(b)); } else { // (-a) - (b) => -(a + b) - const ap = Int{ - .allocator = undefined, - .positive = true, - .limbs = a.limbs, - .len = a.len, - }; - try r.add(ap, b); - r.positive = false; + try r.add(readOnlyPositive(a), b); + r.setSign(false); } } else { - if (a.positive) { + if (a.isPositive()) { // (a) - (b) => a - b if (a.cmp(b) >= 0) { - try r.ensureCapacity(a.len + 1); - llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); - r.normN(a.len); - r.positive = true; + try r.ensureCapacity(a.len() + 1); + llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); + r.normalize(a.len()); + r.setSign(true); } else { - try r.ensureCapacity(b.len + 1); - llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); - r.normN(b.len); - r.positive = false; + try r.ensureCapacity(b.len() + 1); + llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); + r.normalize(b.len()); + r.setSign(false); } } else { // (-a) - (-b) => -(a - b) if (a.cmp(b) < 0) { - try r.ensureCapacity(a.len + 1); - llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); - r.normN(a.len); - r.positive = false; + try r.ensureCapacity(a.len() + 1); + llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); + r.normalize(a.len()); + r.setSign(false); } else { - try r.ensureCapacity(b.len + 1); - llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); - r.normN(b.len); - r.positive = true; + try r.ensureCapacity(b.len() + 1); + llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); + r.normalize(b.len()); + r.setSign(true); } } } @@ -671,12 +688,14 @@ pub const Int = struct { // // For greatest efficiency, ensure rma does not alias a or b. pub fn mul(rma: *Int, a: Int, b: Int) !void { + rma.assertWritable(); + var r = rma; var aliased = rma.limbs.ptr == a.limbs.ptr or rma.limbs.ptr == b.limbs.ptr; var sr: Int = undefined; if (aliased) { - sr = try Int.initCapacity(rma.allocator, a.len + b.len); + sr = try Int.initCapacity(rma.allocator.?, a.len() + b.len()); r = &sr; aliased = true; } @@ -685,16 +704,16 @@ pub const Int = struct { r.deinit(); }; - try r.ensureCapacity(a.len + b.len); + try r.ensureCapacity(a.len() + b.len()); - if (a.len >= b.len) { - llmul(r.limbs, a.limbs[0..a.len], b.limbs[0..b.len]); + if (a.len() >= b.len()) { + llmul(r.limbs, a.limbs[0..a.len()], b.limbs[0..b.len()]); } else { - llmul(r.limbs, b.limbs[0..b.len], a.limbs[0..a.len]); + llmul(r.limbs, b.limbs[0..b.len()], a.limbs[0..a.len()]); } - r.positive = a.positive == b.positive; - r.normN(a.len + b.len); + r.normalize(a.len() + b.len()); + r.setSign(a.isPositive() == b.isPositive()); } // a + b * c + *carry, sets carry to the overflow bits @@ -744,25 +763,24 @@ pub const Int = struct { try div(q, r, a, b); // Trunc -> Floor. - if (!q.positive) { - // TODO values less than limb size should guarantee non allocating - var one_buffer: [512]u8 = undefined; - const one_al = &std.heap.FixedBufferAllocator.init(one_buffer[0..]).allocator; - const one_ap = try Int.initSet(one_al, 1); - - try q.sub(q.*, one_ap); - try r.add(q.*, one_ap); + if (!q.isPositive()) { + const one = Int.initFixed(([]Limb{1})[0..]); + try q.sub(q.*, one); + try r.add(q.*, one); } - r.positive = b.positive; + r.setSign(b.isPositive()); } pub fn divTrunc(q: *Int, r: *Int, a: Int, b: Int) !void { try div(q, r, a, b); - r.positive = a.positive; + r.setSign(a.isPositive()); } // Truncates by default. fn div(quo: *Int, rem: *Int, a: Int, b: Int) !void { + quo.assertWritable(); + rem.assertWritable(); + if (b.eqZero()) { @panic("division by zero"); } @@ -773,36 +791,67 @@ pub const Int = struct { if (a.cmpAbs(b) < 0) { // quo may alias a so handle rem first try rem.copy(a); - rem.positive = a.positive == b.positive; + rem.setSign(a.isPositive() == b.isPositive()); - quo.positive = true; - quo.len = 1; + quo.metadata = 1; quo.limbs[0] = 0; return; } - if (b.len == 1) { - try quo.ensureCapacity(a.len); + // Handle trailing zero-words of divisor/dividend. These are not handled in the following + // algorithms. + const a_zero_limb_count = blk: { + var i: usize = 0; + while (i < a.len()) : (i += 1) { + if (a.limbs[i] != 0) break; + } + break :blk i; + }; + const b_zero_limb_count = blk: { + var i: usize = 0; + while (i < b.len()) : (i += 1) { + if (b.limbs[i] != 0) break; + } + break :blk i; + }; + + const ab_zero_limb_count = std.math.min(a_zero_limb_count, b_zero_limb_count); + + if (b.len() - ab_zero_limb_count == 1) { + try quo.ensureCapacity(a.len()); - lldiv1(quo.limbs[0..], &rem.limbs[0], a.limbs[0..a.len], b.limbs[0]); - quo.norm1(a.len); - quo.positive = a.positive == b.positive; + lldiv1(quo.limbs[0..], &rem.limbs[0], a.limbs[ab_zero_limb_count..a.len()], b.limbs[b.len() - 1]); + quo.normalize(a.len() - ab_zero_limb_count); + quo.setSign(a.isPositive() == b.isPositive()); - rem.len = 1; - rem.positive = true; + rem.metadata = 1; } else { // x and y are modified during division - var x = try a.clone(); + var x = try Int.initCapacity(quo.allocator.?, a.len()); defer x.deinit(); + try x.copy(a); - var y = try b.clone(); + var y = try Int.initCapacity(quo.allocator.?, b.len()); defer y.deinit(); + try y.copy(b); // x may grow one limb during normalization - try quo.ensureCapacity(a.len + y.len); - try divN(quo.allocator, quo, rem, &x, &y); + try quo.ensureCapacity(a.len() + y.len()); + + // Shrink x, y such that the trailing zero limbs shared between are removed. + if (ab_zero_limb_count != 0) { + std.mem.copy(Limb, x.limbs[0..], x.limbs[ab_zero_limb_count..]); + std.mem.copy(Limb, y.limbs[0..], y.limbs[ab_zero_limb_count..]); + x.metadata -= ab_zero_limb_count; + y.metadata -= ab_zero_limb_count; + } + + try divN(quo.allocator.?, quo, rem, &x, &y); + quo.setSign(a.isPositive() == b.isPositive()); + } - quo.positive = a.positive == b.positive; + if (ab_zero_limb_count != 0) { + try rem.shiftLeft(rem.*, ab_zero_limb_count * Limb.bit_count); } } @@ -837,25 +886,28 @@ pub const Int = struct { // // x = qy + r where 0 <= r < y fn divN(allocator: *Allocator, q: *Int, r: *Int, x: *Int, y: *Int) !void { - debug.assert(y.len >= 2); - debug.assert(x.len >= y.len); - debug.assert(q.limbs.len >= x.len + y.len - 1); + debug.assert(y.len() >= 2); + debug.assert(x.len() >= y.len()); + debug.assert(q.limbs.len >= x.len() + y.len() - 1); debug.assert(default_capacity >= 3); // see 3.2 var tmp = try Int.init(allocator); defer tmp.deinit(); - // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) - const norm_shift = @clz(y.limbs[y.len - 1]); + // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) and even + var norm_shift = @clz(y.limbs[y.len() - 1]); + if (norm_shift == 0 and y.isOdd()) { + norm_shift = Limb.bit_count; + } try x.shiftLeft(x.*, norm_shift); try y.shiftLeft(y.*, norm_shift); - const n = x.len - 1; - const t = y.len - 1; + const n = x.len() - 1; + const t = y.len() - 1; // 1. - q.len = n - t + 1; - mem.set(Limb, q.limbs[0..q.len], 0); + q.metadata = n - t + 1; + mem.set(Limb, q.limbs[0..q.len()], 0); // 2. try tmp.shiftLeft(y.*, Limb.bit_count * (n - t)); @@ -880,7 +932,7 @@ pub const Int = struct { tmp.limbs[0] = if (i >= 2) x.limbs[i - 2] else 0; tmp.limbs[1] = if (i >= 1) x.limbs[i - 1] else 0; tmp.limbs[2] = x.limbs[i]; - tmp.normN(3); + tmp.normalize(3); while (true) { // 2x1 limb multiplication unrolled against single-limb q[i-t-1] @@ -888,7 +940,7 @@ pub const Int = struct { r.limbs[0] = addMulLimbWithCarry(0, if (t >= 1) y.limbs[t - 1] else 0, q.limbs[i - t - 1], &carry); r.limbs[1] = addMulLimbWithCarry(0, y.limbs[t], q.limbs[i - t - 1], &carry); r.limbs[2] = carry; - r.normN(3); + r.normalize(3); if (r.cmpAbs(tmp) <= 0) { break; @@ -903,7 +955,7 @@ pub const Int = struct { try tmp.shiftLeft(tmp, Limb.bit_count * (i - t - 1)); try x.sub(x.*, tmp); - if (!x.positive) { + if (!x.isPositive()) { try tmp.shiftLeft(y.*, Limb.bit_count * (i - t - 1)); try x.add(x.*, tmp); q.limbs[i - t - 1] -= 1; @@ -911,18 +963,20 @@ pub const Int = struct { } // Denormalize - q.normN(q.len); + q.normalize(q.len()); try r.shiftRight(x.*, norm_shift); - r.normN(r.len); + r.normalize(r.len()); } // r = a << shift, in other words, r = a * 2^shift pub fn shiftLeft(r: *Int, a: Int, shift: usize) !void { - try r.ensureCapacity(a.len + (shift / Limb.bit_count) + 1); - llshl(r.limbs[0..], a.limbs[0..a.len], shift); - r.norm1(a.len + (shift / Limb.bit_count) + 1); - r.positive = a.positive; + r.assertWritable(); + + try r.ensureCapacity(a.len() + (shift / Limb.bit_count) + 1); + llshl(r.limbs[0..], a.limbs[0..a.len()], shift); + r.normalize(a.len() + (shift / Limb.bit_count) + 1); + r.setSign(a.isPositive()); } fn llshl(r: []Limb, a: []const Limb, shift: usize) void { @@ -950,17 +1004,18 @@ pub const Int = struct { // r = a >> shift pub fn shiftRight(r: *Int, a: Int, shift: usize) !void { - if (a.len <= shift / Limb.bit_count) { - r.len = 1; + r.assertWritable(); + + if (a.len() <= shift / Limb.bit_count) { + r.metadata = 1; r.limbs[0] = 0; - r.positive = true; return; } - try r.ensureCapacity(a.len - (shift / Limb.bit_count)); - const r_len = llshr(r.limbs[0..], a.limbs[0..a.len], shift); - r.len = a.len - (shift / Limb.bit_count); - r.positive = a.positive; + try r.ensureCapacity(a.len() - (shift / Limb.bit_count)); + const r_len = llshr(r.limbs[0..], a.limbs[0..a.len()], shift); + r.metadata = a.len() - (shift / Limb.bit_count); + r.setSign(a.isPositive()); } fn llshr(r: []Limb, a: []const Limb, shift: usize) void { @@ -985,14 +1040,16 @@ pub const Int = struct { // r = a | b pub fn bitOr(r: *Int, a: Int, b: Int) !void { - if (a.len > b.len) { - try r.ensureCapacity(a.len); - llor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); - r.len = a.len; + r.assertWritable(); + + if (a.len() > b.len()) { + try r.ensureCapacity(a.len()); + llor(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); + r.setLen(a.len()); } else { - try r.ensureCapacity(b.len); - llor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); - r.len = b.len; + try r.ensureCapacity(b.len()); + llor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); + r.setLen(b.len()); } } @@ -1012,14 +1069,16 @@ pub const Int = struct { // r = a & b pub fn bitAnd(r: *Int, a: Int, b: Int) !void { - if (a.len > b.len) { - try r.ensureCapacity(b.len); - lland(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); - r.normN(b.len); + r.assertWritable(); + + if (a.len() > b.len()) { + try r.ensureCapacity(b.len()); + lland(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); + r.normalize(b.len()); } else { - try r.ensureCapacity(a.len); - lland(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); - r.normN(a.len); + try r.ensureCapacity(a.len()); + lland(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); + r.normalize(a.len()); } } @@ -1036,14 +1095,16 @@ pub const Int = struct { // r = a ^ b pub fn bitXor(r: *Int, a: Int, b: Int) !void { - if (a.len > b.len) { - try r.ensureCapacity(a.len); - llxor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); - r.normN(a.len); + r.assertWritable(); + + if (a.len() > b.len()) { + try r.ensureCapacity(a.len()); + llxor(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); + r.normalize(a.len()); } else { - try r.ensureCapacity(b.len); - llxor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); - r.normN(b.len); + try r.ensureCapacity(b.len()); + llxor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); + r.normalize(b.len()); } } @@ -1067,7 +1128,9 @@ pub const Int = struct { // They will still run on larger than this and should pass, but the multi-limb code-paths // may be untested in some cases. -const al = debug.global_allocator; +var buffer: [64 * 8192]u8 = undefined; +var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); +const al = &fixed.allocator; test "big.int comptime_int set" { comptime var s = 0xefffffff00000001eeeeeeefaaaaaaab; @@ -1088,14 +1151,14 @@ test "big.int comptime_int set negative" { var a = try Int.initSet(al, -10); testing.expect(a.limbs[0] == 10); - testing.expect(a.positive == false); + testing.expect(a.isPositive() == false); } test "big.int int set unaligned small" { var a = try Int.initSet(al, u7(45)); testing.expect(a.limbs[0] == 45); - testing.expect(a.positive == true); + testing.expect(a.isPositive() == true); } test "big.int comptime_int to" { @@ -1116,7 +1179,7 @@ test "big.int to target too small error" { testing.expectError(error.TargetTooSmall, a.to(u8)); } -test "big.int norm1" { +test "big.int normalize" { var a = try Int.init(al); try a.ensureCapacity(8); @@ -1124,26 +1187,26 @@ test "big.int norm1" { a.limbs[1] = 2; a.limbs[2] = 3; a.limbs[3] = 0; - a.norm1(4); - testing.expect(a.len == 3); + a.normalize(4); + testing.expect(a.len() == 3); a.limbs[0] = 1; a.limbs[1] = 2; a.limbs[2] = 3; - a.norm1(3); - testing.expect(a.len == 3); + a.normalize(3); + testing.expect(a.len() == 3); a.limbs[0] = 0; a.limbs[1] = 0; - a.norm1(2); - testing.expect(a.len == 1); + a.normalize(2); + testing.expect(a.len() == 1); a.limbs[0] = 0; - a.norm1(1); - testing.expect(a.len == 1); + a.normalize(1); + testing.expect(a.len() == 1); } -test "big.int normN" { +test "big.int normalize multi" { var a = try Int.init(al); try a.ensureCapacity(8); @@ -1151,25 +1214,25 @@ test "big.int normN" { a.limbs[1] = 2; a.limbs[2] = 0; a.limbs[3] = 0; - a.normN(4); - testing.expect(a.len == 2); + a.normalize(4); + testing.expect(a.len() == 2); a.limbs[0] = 1; a.limbs[1] = 2; a.limbs[2] = 3; - a.normN(3); - testing.expect(a.len == 3); + a.normalize(3); + testing.expect(a.len() == 3); a.limbs[0] = 0; a.limbs[1] = 0; a.limbs[2] = 0; a.limbs[3] = 0; - a.normN(4); - testing.expect(a.len == 1); + a.normalize(4); + testing.expect(a.len() == 1); a.limbs[0] = 0; - a.normN(1); - testing.expect(a.len == 1); + a.normalize(1); + testing.expect(a.len() == 1); } test "big.int parity" { @@ -1204,7 +1267,7 @@ test "big.int bitcount + sizeInBase" { try a.shiftLeft(a, 5000); testing.expect(a.bitCountAbs() == 5032); testing.expect(a.sizeInBase(2) >= 5032); - a.positive = false; + a.setSign(false); testing.expect(a.bitCountAbs() == 5032); testing.expect(a.sizeInBase(2) >= 5033); @@ -1980,6 +2043,98 @@ test "big.int div multi-multi (3.1/3.3 branch)" { testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282); } +test "big.int div multi-single zero-limb trailing" { + var a = try Int.initSet(al, 0x60000000000000000000000000000000000000000000000000000000000000000); + var b = try Int.initSet(al, 0x10000000000000000); + + var q = try Int.init(al); + var r = try Int.init(al); + try Int.divTrunc(&q, &r, a, b); + + var expected = try Int.initSet(al, 0x6000000000000000000000000000000000000000000000000); + testing.expect(q.eq(expected)); + testing.expect(r.eqZero()); +} + +test "big.int div multi-multi zero-limb trailing (with rem)" { + var a = try Int.initSet(al, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); + var b = try Int.initSet(al, 0x8666666655555555444444443333333300000000000000000000000000000000); + + var q = try Int.init(al); + var r = try Int.init(al); + try Int.divTrunc(&q, &r, a, b); + + testing.expect((try q.to(u128)) == 0x10000000000000000); + + const rs = try r.toString(al, 16); + testing.expect(std.mem.eql(u8, rs, "4444444344444443111111111111111100000000000000000000000000000000")); +} + +test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" { + var a = try Int.initSet(al, 0x8666666655555555888888877777777611111111111111110000000000000000); + var b = try Int.initSet(al, 0x8666666655555555444444443333333300000000000000000000000000000000); + + var q = try Int.init(al); + var r = try Int.init(al); + try Int.divTrunc(&q, &r, a, b); + + testing.expect((try q.to(u128)) == 0x1); + + const rs = try r.toString(al, 16); + testing.expect(std.mem.eql(u8, rs, "444444434444444311111111111111110000000000000000")); +} + +test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" { + var a = try Int.initSet(al, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); + var b = try Int.initSet(al, 0x866666665555555544444444333333330000000000000000); + + var q = try Int.init(al); + var r = try Int.init(al); + try Int.divTrunc(&q, &r, a, b); + + const qs = try q.toString(al, 16); + testing.expect(std.mem.eql(u8, qs, "10000000000000000820820803105186f")); + + const rs = try r.toString(al, 16); + testing.expect(std.mem.eql(u8, rs, "4e11f2baa5896a321d463b543d0104e30000000000000000")); +} + +test "big.int div multi-multi fuzz case #1" { + var a = try Int.init(al); + var b = try Int.init(al); + + try a.setString(16, "ffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + try b.setString(16, "3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000007fffffffffff"); + + var q = try Int.init(al); + var r = try Int.init(al); + try Int.divTrunc(&q, &r, a, b); + + const qs = try q.toString(al, 16); + testing.expect(std.mem.eql(u8, qs, "3ffffffffffffffffffffffffffff0000000000000000000000000000000000001ffffffffffffffffffffffffffff7fffffffe000000000000000000000000000180000000000000000000003fffffbfffffffdfffffffffffffeffff800000100101000000100000000020003fffffdfbfffffe3ffffffffffffeffff7fffc00800a100000017ffe000002000400007efbfff7fe9f00000037ffff3fff7fffa004006100000009ffe00000190038200bf7d2ff7fefe80400060000f7d7f8fbf9401fe38e0403ffc0bdffffa51102c300d7be5ef9df4e5060007b0127ad3fa69f97d0f820b6605ff617ddf7f32ad7a05c0d03f2e7bc78a6000e087a8bbcdc59e07a5a079128a7861f553ddebed7e8e56701756f9ead39b48cd1b0831889ea6ec1fddf643d0565b075ff07e6caea4e2854ec9227fd635ed60a2f5eef2893052ffd54718fa08604acbf6a15e78a467c4a3c53c0278af06c4416573f925491b195e8fd79302cb1aaf7caf4ecfc9aec1254cc969786363ac729f914c6ddcc26738d6b0facd54eba026580aba2eb6482a088b0d224a8852420b91ec1")); + + const rs = try r.toString(al, 16); + testing.expect(std.mem.eql(u8, rs, "310d1d4c414426b4836c2635bad1df3a424e50cbdd167ffccb4dfff57d36b4aae0d6ca0910698220171a0f3373c1060a046c2812f0027e321f72979daa5e7973214170d49e885de0c0ecc167837d44502430674a82522e5df6a0759548052420b91ec1")); +} + +test "big.int div multi-multi fuzz case #2" { + var a = try Int.init(al); + var b = try Int.init(al); + + try a.setString(16, "3ffffffffe00000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000001fffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffc000000000000000000000000000000000000000000000000000000000000000"); + try b.setString(16, "ffc0000000000000000000000000000000000000000000000000"); + + var q = try Int.init(al); + var r = try Int.init(al); + try Int.divTrunc(&q, &r, a, b); + + const qs = try q.toString(al, 16); + testing.expect(std.mem.eql(u8, qs, "40100400fe3f8fe3f8fe3f8fe3f8fe3f8fe4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f91e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4992649926499264991e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4792e4b92e4b92e4b92e4b92a4a92a4a92a4")); + + const rs = try r.toString(al, 16); + testing.expect(std.mem.eql(u8, rs, "a900000000000000000000000000000000000000000000000000")); +} + test "big.int shift-right single" { var a = try Int.initSet(al, 0xffff0000); try a.shiftRight(a, 16); diff --git a/std/math/big/rational.zig b/std/math/big/rational.zig new file mode 100644 index 0000000000..34cf3bf764 --- /dev/null +++ b/std/math/big/rational.zig @@ -0,0 +1,896 @@ +const std = @import("../../std.zig"); +const builtin = @import("builtin"); +const debug = std.debug; +const math = std.math; +const mem = std.mem; +const testing = std.testing; +const Allocator = mem.Allocator; +const ArrayList = std.ArrayList; + +const TypeId = builtin.TypeId; + +const bn = @import("int.zig"); +const Limb = bn.Limb; +const DoubleLimb = bn.DoubleLimb; +const Int = bn.Int; + +pub const Rational = struct { + // Sign of Rational is sign of p. Sign of q is ignored + p: Int, + q: Int, + + pub fn init(a: *Allocator) !Rational { + return Rational{ + .p = try Int.init(a), + .q = try Int.initSet(a, 1), + }; + } + + pub fn deinit(self: *Rational) void { + self.p.deinit(); + self.q.deinit(); + } + + pub fn setInt(self: *Rational, a: var) !void { + try self.p.set(a); + try self.q.set(1); + } + + // TODO: Accept a/b fractions and exponent form + pub fn setFloatString(self: *Rational, str: []const u8) !void { + if (str.len == 0) { + return error.InvalidFloatString; + } + + const State = enum { + Integer, + Fractional, + }; + + var state = State.Integer; + var point: ?usize = null; + + var start: usize = 0; + if (str[0] == '-') { + start += 1; + } + + for (str) |c, i| { + switch (state) { + State.Integer => { + switch (c) { + '.' => { + state = State.Fractional; + point = i; + }, + '0'...'9' => { + // okay + }, + else => { + return error.InvalidFloatString; + }, + } + }, + State.Fractional => { + switch (c) { + '0'...'9' => { + // okay + }, + else => { + return error.InvalidFloatString; + }, + } + }, + } + } + + // TODO: batch the multiplies by 10 + if (point) |i| { + try self.p.setString(10, str[0..i]); + + const base = Int.initFixed(([]Limb{10})[0..]); + + var j: usize = start; + while (j < str.len - i - 1) : (j += 1) { + try self.p.mul(self.p, base); + } + + try self.q.setString(10, str[i + 1 ..]); + try self.p.add(self.p, self.q); + + try self.q.set(1); + var k: usize = i + 1; + while (k < str.len) : (k += 1) { + try self.q.mul(self.q, base); + } + + try self.reduce(); + } else { + try self.p.setString(10, str[0..]); + try self.q.set(1); + } + } + + // Translated from golang.go/src/math/big/rat.go. + pub fn setFloat(self: *Rational, comptime T: type, f: T) !void { + debug.assert(@typeId(T) == builtin.TypeId.Float); + + const UnsignedIntType = @IntType(false, T.bit_count); + const f_bits = @bitCast(UnsignedIntType, f); + + const exponent_bits = math.floatExponentBits(T); + const exponent_bias = (1 << (exponent_bits - 1)) - 1; + const mantissa_bits = math.floatMantissaBits(T); + + const exponent_mask = (1 << exponent_bits) - 1; + const mantissa_mask = (1 << mantissa_bits) - 1; + + var exponent = @intCast(i16, (f_bits >> mantissa_bits) & exponent_mask); + var mantissa = f_bits & mantissa_mask; + + switch (exponent) { + exponent_mask => { + return error.NonFiniteFloat; + }, + 0 => { + // denormal + exponent -= exponent_bias - 1; + }, + else => { + // normal + mantissa |= 1 << mantissa_bits; + exponent -= exponent_bias; + }, + } + + var shift: i16 = mantissa_bits - exponent; + + // factor out powers of two early from rational + while (mantissa & 1 == 0 and shift > 0) { + mantissa >>= 1; + shift -= 1; + } + + try self.p.set(mantissa); + self.p.setSign(f >= 0); + + try self.q.set(1); + if (shift >= 0) { + try self.q.shiftLeft(self.q, @intCast(usize, shift)); + } else { + try self.p.shiftLeft(self.p, @intCast(usize, -shift)); + } + + try self.reduce(); + } + + // Translated from golang.go/src/math/big/rat.go. + pub fn toFloat(self: Rational, comptime T: type) !T { + debug.assert(@typeId(T) == builtin.TypeId.Float); + + const fsize = T.bit_count; + const BitReprType = @IntType(false, T.bit_count); + + const msize = math.floatMantissaBits(T); + const msize1 = msize + 1; + const msize2 = msize1 + 1; + + const esize = math.floatExponentBits(T); + const ebias = (1 << (esize - 1)) - 1; + const emin = 1 - ebias; + const emax = ebias; + + if (self.p.eqZero()) { + return 0; + } + + // 1. left-shift a or sub so that a/b is in [1 << msize1, 1 << (msize2 + 1)] + var exp = @intCast(isize, self.p.bitCountTwosComp()) - @intCast(isize, self.q.bitCountTwosComp()); + + var a2 = try self.p.clone(); + defer a2.deinit(); + + var b2 = try self.q.clone(); + defer b2.deinit(); + + const shift = msize2 - exp; + if (shift >= 0) { + try a2.shiftLeft(a2, @intCast(usize, shift)); + } else { + try b2.shiftLeft(b2, @intCast(usize, -shift)); + } + + // 2. compute quotient and remainder + var q = try Int.init(self.p.allocator.?); + defer q.deinit(); + + // unused + var r = try Int.init(self.p.allocator.?); + defer r.deinit(); + + try Int.divTrunc(&q, &r, a2, b2); + + var mantissa = extractLowBits(q, BitReprType); + var have_rem = r.len() > 0; + + // 3. q didn't fit in msize2 bits, redo division b2 << 1 + if (mantissa >> msize2 == 1) { + if (mantissa & 1 == 1) { + have_rem = true; + } + mantissa >>= 1; + exp += 1; + } + if (mantissa >> msize1 != 1) { + // NOTE: This can be hit if the limb size is small (u8/16). + @panic("unexpected bits in result"); + } + + // 4. Rounding + if (emin - msize <= exp and exp <= emin) { + // denormal + const shift1 = @intCast(math.Log2Int(BitReprType), emin - (exp - 1)); + const lost_bits = mantissa & ((@intCast(BitReprType, 1) << shift1) - 1); + have_rem = have_rem or lost_bits != 0; + mantissa >>= shift1; + exp = 2 - ebias; + } + + // round q using round-half-to-even + var exact = !have_rem; + if (mantissa & 1 != 0) { + exact = false; + if (have_rem or (mantissa & 2 != 0)) { + mantissa += 1; + if (mantissa >= 1 << msize2) { + // 11...1 => 100...0 + mantissa >>= 1; + exp += 1; + } + } + } + mantissa >>= 1; + + const f = math.scalbn(@intToFloat(T, mantissa), @intCast(i32, exp - msize1)); + if (math.isInf(f)) { + exact = false; + } + + return if (self.p.isPositive()) f else -f; + } + + pub fn setRatio(self: *Rational, p: var, q: var) !void { + try self.p.set(p); + try self.q.set(q); + + self.p.setSign(@boolToInt(self.p.isPositive()) ^ @boolToInt(self.q.isPositive()) == 0); + self.q.setSign(true); + + try self.reduce(); + + if (self.q.eqZero()) { + @panic("cannot set rational with denominator = 0"); + } + } + + pub fn copyInt(self: *Rational, a: Int) !void { + try self.p.copy(a); + try self.q.set(1); + } + + pub fn copyRatio(self: *Rational, a: Int, b: Int) !void { + try self.p.copy(a); + try self.q.copy(b); + + self.p.setSign(@boolToInt(self.p.isPositive()) ^ @boolToInt(self.q.isPositive()) == 0); + self.q.setSign(true); + + try self.reduce(); + } + + pub fn abs(r: *Rational) void { + r.p.abs(); + } + + pub fn negate(r: *Rational) void { + r.p.negate(); + } + + pub fn swap(r: *Rational, other: *Rational) void { + r.p.swap(&other.p); + r.q.swap(&other.q); + } + + pub fn cmp(a: Rational, b: Rational) !i8 { + return cmpInternal(a, b, true); + } + + pub fn cmpAbs(a: Rational, b: Rational) !i8 { + return cmpInternal(a, b, false); + } + + // p/q > x/y iff p*y > x*q + fn cmpInternal(a: Rational, b: Rational, is_abs: bool) !i8 { + // TODO: Would a div compare algorithm of sorts be viable and quicker? Can we avoid + // the memory allocations here? + var q = try Int.init(a.p.allocator.?); + defer q.deinit(); + + var p = try Int.init(b.p.allocator.?); + defer p.deinit(); + + try q.mul(a.p, b.q); + try p.mul(b.p, a.q); + + return if (is_abs) q.cmpAbs(p) else q.cmp(p); + } + + // r/q = ap/aq + bp/bq = (ap*bq + bp*aq) / (aq*bq) + // + // For best performance, rma should not alias a or b. + pub fn add(rma: *Rational, a: Rational, b: Rational) !void { + var r = rma; + var aliased = rma.p.limbs.ptr == a.p.limbs.ptr or rma.p.limbs.ptr == b.p.limbs.ptr; + + var sr: Rational = undefined; + if (aliased) { + sr = try Rational.init(rma.p.allocator.?); + r = &sr; + aliased = true; + } + defer if (aliased) { + rma.swap(r); + r.deinit(); + }; + + try r.p.mul(a.p, b.q); + try r.q.mul(b.p, a.q); + try r.p.add(r.p, r.q); + + try r.q.mul(a.q, b.q); + try r.reduce(); + } + + // r/q = ap/aq - bp/bq = (ap*bq - bp*aq) / (aq*bq) + // + // For best performance, rma should not alias a or b. + pub fn sub(rma: *Rational, a: Rational, b: Rational) !void { + var r = rma; + var aliased = rma.p.limbs.ptr == a.p.limbs.ptr or rma.p.limbs.ptr == b.p.limbs.ptr; + + var sr: Rational = undefined; + if (aliased) { + sr = try Rational.init(rma.p.allocator.?); + r = &sr; + aliased = true; + } + defer if (aliased) { + rma.swap(r); + r.deinit(); + }; + + try r.p.mul(a.p, b.q); + try r.q.mul(b.p, a.q); + try r.p.sub(r.p, r.q); + + try r.q.mul(a.q, b.q); + try r.reduce(); + } + + // r/q = ap/aq * bp/bq = ap*bp / aq*bq + pub fn mul(r: *Rational, a: Rational, b: Rational) !void { + try r.p.mul(a.p, b.p); + try r.q.mul(a.q, b.q); + try r.reduce(); + } + + // r/q = (ap/aq) / (bp/bq) = ap*bq / bp*aq + pub fn div(r: *Rational, a: Rational, b: Rational) !void { + if (b.p.eqZero()) { + @panic("division by zero"); + } + + try r.p.mul(a.p, b.q); + try r.q.mul(b.p, a.q); + try r.reduce(); + } + + // r/q = q/r + pub fn invert(r: *Rational) void { + Int.swap(&r.p, &r.q); + } + + // reduce r/q such that gcd(r, q) = 1 + fn reduce(r: *Rational) !void { + var a = try Int.init(r.p.allocator.?); + defer a.deinit(); + + const sign = r.p.isPositive(); + r.p.abs(); + try gcd(&a, r.p, r.q); + r.p.setSign(sign); + + const one = Int.initFixed(([]Limb{1})[0..]); + if (a.cmp(one) != 0) { + var unused = try Int.init(r.p.allocator.?); + defer unused.deinit(); + + // TODO: divexact would be useful here + // TODO: don't copy r.q for div + try Int.divTrunc(&r.p, &unused, r.p, a); + try Int.divTrunc(&r.q, &unused, r.q, a); + } + } +}; + +const SignedDoubleLimb = @IntType(true, DoubleLimb.bit_count); + +fn gcd(rma: *Int, x: Int, y: Int) !void { + rma.assertWritable(); + var r = rma; + var aliased = rma.limbs.ptr == x.limbs.ptr or rma.limbs.ptr == y.limbs.ptr; + + var sr: Int = undefined; + if (aliased) { + sr = try Int.initCapacity(rma.allocator.?, math.max(x.len(), y.len())); + r = &sr; + aliased = true; + } + defer if (aliased) { + rma.swap(r); + r.deinit(); + }; + + try gcdLehmer(r, x, y); +} + +// Storage must live for the lifetime of the returned value +fn FixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Int { + std.debug.assert(storage.len >= 2); + + var A_is_positive = A >= 0; + const Au = @intCast(DoubleLimb, if (A < 0) -A else A); + storage[0] = @truncate(Limb, Au); + storage[1] = @truncate(Limb, Au >> Limb.bit_count); + var Ap = Int.initFixed(storage[0..2]); + Ap.setSign(A_is_positive); + return Ap; +} + +fn gcdLehmer(r: *Int, xa: Int, ya: Int) !void { + var x = try xa.clone(); + x.abs(); + defer x.deinit(); + + var y = try ya.clone(); + y.abs(); + defer y.deinit(); + + if (x.cmp(y) < 0) { + x.swap(&y); + } + + var T = try Int.init(r.allocator.?); + defer T.deinit(); + + while (y.len() > 1) { + debug.assert(x.isPositive() and y.isPositive()); + debug.assert(x.len() >= y.len()); + + var xh: SignedDoubleLimb = x.limbs[x.len() - 1]; + var yh: SignedDoubleLimb = if (x.len() > y.len()) 0 else y.limbs[x.len() - 1]; + + var A: SignedDoubleLimb = 1; + var B: SignedDoubleLimb = 0; + var C: SignedDoubleLimb = 0; + var D: SignedDoubleLimb = 1; + + while (yh + C != 0 and yh + D != 0) { + const q = @divFloor(xh + A, yh + C); + const qp = @divFloor(xh + B, yh + D); + if (q != qp) { + break; + } + + var t = A - q * C; + A = C; + C = t; + t = B - q * D; + B = D; + D = t; + + t = xh - q * yh; + xh = yh; + yh = t; + } + + if (B == 0) { + // T = x % y, r is unused + try Int.divTrunc(r, &T, x, y); + debug.assert(T.isPositive()); + + x.swap(&y); + y.swap(&T); + } else { + var storage: [8]Limb = undefined; + const Ap = FixedIntFromSignedDoubleLimb(A, storage[0..2]); + const Bp = FixedIntFromSignedDoubleLimb(B, storage[2..4]); + const Cp = FixedIntFromSignedDoubleLimb(C, storage[4..6]); + const Dp = FixedIntFromSignedDoubleLimb(D, storage[6..8]); + + // T = Ax + By + try r.mul(x, Ap); + try T.mul(y, Bp); + try T.add(r.*, T); + + // u = Cx + Dy, r as u + try x.mul(x, Cp); + try r.mul(y, Dp); + try r.add(x, r.*); + + x.swap(&T); + y.swap(r); + } + } + + // euclidean algorithm + debug.assert(x.cmp(y) >= 0); + + while (!y.eqZero()) { + try Int.divTrunc(&T, r, x, y); + x.swap(&y); + y.swap(r); + } + + r.swap(&x); +} + +var buffer: [64 * 8192]u8 = undefined; +var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); +var al = &fixed.allocator; + +test "big.rational gcd non-one small" { + var a = try Int.initSet(al, 17); + var b = try Int.initSet(al, 97); + var r = try Int.init(al); + + try gcd(&r, a, b); + + testing.expect((try r.to(u32)) == 1); +} + +test "big.rational gcd non-one small" { + var a = try Int.initSet(al, 4864); + var b = try Int.initSet(al, 3458); + var r = try Int.init(al); + + try gcd(&r, a, b); + + testing.expect((try r.to(u32)) == 38); +} + +test "big.rational gcd non-one large" { + var a = try Int.initSet(al, 0xffffffffffffffff); + var b = try Int.initSet(al, 0xffffffffffffffff7777); + var r = try Int.init(al); + + try gcd(&r, a, b); + + testing.expect((try r.to(u32)) == 4369); +} + +test "big.rational gcd large multi-limb result" { + var a = try Int.initSet(al, 0x12345678123456781234567812345678123456781234567812345678); + var b = try Int.initSet(al, 0x12345671234567123456712345671234567123456712345671234567); + var r = try Int.init(al); + + try gcd(&r, a, b); + + testing.expect((try r.to(u256)) == 0xf000000ff00000fff0000ffff000fffff00ffffff1); +} + +test "big.rational gcd one large" { + var a = try Int.initSet(al, 1897056385327307); + var b = try Int.initSet(al, 2251799813685248); + var r = try Int.init(al); + + try gcd(&r, a, b); + + testing.expect((try r.to(u64)) == 1); +} + +fn extractLowBits(a: Int, comptime T: type) T { + testing.expect(@typeId(T) == builtin.TypeId.Int); + + if (T.bit_count <= Limb.bit_count) { + return @truncate(T, a.limbs[0]); + } else { + var r: T = 0; + comptime var i: usize = 0; + + // Remainder is always 0 since if T.bit_count >= Limb.bit_count -> Limb | T and both + // are powers of two. + inline while (i < T.bit_count / Limb.bit_count) : (i += 1) { + r |= math.shl(T, a.limbs[i], i * Limb.bit_count); + } + + return r; + } +} + +test "big.rational extractLowBits" { + var a = try Int.initSet(al, 0x11112222333344441234567887654321); + + const a1 = extractLowBits(a, u8); + testing.expect(a1 == 0x21); + + const a2 = extractLowBits(a, u16); + testing.expect(a2 == 0x4321); + + const a3 = extractLowBits(a, u32); + testing.expect(a3 == 0x87654321); + + const a4 = extractLowBits(a, u64); + testing.expect(a4 == 0x1234567887654321); + + const a5 = extractLowBits(a, u128); + testing.expect(a5 == 0x11112222333344441234567887654321); +} + +test "big.rational set" { + var a = try Rational.init(al); + + try a.setInt(5); + testing.expect((try a.p.to(u32)) == 5); + testing.expect((try a.q.to(u32)) == 1); + + try a.setRatio(7, 3); + testing.expect((try a.p.to(u32)) == 7); + testing.expect((try a.q.to(u32)) == 3); + + try a.setRatio(9, 3); + testing.expect((try a.p.to(i32)) == 3); + testing.expect((try a.q.to(i32)) == 1); + + try a.setRatio(-9, 3); + testing.expect((try a.p.to(i32)) == -3); + testing.expect((try a.q.to(i32)) == 1); + + try a.setRatio(9, -3); + testing.expect((try a.p.to(i32)) == -3); + testing.expect((try a.q.to(i32)) == 1); + + try a.setRatio(-9, -3); + testing.expect((try a.p.to(i32)) == 3); + testing.expect((try a.q.to(i32)) == 1); +} + +test "big.rational setFloat" { + var a = try Rational.init(al); + + try a.setFloat(f64, 2.5); + testing.expect((try a.p.to(i32)) == 5); + testing.expect((try a.q.to(i32)) == 2); + + try a.setFloat(f32, -2.5); + testing.expect((try a.p.to(i32)) == -5); + testing.expect((try a.q.to(i32)) == 2); + + try a.setFloat(f32, 3.141593); + + // = 3.14159297943115234375 + testing.expect((try a.p.to(u32)) == 3294199); + testing.expect((try a.q.to(u32)) == 1048576); + + try a.setFloat(f64, 72.141593120712409172417410926841290461290467124); + + // = 72.1415931207124145885245525278151035308837890625 + testing.expect((try a.p.to(u128)) == 5076513310880537); + testing.expect((try a.q.to(u128)) == 70368744177664); +} + +test "big.rational setFloatString" { + var a = try Rational.init(al); + + try a.setFloatString("72.14159312071241458852455252781510353"); + + // = 72.1415931207124145885245525278151035308837890625 + testing.expect((try a.p.to(u128)) == 7214159312071241458852455252781510353); + testing.expect((try a.q.to(u128)) == 100000000000000000000000000000000000); +} + +test "big.rational toFloat" { + var a = try Rational.init(al); + + // = 3.14159297943115234375 + try a.setRatio(3294199, 1048576); + testing.expect((try a.toFloat(f64)) == 3.14159297943115234375); + + // = 72.1415931207124145885245525278151035308837890625 + try a.setRatio(5076513310880537, 70368744177664); + testing.expect((try a.toFloat(f64)) == 72.141593120712409172417410926841290461290467124); +} + +test "big.rational set/to Float round-trip" { + var a = try Rational.init(al); + var prng = std.rand.DefaultPrng.init(0x5EED); + var i: usize = 0; + while (i < 512) : (i += 1) { + const r = prng.random.float(f64); + try a.setFloat(f64, r); + testing.expect((try a.toFloat(f64)) == r); + } +} + +test "big.rational copy" { + var a = try Rational.init(al); + + const b = try Int.initSet(al, 5); + + try a.copyInt(b); + testing.expect((try a.p.to(u32)) == 5); + testing.expect((try a.q.to(u32)) == 1); + + const c = try Int.initSet(al, 7); + const d = try Int.initSet(al, 3); + + try a.copyRatio(c, d); + testing.expect((try a.p.to(u32)) == 7); + testing.expect((try a.q.to(u32)) == 3); + + const e = try Int.initSet(al, 9); + const f = try Int.initSet(al, 3); + + try a.copyRatio(e, f); + testing.expect((try a.p.to(u32)) == 3); + testing.expect((try a.q.to(u32)) == 1); +} + +test "big.rational negate" { + var a = try Rational.init(al); + + try a.setInt(-50); + testing.expect((try a.p.to(i32)) == -50); + testing.expect((try a.q.to(i32)) == 1); + + a.negate(); + testing.expect((try a.p.to(i32)) == 50); + testing.expect((try a.q.to(i32)) == 1); + + a.negate(); + testing.expect((try a.p.to(i32)) == -50); + testing.expect((try a.q.to(i32)) == 1); +} + +test "big.rational abs" { + var a = try Rational.init(al); + + try a.setInt(-50); + testing.expect((try a.p.to(i32)) == -50); + testing.expect((try a.q.to(i32)) == 1); + + a.abs(); + testing.expect((try a.p.to(i32)) == 50); + testing.expect((try a.q.to(i32)) == 1); + + a.abs(); + testing.expect((try a.p.to(i32)) == 50); + testing.expect((try a.q.to(i32)) == 1); +} + +test "big.rational swap" { + var a = try Rational.init(al); + var b = try Rational.init(al); + + try a.setRatio(50, 23); + try b.setRatio(17, 3); + + testing.expect((try a.p.to(u32)) == 50); + testing.expect((try a.q.to(u32)) == 23); + + testing.expect((try b.p.to(u32)) == 17); + testing.expect((try b.q.to(u32)) == 3); + + a.swap(&b); + + testing.expect((try a.p.to(u32)) == 17); + testing.expect((try a.q.to(u32)) == 3); + + testing.expect((try b.p.to(u32)) == 50); + testing.expect((try b.q.to(u32)) == 23); +} + +test "big.rational cmp" { + var a = try Rational.init(al); + var b = try Rational.init(al); + + try a.setRatio(500, 231); + try b.setRatio(18903, 8584); + testing.expect((try a.cmp(b)) < 0); + + try a.setRatio(890, 10); + try b.setRatio(89, 1); + testing.expect((try a.cmp(b)) == 0); +} + +test "big.rational add single-limb" { + var a = try Rational.init(al); + var b = try Rational.init(al); + + try a.setRatio(500, 231); + try b.setRatio(18903, 8584); + testing.expect((try a.cmp(b)) < 0); + + try a.setRatio(890, 10); + try b.setRatio(89, 1); + testing.expect((try a.cmp(b)) == 0); +} + +test "big.rational add" { + var a = try Rational.init(al); + var b = try Rational.init(al); + var r = try Rational.init(al); + + try a.setRatio(78923, 23341); + try b.setRatio(123097, 12441414); + try a.add(a, b); + + try r.setRatio(984786924199, 290395044174); + testing.expect((try a.cmp(r)) == 0); +} + +test "big.rational sub" { + var a = try Rational.init(al); + var b = try Rational.init(al); + var r = try Rational.init(al); + + try a.setRatio(78923, 23341); + try b.setRatio(123097, 12441414); + try a.sub(a, b); + + try r.setRatio(979040510045, 290395044174); + testing.expect((try a.cmp(r)) == 0); +} + +test "big.rational mul" { + var a = try Rational.init(al); + var b = try Rational.init(al); + var r = try Rational.init(al); + + try a.setRatio(78923, 23341); + try b.setRatio(123097, 12441414); + try a.mul(a, b); + + try r.setRatio(571481443, 17082061422); + testing.expect((try a.cmp(r)) == 0); +} + +test "big.rational div" { + var a = try Rational.init(al); + var b = try Rational.init(al); + var r = try Rational.init(al); + + try a.setRatio(78923, 23341); + try b.setRatio(123097, 12441414); + try a.div(a, b); + + try r.setRatio(75531824394, 221015929); + testing.expect((try a.cmp(r)) == 0); +} + +test "big.rational div" { + var a = try Rational.init(al); + var r = try Rational.init(al); + + try a.setRatio(78923, 23341); + a.invert(); + + try r.setRatio(23341, 78923); + testing.expect((try a.cmp(r)) == 0); + + try a.setRatio(-78923, 23341); + a.invert(); + + try r.setRatio(-23341, 78923); + testing.expect((try a.cmp(r)) == 0); +} diff --git a/std/special/compiler_rt.zig b/std/special/compiler_rt.zig index f15cf42be2..e2ecd1b0cf 100644 --- a/std/special/compiler_rt.zig +++ b/std/special/compiler_rt.zig @@ -160,10 +160,11 @@ comptime { @export("__chkstk", __chkstk, strong_linkage); @export("___chkstk_ms", ___chkstk_ms, linkage); } + // The "ti" functions must use @Vector(2, u64) parameter types to adhere to the ABI + // that LLVM expects compiler-rt to have. @export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage); @export("__modti3", @import("compiler_rt/modti3.zig").__modti3_windows_x86_64, linkage); @export("__multi3", @import("compiler_rt/multi3.zig").__multi3_windows_x86_64, linkage); - @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4_windows_x86_64, linkage); @export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64, linkage); @export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64, linkage); @export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64, linkage); @@ -174,11 +175,11 @@ comptime { @export("__divti3", @import("compiler_rt/divti3.zig").__divti3, linkage); @export("__modti3", @import("compiler_rt/modti3.zig").__modti3, linkage); @export("__multi3", @import("compiler_rt/multi3.zig").__multi3, linkage); - @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4, linkage); @export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3, linkage); @export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4, linkage); @export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3, linkage); } + @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4, linkage); } const std = @import("std"); @@ -198,17 +199,6 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn } } -pub fn setXmm0(comptime T: type, value: T) void { - comptime assert(builtin.arch == builtin.Arch.x86_64); - const aligned_value: T align(16) = value; - asm volatile ( - \\movaps (%[ptr]), %%xmm0 - : - : [ptr] "r" (&aligned_value) - : "xmm0" - ); -} - extern fn __udivdi3(a: u64, b: u64) u64 { @setRuntimeSafety(is_test); return __udivmoddi4(a, b, null); diff --git a/std/special/compiler_rt/divti3.zig b/std/special/compiler_rt/divti3.zig index e89a1ada5c..d5b2778a34 100644 --- a/std/special/compiler_rt/divti3.zig +++ b/std/special/compiler_rt/divti3.zig @@ -16,9 +16,9 @@ pub extern fn __divti3(a: i128, b: i128) i128 { return (@bitCast(i128, r) ^ s) -% s; } -pub extern fn __divti3_windows_x86_64(a: *const i128, b: *const i128) void { - @setRuntimeSafety(builtin.is_test); - compiler_rt.setXmm0(i128, __divti3(a.*, b.*)); +const v128 = @Vector(2, u64); +pub extern fn __divti3_windows_x86_64(a: v128, b: v128) v128 { + return @bitCast(v128, @inlineCall(__divti3, @bitCast(i128, a), @bitCast(i128, b))); } test "import divti3" { diff --git a/std/special/compiler_rt/modti3.zig b/std/special/compiler_rt/modti3.zig index 03222cadf5..16f2f38ba3 100644 --- a/std/special/compiler_rt/modti3.zig +++ b/std/special/compiler_rt/modti3.zig @@ -20,9 +20,9 @@ pub extern fn __modti3(a: i128, b: i128) i128 { return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -1 } -pub extern fn __modti3_windows_x86_64(a: *const i128, b: *const i128) void { - @setRuntimeSafety(builtin.is_test); - compiler_rt.setXmm0(i128, __modti3(a.*, b.*)); +const v128 = @Vector(2, u64); +pub extern fn __modti3_windows_x86_64(a: v128, b: v128) v128 { + return @bitCast(v128, @inlineCall(__modti3, @bitCast(i128, a), @bitCast(i128, b))); } test "import modti3" { diff --git a/std/special/compiler_rt/muloti4.zig b/std/special/compiler_rt/muloti4.zig index fd6855072b..ccde8e3e6c 100644 --- a/std/special/compiler_rt/muloti4.zig +++ b/std/special/compiler_rt/muloti4.zig @@ -1,4 +1,3 @@ -const udivmod = @import("udivmod.zig").udivmod; const builtin = @import("builtin"); const compiler_rt = @import("../compiler_rt.zig"); @@ -33,11 +32,11 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 { } if (sa == sb) { - if (abs_a > @divFloor(max, abs_b)) { + if (abs_a > @divTrunc(max, abs_b)) { overflow.* = 1; } } else { - if (abs_a > @divFloor(min, -abs_b)) { + if (abs_a > @divTrunc(min, -abs_b)) { overflow.* = 1; } } @@ -45,11 +44,6 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 { return r; } -pub extern fn __muloti4_windows_x86_64(a: *const i128, b: *const i128, overflow: *c_int) void { - @setRuntimeSafety(builtin.is_test); - compiler_rt.setXmm0(i128, __muloti4(a.*, b.*, overflow)); -} - test "import muloti4" { _ = @import("muloti4_test.zig"); } diff --git a/std/special/compiler_rt/multi3.zig b/std/special/compiler_rt/multi3.zig index a0c84adaf4..799b1f575d 100644 --- a/std/special/compiler_rt/multi3.zig +++ b/std/special/compiler_rt/multi3.zig @@ -14,9 +14,9 @@ pub extern fn __multi3(a: i128, b: i128) i128 { return r.all; } -pub extern fn __multi3_windows_x86_64(a: *const i128, b: *const i128) void { - @setRuntimeSafety(builtin.is_test); - compiler_rt.setXmm0(i128, __multi3(a.*, b.*)); +const v128 = @Vector(2, u64); +pub extern fn __multi3_windows_x86_64(a: v128, b: v128) v128 { + return @bitCast(v128, @inlineCall(__multi3, @bitCast(i128, a), @bitCast(i128, b))); } fn __mulddi3(a: u64, b: u64) i128 { diff --git a/std/special/compiler_rt/udivmodti4.zig b/std/special/compiler_rt/udivmodti4.zig index 6a037d3bae..c74dff512d 100644 --- a/std/special/compiler_rt/udivmodti4.zig +++ b/std/special/compiler_rt/udivmodti4.zig @@ -7,9 +7,10 @@ pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) u128 { return udivmod(u128, a, b, maybe_rem); } -pub extern fn __udivmodti4_windows_x86_64(a: *const u128, b: *const u128, maybe_rem: ?*u128) void { +const v128 = @Vector(2, u64); +pub extern fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) v128 { @setRuntimeSafety(builtin.is_test); - compiler_rt.setXmm0(u128, udivmod(u128, a.*, b.*, maybe_rem)); + return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), maybe_rem)); } test "import udivmodti4" { diff --git a/std/special/compiler_rt/udivti3.zig b/std/special/compiler_rt/udivti3.zig index 510e21ac1d..ab451859bf 100644 --- a/std/special/compiler_rt/udivti3.zig +++ b/std/special/compiler_rt/udivti3.zig @@ -6,7 +6,8 @@ pub extern fn __udivti3(a: u128, b: u128) u128 { return udivmodti4.__udivmodti4(a, b, null); } -pub extern fn __udivti3_windows_x86_64(a: *const u128, b: *const u128) void { +const v128 = @Vector(2, u64); +pub extern fn __udivti3_windows_x86_64(a: v128, b: v128) v128 { @setRuntimeSafety(builtin.is_test); - udivmodti4.__udivmodti4_windows_x86_64(a, b, null); + return udivmodti4.__udivmodti4_windows_x86_64(a, b, null); } diff --git a/std/special/compiler_rt/umodti3.zig b/std/special/compiler_rt/umodti3.zig index 12aca8b036..7add0b2ffe 100644 --- a/std/special/compiler_rt/umodti3.zig +++ b/std/special/compiler_rt/umodti3.zig @@ -9,7 +9,7 @@ pub extern fn __umodti3(a: u128, b: u128) u128 { return r; } -pub extern fn __umodti3_windows_x86_64(a: *const u128, b: *const u128) void { - @setRuntimeSafety(builtin.is_test); - compiler_rt.setXmm0(u128, __umodti3(a.*, b.*)); +const v128 = @Vector(2, u64); +pub extern fn __umodti3_windows_x86_64(a: v128, b: v128) v128 { + return @bitCast(v128, @inlineCall(__umodti3, @bitCast(u128, a), @bitCast(u128, b))); } diff --git a/test/stage1/behavior/bit_shifting.zig b/test/stage1/behavior/bit_shifting.zig index 610acc06c2..c638ec1709 100644 --- a/test/stage1/behavior/bit_shifting.zig +++ b/test/stage1/behavior/bit_shifting.zig @@ -86,3 +86,11 @@ fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, c expect(table.get(@intCast(Key, i)) == node); } } + +// #2225 +test "comptime shr of BigInt" { + comptime { + var n = 0xdeadbeef0000000000000000; + std.debug.assert(n >> 64 == 0xdeadbeef); + } +} diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig index 23dc6d1feb..acbd9209df 100644 --- a/test/stage1/behavior/math.zig +++ b/test/stage1/behavior/math.zig @@ -632,3 +632,10 @@ fn testNanEqNan(comptime F: type) void { expect(!(nan1 < nan2)); expect(!(nan1 <= nan2)); } + +test "128-bit multiplication" { + var a: i128 = 3; + var b: i128 = 2; + var c = a * b; + expect(c == 6); +} |
