-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stage2 translate-c: function body statements #2569
Conversation
BTW did you see that |
@andrewrk Cool, I hadn't seen that! I'll make use of that once the new changes can pass a test. Current status: This is getting bigger than I wanted, but after a squish 'n' rebase it shouldn't cause any problems. Something I did is causing infinitely nesting blocks to be rendered when one or more local var decl exists in the function body. After that is solved I'll fast-track this to mergeability. |
Something is wrong with this test. It passes on my Linux machine but not on mac:
I think there may be a legitimate bug in my string literal implementation but I haven't identified it yet. |
Regarding the error, I was able to get more information by running debug zig, and it looks like it may be related to result location. See https://gist.github.com/Sahnvour/16d36b44e0d313a1cd520ba4b6e0eccd. |
Indeed, the crash appears to be a regression from result location changes, in the return statement of this code: fn getExprQualType(c: *Context, expr: *const ZigClangExpr) ZigClangQualType {
blk: {
// If this is a C `char *`, turn it into a `const char *`
if (ZigClangExpr_getStmtClass(expr) != .ImplicitCastExprClass) break :blk;
const cast_expr = @ptrCast(*const ZigClangImplicitCastExpr, expr);
if (ZigClangImplicitCastExpr_getCastKind(cast_expr) != .ArrayToPointerDecay) break :blk;
const sub_expr = ZigClangImplicitCastExpr_getSubExpr(cast_expr);
if (ZigClangExpr_getStmtClass(sub_expr) != .StringLiteralClass) break :blk;
const array_qt = ZigClangExpr_getType(sub_expr);
const array_type = @ptrCast(*const ZigClangArrayType, ZigClangQualType_getTypePtr(array_qt));
var pointee_qt = ZigClangArrayType_getElementType(array_type);
ZigClangQualType_addConst(&pointee_qt);
return ZigClangASTContext_getPointerType(c.clang_context, pointee_qt);
}
return ZigClangExpr_getType(expr);
} I'll modify the code to work around the issue and then try to come up with a reduction for the bug to fix separately. |
I was able to fix the issue. Here's an explanation. First of all, why is it failing on Windows? I don't know, but we were tripping an LLVM assert on all platforms and Windows just happened to be the one where Undefined Behavior caused a crash. It would have eventually been caught regardless, when we tested the code on a debug build of LLVM, which I always do for the branch that tests against the next LLVM version. A debug build of LLVM catches this issue on all platforms, not just Windows. What happened is that, before, we had this code: } else if (handle_is_ptr(src_return_type)) {
LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
LLVMSetAlignment(store_instr, LLVMGetAlignment(result_loc)); // note this line
return result_loc;
} else { Except before the result location branch, unsigned LLVMGetAlignment(LLVMValueRef V) {
Value *P = unwrap<Value>(V);
if (GlobalValue *GV = dyn_cast<GlobalValue>(P))
return GV->getAlignment();
if (AllocaInst *AI = dyn_cast<AllocaInst>(P))
return AI->getAlignment();
if (LoadInst *LI = dyn_cast<LoadInst>(P))
return LI->getAlignment();
if (StoreInst *SI = dyn_cast<StoreInst>(P))
return SI->getAlignment();
llvm_unreachable(
"only GlobalValue, AllocaInst, LoadInst and StoreInst have alignment");
} So you can see that it always worked before because it always hit the AllocaInst case. However, after result location changes, the result location value is not necessarily an LLVM Alloca instruction. However, it is always a pointer, and we have a Zig type for it. So the fix is to use that type information: } else if (handle_is_ptr(src_return_type)) {
LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
- LLVMSetAlignment(store_instr, LLVMGetAlignment(result_loc));
+ LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value.type));
return result_loc;
} else { After this fix, I can build zig against debug LLVM and all the translate-c tests pass 🎉 |
Amazing explanation of what happened! |
See #1964
Overview
This PR adds various translations that apply to statements inside function bodies.
Support translating from these Clang classes:
Other changes
fn
to match stage2 behavior. This convergence was done to make existing translate-c test cases work for both stage1 and stage2. stage2 behavior was favored because the existing meaningful tests on rendering (i.e.zig fmt
) pertain to stage2.Regressions
TODO
severala few stage1 test cases to stage1+stage2Clean up clang.zig?