|
380 | 380 | @test (verify(mod); true) |
381 | 381 | end |
382 | 382 |
|
| 383 | + # typed-pointer shim with an integer-ABI attribute on the boundary: Julia tags the |
| 384 | + # `ptrtoint` image with `zeroext`, which is invalid once the parameter/argument is |
| 385 | + # retargeted to a pointer. the pass must drop it on the parameter *and* the call site, or |
| 386 | + # the module fails verification. (regression: the parameter side was cleaned but the call |
| 387 | + # site kept its `zeroext`, leaving `i8 addrspace(2)* zeroext` and crashing LLVM |
| 388 | + # verification of throwing kernels on Julia 1.10/1.11 -- JuliaGPU/Metal.jl device exceptions.) |
| 389 | + Context() do ctx |
| 390 | + i8 = LLVM.Int8Type() |
| 391 | + i64 = LLVM.Int64Type() |
| 392 | + mod = LLVM.Module("test") |
| 393 | + callee_ft = LLVM.FunctionType(i8, LLVM.LLVMType[i64]) |
| 394 | + callee = LLVM.Function(mod, "callee", callee_ft) |
| 395 | + linkage!(callee, LLVM.API.LLVMInternalLinkage) |
| 396 | + push!(parameter_attributes(callee, 1), EnumAttribute("zeroext", 0)) |
| 397 | + @dispose builder=IRBuilder() begin |
| 398 | + position!(builder, BasicBlock(callee, "entry")) |
| 399 | + p = inttoptr!(builder, parameters(callee)[1], asptr(0)) |
| 400 | + ret!(builder, load!(builder, i8, p)) |
| 401 | + end |
| 402 | + g = GlobalVariable(mod, i8, "g", 2) |
| 403 | + initializer!(g, ConstantInt(i8, 1)); constant!(g, true) |
| 404 | + caller = LLVM.Function(mod, "caller", LLVM.FunctionType(i8, LLVM.LLVMType[])) |
| 405 | + linkage!(caller, LLVM.API.LLVMInternalLinkage) |
| 406 | + @dispose builder=IRBuilder() begin |
| 407 | + position!(builder, BasicBlock(caller, "entry")) |
| 408 | + arg = const_ptrtoint(const_addrspacecast(g, asptr(0)), i64) |
| 409 | + cs = call!(builder, callee_ft, callee, [arg]) |
| 410 | + push!(argument_attributes(cs, 1), EnumAttribute("zeroext", 0)) |
| 411 | + ret!(builder, cs) |
| 412 | + end |
| 413 | + @test (verify(mod); true) # `zeroext` on the i64 boundary is valid pre-narrowing |
| 414 | + |
| 415 | + if supports_typed_pointers() |
| 416 | + @test GPUCompiler.propagate_argument_address_spaces!(mod) |
| 417 | + # the retargeted pointer must not keep the integer's `zeroext`, on either side |
| 418 | + callee = functions(mod)["callee"] |
| 419 | + @test !(kind(EnumAttribute("zeroext", 0)) in |
| 420 | + kind.(collect(parameter_attributes(callee, 1)))) |
| 421 | + @test all(c -> !(kind(EnumAttribute("zeroext", 0)) in |
| 422 | + kind.(collect(argument_attributes(c, 1)))), calls_to(mod, "callee")) |
| 423 | + else |
| 424 | + @test !GPUCompiler.propagate_argument_address_spaces!(mod) |
| 425 | + end |
| 426 | + @test (verify(mod); true) |
| 427 | + end |
| 428 | + |
383 | 429 | # an integer parameter used as more than a pointer image (here also in arithmetic) is |
384 | 430 | # left alone: narrowing it would lose the integer's other uses (and under opaque pointers |
385 | 431 | # the typed-pointer shim is off, so it is left alone regardless) |
|
0 commit comments