https://github.com/vtjnash updated https://github.com/llvm/llvm-project/pull/197540
>From 655e4ebc56bc913aa7e5d4172a0dea5591961cb9 Mon Sep 17 00:00:00 2001 From: Jameson Nash <[email protected]> Date: Fri, 13 Feb 2026 16:18:13 +0000 Subject: [PATCH 1/4] [clang] Change Alloca type when non-default specified Change alloca semantics to be taken from Sema unless the semantics say to use the default addrspace, in which case it takes the default from the datalayout. This lets frontends (or users) to select multiple address spaces for alloca with some special semantics. For example, it may be common for a GC to have a separate addrspace for GC-tracked alloca vs all other alloca. In WASM, this is the flat vs. local address space, for example. --- clang/lib/CodeGen/CGCUDANV.cpp | 5 +++-- clang/lib/CodeGen/CGCall.cpp | 2 +- clang/lib/CodeGen/CGCleanup.cpp | 2 +- clang/lib/CodeGen/CGCoroutine.cpp | 8 ++++---- clang/lib/CodeGen/CGException.cpp | 11 +++++++---- clang/lib/CodeGen/CGExpr.cpp | 29 ++++++++++++++++++----------- clang/lib/CodeGen/CGExprCXX.cpp | 3 ++- clang/lib/CodeGen/CGGPUBuiltin.cpp | 2 +- clang/lib/CodeGen/CodeGenFunction.h | 8 +++++--- 9 files changed, 42 insertions(+), 28 deletions(-) diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index 259b6c040706b..e0343b15aba9c 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -345,9 +345,10 @@ Address CGNVCUDARuntime::prepareKernelArgsLLVMOffload(CodeGenFunction &CGF, llvm::StructType *KernelLaunchParamsTy = llvm::StructType::create(KernelLaunchParamsTypes); Address KernelArgs = CGF.CreateTempAllocaWithoutCast( - KernelArgsTy, CharUnits::fromQuantity(16), "kernel_args"); + KernelArgsTy, LangAS::Default, CharUnits::fromQuantity(16), + "kernel_args"); Address KernelLaunchParams = CGF.CreateTempAllocaWithoutCast( - KernelLaunchParamsTy, CharUnits::fromQuantity(16), + KernelLaunchParamsTy, LangAS::Default, CharUnits::fromQuantity(16), "kernel_launch_params"); auto KernelArgsSize = CGM.getDataLayout().getTypeAllocSize(KernelArgsTy); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 40cc275d40273..d754189ce1a3c 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -5504,7 +5504,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, AI = new llvm::AllocaInst(ArgStruct, DL.getAllocaAddrSpace(), "argmem", IP->getIterator()); } else { - AI = CreateTempAlloca(ArgStruct, "argmem"); + AI = CreateTempAlloca(ArgStruct, LangAS::Default, "argmem"); } auto Align = CallInfo.getArgStructAlignment(); AI->setAlignment(Align.getAsAlign()); diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index 977f81a641ff3..02c057f7fb962 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -279,7 +279,7 @@ void EHScopeStack::popNullFixups() { RawAddress CodeGenFunction::createCleanupActiveFlag() { // Create a variable to decide whether the cleanup needs to be run. RawAddress active = CreateTempAllocaWithoutCast( - Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond"); + Builder.getInt1Ty(), LangAS::Default, CharUnits::One(), "cleanup.cond"); // Initialize it to false at a site that's guaranteed to be run // before each evaluation. diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index fac2047d54d63..4b40341ac9cb4 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -344,8 +344,8 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co CXXTryStmt *TryStmt = nullptr; if (Coro.ExceptionHandler && Kind == AwaitKind::Init && StmtCanThrow(S.getResumeExpr())) { - Coro.ResumeEHVar = - CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh")); + Coro.ResumeEHVar = CGF.CreateTempAlloca( + Builder.getInt1Ty(), LangAS::Default, Prefix + Twine("resume.eh")); Builder.CreateFlagStore(true, Coro.ResumeEHVar); auto Loc = S.getResumeExpr()->getExprLoc(); @@ -707,8 +707,8 @@ struct GetReturnObjectManager { } // Set GRO flag that it is not initialized yet - GroActiveFlag = CGF.CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(), - "gro.active"); + GroActiveFlag = CGF.CreateTempAlloca(Builder.getInt1Ty(), LangAS::Default, + CharUnits::One(), "gro.active"); Builder.CreateStore(Builder.getFalse(), GroActiveFlag); } diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 99dfaa80be429..a98fa026f5c8d 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -425,13 +425,14 @@ void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { Address CodeGenFunction::getExceptionSlot() { if (!ExceptionSlot) - ExceptionSlot = CreateTempAlloca(Int8PtrTy, "exn.slot"); + ExceptionSlot = CreateTempAlloca(Int8PtrTy, LangAS::Default, "exn.slot"); return Address(ExceptionSlot, Int8PtrTy, getPointerAlign()); } Address CodeGenFunction::getEHSelectorSlot() { if (!EHSelectorSlot) - EHSelectorSlot = CreateTempAlloca(Int32Ty, "ehselector.slot"); + EHSelectorSlot = + CreateTempAlloca(Int32Ty, LangAS::Default, "ehselector.slot"); return Address(EHSelectorSlot, Int32Ty, CharUnits::fromQuantity(4)); } @@ -1453,7 +1454,8 @@ void CodeGenFunction::FinallyInfo::enter(CodeGenFunction &CGF, const Stmt *body, llvm::FunctionType *rethrowFnTy = rethrowFn.getFunctionType(); SavedExnVar = nullptr; if (rethrowFnTy->getNumParams()) - SavedExnVar = CGF.CreateTempAlloca(CGF.Int8PtrTy, "finally.exn"); + SavedExnVar = + CGF.CreateTempAlloca(CGF.Int8PtrTy, LangAS::Default, "finally.exn"); // A finally block is a statement which must be executed on any edge // out of a given scope. Unlike a cleanup, the finally block may @@ -1473,7 +1475,8 @@ void CodeGenFunction::FinallyInfo::enter(CodeGenFunction &CGF, const Stmt *body, RethrowDest = CGF.getJumpDestInCurrentScope(CGF.getUnreachableBlock()); // Whether the finally block is being executed for EH purposes. - ForEHVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "finally.for-eh"); + ForEHVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), LangAS::Default, + "finally.for-eh"); CGF.Builder.CreateFlagStore(false, ForEHVar); // Enter a normal cleanup which will perform the @finally block. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index f6cb636368598..036e897c368dc 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -105,15 +105,13 @@ static llvm::StringRef GetUBSanTrapForHandler(SanitizerHandler ID) { /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. RawAddress -CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize) { +CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, LangAS UseAddrSpace, CharUnits Align, const Twine &Name, llvm::Value *ArraySize) { if (getLangOpts().EmitLogicalPointer) { auto Alloca = Builder.CreateStructuredAlloca(Ty, Name); return RawAddress(Alloca, Ty, Align, KnownNonNull); } - auto *Alloca = CreateTempAlloca(Ty, Name, ArraySize); + auto *Alloca = CreateTempAlloca(Ty, UseAddrSpace, Name, ArraySize); Alloca->setAlignment(Align.getAsAlign()); return RawAddress(Alloca, Ty, Align, KnownNonNull); } @@ -147,7 +145,8 @@ RawAddress CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, LangAS DestLangAS, CharUnits Align, const Twine &Name, llvm::Value *ArraySize, RawAddress *AllocaAddr) { - RawAddress Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize); + RawAddress Alloca = + CreateTempAllocaWithoutCast(Ty, DestLangAS, Align, Name, ArraySize); if (AllocaAddr) *AllocaAddr = Alloca; return MaybeCastStackAddressSpace(Alloca, DestLangAS, ArraySize); @@ -157,15 +156,21 @@ RawAddress CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, LangAS DestLangAS, /// block if \p ArraySize is nullptr, otherwise inserts it at the current /// insertion point of the builder. llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, + LangAS UseLangAS, const Twine &Name, llvm::Value *ArraySize) { + // Determine the address space for the alloca, whether marked as default + // or specified explicitly + unsigned AllocaAS = UseLangAS == LangAS::Default + ? CGM.getDataLayout().getAllocaAddrSpace() + : getContext().getTargetAddressSpace(UseLangAS); + llvm::AllocaInst *Alloca; if (ArraySize) - Alloca = Builder.CreateAlloca(Ty, ArraySize, Name); + Alloca = Builder.CreateAlloca(Ty, AllocaAS, ArraySize, Name); else - Alloca = - new llvm::AllocaInst(Ty, CGM.getDataLayout().getAllocaAddrSpace(), - ArraySize, Name, AllocaInsertPt->getIterator()); + Alloca = new llvm::AllocaInst(Ty, AllocaAS, ArraySize, Name, + AllocaInsertPt->getIterator()); if (SanOpts.Mask & SanitizerKind::Address) { Alloca->addAnnotationMetadata({"alloca_name_altered", Name.str()}); } @@ -189,7 +194,8 @@ RawAddress CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, RawAddress CodeGenFunction::CreateIRTempWithoutCast(QualType Ty, const Twine &Name) { CharUnits Align = getContext().getTypeAlignInChars(Ty); - return CreateTempAllocaWithoutCast(ConvertType(Ty), Align, Name, nullptr); + return CreateTempAllocaWithoutCast(ConvertType(Ty), Ty.getAddressSpace(), + Align, Name, nullptr); } RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, @@ -225,7 +231,8 @@ RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, CharUnits Align, const Twine &Name) { - return CreateTempAllocaWithoutCast(ConvertTypeForMem(Ty), Align, Name); + return CreateTempAllocaWithoutCast(ConvertTypeForMem(Ty), + Ty.getAddressSpace(), Align, Name); } RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 0dc2e0bb82114..68514dcbc924a 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1815,7 +1815,8 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, assert(!TagAlloca); llvm::Type *Ty = getTypes().ConvertType(TagType); CharUnits Align = CGM.getNaturalTypeAlignment(TagType); - llvm::AllocaInst *TagAllocation = CreateTempAlloca(Ty, TagName); + llvm::AllocaInst *TagAllocation = + CreateTempAlloca(Ty, TagType.getAddressSpace(), TagName); TagAllocation->setAlignment(Align.getAsAlign()); DeleteArgs.add(RValue::getAggregate(Address(TagAllocation, Ty, Align)), TagType); diff --git a/clang/lib/CodeGen/CGGPUBuiltin.cpp b/clang/lib/CodeGen/CGGPUBuiltin.cpp index 47cac03b64532..6b0cebdac1960 100644 --- a/clang/lib/CodeGen/CGGPUBuiltin.cpp +++ b/clang/lib/CodeGen/CGGPUBuiltin.cpp @@ -90,7 +90,7 @@ packArgsIntoNVPTXFormatBuffer(CodeGenFunction *CGF, const CallArgList &Args) { // that the alignment of the llvm type was the same as the alignment of the // clang type. llvm::Type *AllocaTy = llvm::StructType::create(ArgTypes, "printf_args"); - llvm::Value *Alloca = CGF->CreateTempAlloca(AllocaTy); + llvm::Value *Alloca = CGF->CreateTempAlloca(AllocaTy, LangAS::Default); for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I) { llvm::Value *P = Builder.CreateStructGEP(AllocaTy, Alloca, I - 1); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 6bb9f285ebcfd..3eb458154272d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2892,7 +2892,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// /// The cast is not performed in CreateTempAllocaWithoutCast. This is /// more efficient if the caller knows that the address will not be exposed. - llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp", + llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, LangAS UseAddrSpace, + const Twine &Name = "tmp", llvm::Value *ArraySize = nullptr); /// CreateTempAlloca - This creates a alloca and inserts it into the entry @@ -2916,7 +2917,8 @@ class CodeGenFunction : public CodeGenTypeCache { Alloca); } - RawAddress CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, + RawAddress CreateTempAllocaWithoutCast(llvm::Type *Ty, LangAS UseAddrSpace, + CharUnits align, const Twine &Name = "tmp", llvm::Value *ArraySize = nullptr); @@ -5653,7 +5655,7 @@ DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { CGF.CGM.getDataLayout().getPrefTypeAlign(value->getType())) .getAsAlign(); llvm::AllocaInst *AI = - CGF.CreateTempAlloca(value->getType(), "cond-cleanup.save"); + CGF.CreateTempAlloca(value->getType(), LangAS::Default, "cond-cleanup.save"); AI->setAlignment(align); CGF.Builder.CreateAlignedStore(value, AI, align); >From 19e3e8f7a9e99946830e184c0d02ad4ef21d07a0 Mon Sep 17 00:00:00 2001 From: Jameson Nash <[email protected]> Date: Thu, 29 Jan 2026 17:20:00 +0000 Subject: [PATCH 2/4] [Clang][WebAssembly] Move reference type alloca handling to frontend Move WebAssembly reference type alloca address space selection from the WebAssemblyRefTypeMem2Local LLVM pass into Clang's Sema definition. This is a semantic requirement (essentially there are two alloca space here--flat memory and local memory), so it doesn't seem to make sense for LLVM to try to recover this information late, and especially to assume getAllocatedType can provide this information. Similar to global, the key idea here is to use the user's specified address space for creating an alloca, instead of doing an addrspace cast to that. That especially allows a frontend to force the alloca to live in an addrspace that isn't the default one. This then lets us delete the IR pass from LLVM that relies on bypassing the validator (which only happened to work since it only fed a load or store instruction in the test) and using the non-semantic getAllocatedType to recover and fix the incorrect alloca addrspace originally set by Seme. Building upon that, this then defines an addrspace for the WebAssembly local semantics LangAS::wasm_var, matching WASM_ADDRESS_SPACE_VAR, for pointers to reference types (externref / funcref). Example: __externref_t x; // ptr addrspace(10) __externref_t *px; // ptr addrspace(1) in AST (points to ptr addrspace(10)) __externref_t &rx = x; // ptr addrspace(1) in AST Co-Authored-By: Claude Sonnet 4.5 <[email protected]> --- clang/include/clang/Basic/AddressSpaces.h | 1 + clang/include/clang/Sema/Sema.h | 1 + clang/lib/AST/ASTContext.cpp | 9 ++ clang/lib/AST/Decl.cpp | 10 ++- clang/lib/AST/TypePrinter.cpp | 2 + clang/lib/Basic/TargetInfo.cpp | 1 + clang/lib/Basic/Targets/AArch64.h | 3 +- clang/lib/Basic/Targets/AMDGPU.cpp | 14 ++- clang/lib/Basic/Targets/DirectX.h | 3 +- clang/lib/Basic/Targets/NVPTX.h | 3 +- clang/lib/Basic/Targets/SPIR.h | 11 ++- clang/lib/Basic/Targets/SystemZ.h | 3 +- clang/lib/Basic/Targets/TCE.h | 3 +- clang/lib/Basic/Targets/WebAssembly.h | 1 + clang/lib/Basic/Targets/X86.h | 3 +- clang/lib/CodeGen/CGDecl.cpp | 10 +-- clang/lib/Sema/SemaDecl.cpp | 86 ++++++++++--------- .../WebAssembly/reference-type-alloca.c | 35 ++++++++ .../test/CodeGen/WebAssembly/wasm-externref.c | 6 +- clang/test/CodeGen/WebAssembly/wasm-funcref.c | 18 ++-- .../test/CodeGenCXX/wasm-reftypes-mangle.cpp | 4 +- clang/test/Sema/wasm-refs-and-tables.c | 18 ++-- .../SemaTemplate/address_space-dependent.cpp | 4 +- 23 files changed, 169 insertions(+), 80 deletions(-) create mode 100644 clang/test/CodeGen/WebAssembly/reference-type-alloca.c diff --git a/clang/include/clang/Basic/AddressSpaces.h b/clang/include/clang/Basic/AddressSpaces.h index a941805423bca..1bffb13bcdc94 100644 --- a/clang/include/clang/Basic/AddressSpaces.h +++ b/clang/include/clang/Basic/AddressSpaces.h @@ -67,6 +67,7 @@ enum class LangAS : unsigned { // Wasm specific address spaces. wasm_funcref, + wasm_var, // This denotes the count of language-specific address spaces and also // the offset added to the target-specific address spaces, which are usually diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b8d760e7e0975..ec50948bfff23 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4702,6 +4702,7 @@ class Sema final : public SemaBase { void deduceOpenCLAddressSpace(VarDecl *decl); void deduceHLSLAddressSpace(VarDecl *decl); + void deduceWasmAddressSpace(VarDecl *Decl); /// Adjust the \c DeclContext for a function or variable that might be a /// function-local external declaration. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 1e35aba7b2b19..763cd68e7948f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -15070,6 +15070,15 @@ LangAS ASTContext::getLangASForBuiltinAddressSpace(unsigned AS) const { if (LangOpts.CUDA) return getTargetInfo().getCUDABuiltinAddressSpace(AS); + if (getTargetInfo().getTriple().isWasm()) { + switch (AS) { + case 1: + return LangAS::wasm_var; + case 20: + return LangAS::wasm_funcref; + } + } + return getLangASFromTargetAS(AS); } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index b797ebfa1a7e1..4a800453e9ca2 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2919,9 +2919,17 @@ void VarDecl::assignAddressSpace(const ASTContext &Ctxt, LangAS AS) { } void VarDecl::deduceParmAddressSpace(const ASTContext &Ctxt) { - assert(isa<ParmVarDecl>(this) || isa<ImplicitParamDecl>(this)); if (Ctxt.getLangOpts().OpenCL) assignAddressSpace(Ctxt, LangAS::opencl_private); + if (Ctxt.getTargetInfo().getTriple().isWasm()) { + // For WebAssembly, variables holding reference types must have a special + // address space when taking their reference. + QualType Type = getType(); + if (const auto *ATy = dyn_cast<ArrayType>(Type)) + Type = ATy->getElementType(); + if (Type.isWebAssemblyReferenceType()) + assignAddressSpace(Ctxt, LangAS::wasm_var); + } } //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index d85ed244f643a..4c51754a2282f 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2720,6 +2720,8 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) { return "hlsl_push_constant"; case LangAS::wasm_funcref: return "__funcref"; + case LangAS::wasm_var: + return "__externref"; default: return std::to_string(toTargetAddressSpace(AS)); } diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 854d23cadaea2..41ea62152aafb 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -55,6 +55,7 @@ static const LangASMap FakeAddrSpaceMap = { 18, // hlsl_output 19, // hlsl_push_constant 20, // wasm_funcref + 21, // wasm_externref }; // TargetInfo Constructor. diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index 0a29bad81939b..5bbda7313cc1c 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -53,7 +53,8 @@ static const unsigned ARM64AddrSpaceMap[] = { 0, // hlsl_push_constant // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. - 20, // wasm_funcref + 0, // wasm_funcref + 0, // wasm_var }; using AArch64FeatureSet = llvm::SmallDenseSet<StringRef, 32>; diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp index 6b077dfa8e142..c34e6a4bde1a9 100644 --- a/clang/lib/Basic/Targets/AMDGPU.cpp +++ b/clang/lib/Basic/Targets/AMDGPU.cpp @@ -56,6 +56,10 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = { llvm::AMDGPUAS::PRIVATE_ADDRESS, // hlsl_input llvm::AMDGPUAS::PRIVATE_ADDRESS, // hlsl_output llvm::AMDGPUAS::GLOBAL_ADDRESS, // hlsl_push_constant + // Wasm address space values for this target are dummy values, + // as it is only enabled for Wasm targets. + llvm::AMDGPUAS::FLAT_ADDRESS, // wasm_funcref + llvm::AMDGPUAS::FLAT_ADDRESS, // wasm_var }; const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = { @@ -86,6 +90,10 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = { llvm::AMDGPUAS::PRIVATE_ADDRESS, // hlsl_input llvm::AMDGPUAS::PRIVATE_ADDRESS, // hlsl_output llvm::AMDGPUAS::GLOBAL_ADDRESS, // hlsl_push_constant + // Wasm address space values for this target are dummy values, + // as it is only enabled for Wasm targets. + llvm::AMDGPUAS::FLAT_ADDRESS, // wasm_funcref + llvm::AMDGPUAS::FLAT_ADDRESS, // wasm_var }; } // namespace targets } // namespace clang @@ -218,7 +226,11 @@ void AMDGPUTargetInfo::fillValidCPUList( } void AMDGPUTargetInfo::setAddressSpaceMap(bool DefaultIsPrivate) { - AddrSpaceMap = DefaultIsPrivate ? &AMDGPUDefIsPrivMap : &AMDGPUDefIsGenMap; + // Use separate assignments so the compiler will enforce the size is correct. + if (DefaultIsPrivate) + AddrSpaceMap = &AMDGPUDefIsPrivMap; + else + AddrSpaceMap = &AMDGPUDefIsGenMap; } AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple, diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h index 8b21b86bac264..7eeb169299fd3 100644 --- a/clang/lib/Basic/Targets/DirectX.h +++ b/clang/lib/Basic/Targets/DirectX.h @@ -50,7 +50,8 @@ static const unsigned DirectXAddrSpaceMap[] = { 0, // hlsl_push_constant // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. - 20, // wasm_funcref + 0, // wasm_funcref + 0, // wasm_var }; class LLVM_LIBRARY_VISIBILITY DirectXTargetInfo : public TargetInfo { diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h index 69ee20f38343b..ecce7f05dcd6c 100644 --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -54,7 +54,8 @@ static const unsigned NVPTXAddrSpaceMap[] = { 0, // hlsl_push_constant // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. - 20, // wasm_funcref + 0, // wasm_funcref + 0, // wasm_var }; /// The DWARF address class. Taken from diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 389cc075a3a0b..798389dba4b33 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -58,7 +58,8 @@ static const unsigned SPIRDefIsPrivMap[] = { 13, // hlsl_push_constant // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. - 20, // wasm_funcref + 0, // wasm_funcref + 0, // wasm_var }; // Used by both the SPIR and SPIR-V targets. @@ -96,7 +97,8 @@ static const unsigned SPIRDefIsGenMap[] = { 13, // hlsl_push_constant // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. - 20, // wasm_funcref + 0, // wasm_funcref + 0, // wasm_var }; // Base class for SPIR and SPIR-V target info. @@ -213,7 +215,10 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo { } void setAddressSpaceMap(bool DefaultIsGeneric) { - AddrSpaceMap = DefaultIsGeneric ? &SPIRDefIsGenMap : &SPIRDefIsPrivMap; + if (DefaultIsGeneric) + AddrSpaceMap = &SPIRDefIsGenMap; + else + AddrSpaceMap = &SPIRDefIsPrivMap; } void adjust(DiagnosticsEngine &Diags, LangOptions &Opts, diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index 00f7d7a055b24..40376f6e50f5d 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -48,7 +48,8 @@ static const unsigned ZOSAddressMap[] = { 0, // hlsl_input 0, // hlsl_output 0, // hlsl_push_constant - 0 // wasm_funcref + 0, // wasm_funcref + 0 // wasm_var }; class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h index 1360298de9794..c7d25a3d696fd 100644 --- a/clang/lib/Basic/Targets/TCE.h +++ b/clang/lib/Basic/Targets/TCE.h @@ -59,7 +59,8 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = { 0, // hlsl_push_constant // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. - 20, // wasm_funcref + 0, // wasm_funcref + 0, // wasm_var }; class LLVM_LIBRARY_VISIBILITY TCETargetInfo : public TargetInfo { diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h index 6085197498163..f407c32ee27f2 100644 --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -49,6 +49,7 @@ static const unsigned WebAssemblyAddrSpaceMap[] = { 0, // hlsl_output 0, // hlsl_push_constant 20, // wasm_funcref + 1, // wasm_var }; class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo { diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index c8c5d280754b4..4dbc631742099 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -54,7 +54,8 @@ static const unsigned X86AddrSpaceMap[] = { 0, // hlsl_push_constant // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. - 20, // wasm_funcref + 0, // wasm_funcref + 0, // wasm_var }; // X86 target abstract base class; x86-32 and x86-64 are very close, so diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 7608f8cb6fc7a..917a53b47736f 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1482,9 +1482,11 @@ static bool shouldExtendLifetime(const ASTContext &Context, CodeGenFunction::AutoVarEmission CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { QualType Ty = D.getType(); - assert( - Ty.getAddressSpace() == LangAS::Default || - (Ty.getAddressSpace() == LangAS::opencl_private && getLangOpts().OpenCL)); + assert(Ty.getAddressSpace() == LangAS::Default || + (Ty.getAddressSpace() == LangAS::opencl_private && + getLangOpts().OpenCL) || + (Ty.getAddressSpace() == LangAS::wasm_var && + getTarget().getTriple().isWasm())); AutoVarEmission emission(D); @@ -2684,8 +2686,6 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, Arg.getAnyValue()->setName(D.getName()); QualType Ty = D.getType(); - assert((getLangOpts().OpenCL || Ty.getAddressSpace() == LangAS::Default) && - "parameter has non-default address space in non-OpenCL mode"); // Use better IR generation for certain implicit parameters. if (auto IPD = dyn_cast<ImplicitParamDecl>(&D)) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cddcf3a010279..d354465f4185a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -29,6 +29,7 @@ #include "clang/AST/Randstruct.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/DiagnosticComment.h" #include "clang/Basic/HLSLRuntime.h" @@ -7108,6 +7109,11 @@ void Sema::deduceOpenCLAddressSpace(VarDecl *Var) { Var->assignAddressSpace(Context, ImplAS); } +void Sema::deduceWasmAddressSpace(VarDecl *Var) { + if (Context.getTargetInfo().getTriple().isWasm()) + Var->deduceParmAddressSpace(Context); +} + static void checkWeakAttr(Sema &S, NamedDecl &ND) { // 'weak' only applies to declarations with external linkage. if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) { @@ -8226,17 +8232,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } - // WebAssembly tables are always in address space 1 (wasm_var). Don't apply - // address space if the table has local storage (semantic checks elsewhere - // will produce an error anyway). - if (const auto *ATy = dyn_cast<ArrayType>(NewVD->getType())) { - if (ATy && ATy->getElementType().isWebAssemblyReferenceType() && - !NewVD->hasLocalStorage()) { - QualType Type = Context.getAddrSpaceQualType( - NewVD->getType(), Context.getLangASForBuiltinAddressSpace(1)); - NewVD->setType(Type); - } - } + deduceWasmAddressSpace(NewVD); LoadExternalExtnameUndeclaredIdentifiers(); @@ -8926,12 +8922,45 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { NewVD->setType(T); } + // WebAssembly tables must be static with a zero length and can't be + // declared within functions. + if (T->isWebAssemblyTableType()) { + if (getCurScope()->getParent()) { // Parent is null at top-level + Diag(NewVD->getLocation(), diag::err_wasm_table_in_function); + NewVD->setInvalidDecl(); + return; + } + if (NewVD->getStorageClass() != SC_Static) { + Diag(NewVD->getLocation(), diag::err_wasm_table_must_be_static); + NewVD->setInvalidDecl(); + return; + } + const auto *ATy = dyn_cast<ConstantArrayType>(T.getTypePtr()); + if (!ATy || ATy->getZExtSize() != 0) { + Diag(NewVD->getLocation(), + diag::err_typecheck_wasm_table_must_have_zero_length); + NewVD->setInvalidDecl(); + return; + } + } + // Emit an error if an address space was applied to decl with local storage. // This includes arrays of objects with address space qualifiers, but not // automatic variables that point to other address spaces. // ISO/IEC TR 18037 S5.1.2 - if (!getLangOpts().OpenCL && NewVD->hasLocalStorage() && - T.getAddressSpace() != LangAS::Default) { + if (T.isWebAssemblyReferenceType() && + Context.getTargetInfo().getTriple().isWasm() && !T->isArrayType()) { + // WebAssembly: reference types must be in + // wasm_var address space (AS 1) so they can be stored in WebAssembly + // locals. Arrays of reference types (WebAssembly tables) are handled + // separately below. + if (T.getAddressSpace() != LangAS::wasm_var) { + Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1; + NewVD->setInvalidDecl(); + return; + } + } else if (!getLangOpts().OpenCL && NewVD->hasLocalStorage() && + T.getAddressSpace() != LangAS::Default) { Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 0; NewVD->setInvalidDecl(); return; @@ -9059,28 +9088,6 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { } } - // WebAssembly tables must be static with a zero length and can't be - // declared within functions. - if (T->isWebAssemblyTableType()) { - if (getCurScope()->getParent()) { // Parent is null at top-level - Diag(NewVD->getLocation(), diag::err_wasm_table_in_function); - NewVD->setInvalidDecl(); - return; - } - if (NewVD->getStorageClass() != SC_Static) { - Diag(NewVD->getLocation(), diag::err_wasm_table_must_be_static); - NewVD->setInvalidDecl(); - return; - } - const auto *ATy = dyn_cast<ConstantArrayType>(T.getTypePtr()); - if (!ATy || ATy->getZExtSize() != 0) { - Diag(NewVD->getLocation(), - diag::err_typecheck_wasm_table_must_have_zero_length); - NewVD->setInvalidDecl(); - return; - } - } - // zero sized static arrays are not allowed in HIP device functions if (getLangOpts().HIP && LangOpts.CUDAIsDevice) { if (FunctionDecl *FD = getCurFunctionDecl(); @@ -13476,6 +13483,8 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, if (getLangOpts().HLSL) HLSL().deduceAddressSpace(VDecl); + deduceWasmAddressSpace(VDecl); + // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. if (VarDecl *Old = VDecl->getPreviousDecl()) { @@ -15955,10 +15964,9 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, // to be qualified with an address space. !(getLangOpts().OpenCL && (T->isArrayType() || T.getAddressSpace() == LangAS::opencl_private)) && - // WebAssembly allows reference types as parameters. Funcref in particular - // lives in a different address space. - !(T->isFunctionPointerType() && - T.getAddressSpace() == LangAS::wasm_funcref) && + // WebAssembly reference types like __externref_t must be in wasm_var. + !(T.isWebAssemblyReferenceType() && + T.getAddressSpace() == LangAS::wasm_var) && // HLSL allows function arguments to be qualified with an address space // if the groupshared annotation is used. !(getLangOpts().HLSL && diff --git a/clang/test/CodeGen/WebAssembly/reference-type-alloca.c b/clang/test/CodeGen/WebAssembly/reference-type-alloca.c new file mode 100644 index 0000000000000..79fa7a19e26c4 --- /dev/null +++ b/clang/test/CodeGen/WebAssembly/reference-type-alloca.c @@ -0,0 +1,35 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 +// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +reference-types -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: define ptr addrspace(10) @test_externref( +// CHECK-SAME: ptr addrspace(10) [[INPUT:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[INPUT_ADDR:%.*]] = alloca ptr addrspace(10), align 1, addrspace(1) +// CHECK-NEXT: [[LOCAL:%.*]] = alloca ptr addrspace(10), align 1, addrspace(1) +// CHECK-NEXT: store ptr addrspace(10) [[INPUT]], ptr addrspace(1) [[INPUT_ADDR]], align 1 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(10), ptr addrspace(1) [[INPUT_ADDR]], align 1 +// CHECK-NEXT: store ptr addrspace(10) [[TMP0]], ptr addrspace(1) [[LOCAL]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(10), ptr addrspace(1) [[LOCAL]], align 1 +// CHECK-NEXT: ret ptr addrspace(10) [[TMP1]] +// +__externref_t test_externref(__externref_t input) { + __externref_t local = input; + return local; +} + +typedef void (*__funcref funcref_t)(); +// CHECK-LABEL: define ptr addrspace(20) @test_funcref( +// CHECK-SAME: ptr addrspace(20) noundef [[INPUT:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[INPUT_ADDR:%.*]] = alloca ptr addrspace(20), align 4, addrspace(1) +// CHECK-NEXT: [[LOCAL:%.*]] = alloca ptr addrspace(20), align 4, addrspace(1) +// CHECK-NEXT: store ptr addrspace(20) [[INPUT]], ptr addrspace(1) [[INPUT_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr addrspace(1) [[INPUT_ADDR]], align 4 +// CHECK-NEXT: store ptr addrspace(20) [[TMP0]], ptr addrspace(1) [[LOCAL]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(20), ptr addrspace(1) [[LOCAL]], align 4 +// CHECK-NEXT: ret ptr addrspace(20) [[TMP1]] +// +funcref_t test_funcref(funcref_t input) { + funcref_t local = input; + return local; +} diff --git a/clang/test/CodeGen/WebAssembly/wasm-externref.c b/clang/test/CodeGen/WebAssembly/wasm-externref.c index 788438bb4a86a..c3f337b2b22b4 100644 --- a/clang/test/CodeGen/WebAssembly/wasm-externref.c +++ b/clang/test/CodeGen/WebAssembly/wasm-externref.c @@ -7,9 +7,9 @@ void helper(externref_t); // CHECK-LABEL: @handle( // CHECK-NEXT: entry: -// CHECK-NEXT: [[OBJ_ADDR:%.*]] = alloca ptr addrspace(10), align 1 -// CHECK-NEXT: store ptr addrspace(10) [[OBJ:%.*]], ptr [[OBJ_ADDR]], align 1 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(10), ptr [[OBJ_ADDR]], align 1 +// CHECK-NEXT: [[OBJ_ADDR:%.*]] = alloca ptr addrspace(10), align 1, addrspace(1) +// CHECK-NEXT: store ptr addrspace(10) [[OBJ:%.*]], ptr addrspace(1) [[OBJ_ADDR]], align 1 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(10), ptr addrspace(1) [[OBJ_ADDR]], align 1 // CHECK-NEXT: call void @helper(ptr addrspace(10) [[TMP0]]) // CHECK-NEXT: ret void // diff --git a/clang/test/CodeGen/WebAssembly/wasm-funcref.c b/clang/test/CodeGen/WebAssembly/wasm-funcref.c index f01af0db321dd..c1006893e3d4f 100644 --- a/clang/test/CodeGen/WebAssembly/wasm-funcref.c +++ b/clang/test/CodeGen/WebAssembly/wasm-funcref.c @@ -29,9 +29,9 @@ fn_funcref_t get_null_ii() { // Identity function for funcref. // CHECK-LABEL: @identity( // CHECK-NEXT: entry: -// CHECK-NEXT: [[FN_ADDR:%.*]] = alloca ptr addrspace(20), align 4 -// CHECK-NEXT: store ptr addrspace(20) [[FN:%.*]], ptr [[FN_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr [[FN_ADDR]], align 4 +// CHECK-NEXT: [[FN_ADDR:%.*]] = alloca ptr addrspace(20), align 4, addrspace(1) +// CHECK-NEXT: store ptr addrspace(20) [[FN:%.*]], ptr addrspace(1) [[FN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr addrspace(1) [[FN_ADDR]], align 4 // CHECK-NEXT: ret ptr addrspace(20) [[TMP0]] // funcref_t identity(funcref_t fn) { @@ -43,9 +43,9 @@ void helper(funcref_t); // Pass funcref ref as an argument to a helper function. // CHECK-LABEL: @handle( // CHECK-NEXT: entry: -// CHECK-NEXT: [[FN_ADDR:%.*]] = alloca ptr addrspace(20), align 4 -// CHECK-NEXT: store ptr addrspace(20) [[FN:%.*]], ptr [[FN_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr [[FN_ADDR]], align 4 +// CHECK-NEXT: [[FN_ADDR:%.*]] = alloca ptr addrspace(20), align 4, addrspace(1) +// CHECK-NEXT: store ptr addrspace(20) [[FN:%.*]], ptr addrspace(1) [[FN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr addrspace(1) [[FN_ADDR]], align 4 // CHECK-NEXT: call void @helper(ptr addrspace(20) noundef [[TMP0]]) // CHECK-NEXT: ret i32 0 // @@ -70,11 +70,11 @@ fn_funcref_t get_ref(fn_t fnptr) { // Call funcref // CHECK-LABEL: @call_fn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[REF_ADDR:%.*]] = alloca ptr addrspace(20), align 4 +// CHECK-NEXT: [[REF_ADDR:%.*]] = alloca ptr addrspace(20), align 4, addrspace(1) // CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store ptr addrspace(20) [[REF:%.*]], ptr [[REF_ADDR]], align 4 +// CHECK-NEXT: store ptr addrspace(20) [[REF:%.*]], ptr addrspace(1) [[REF_ADDR]], align 4 // CHECK-NEXT: store i32 [[X:%.*]], ptr [[X_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr [[REF_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr addrspace(1) [[REF_ADDR]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[X_ADDR]], align 4 // CHECK-NEXT: [[CALL:%.*]] = call addrspace(20) i32 [[TMP0]](i32 noundef [[TMP1]]) // CHECK-NEXT: ret i32 [[CALL]] diff --git a/clang/test/CodeGenCXX/wasm-reftypes-mangle.cpp b/clang/test/CodeGenCXX/wasm-reftypes-mangle.cpp index 20e33cfdaa31c..e736732ac87a9 100644 --- a/clang/test/CodeGenCXX/wasm-reftypes-mangle.cpp +++ b/clang/test/CodeGenCXX/wasm-reftypes-mangle.cpp @@ -7,10 +7,10 @@ typedef void (*__funcref funcref_t)(); // Global funcref variables - test that codegen doesn't crash. -// CHECK-DAG: @fptr = global ptr addrspace(20) null +// CHECK-DAG: @fptr = addrspace(1) global ptr addrspace(20) null funcref_t fptr; -// CHECK-DAG: @fpt2 = global ptr addrspace(20) null +// CHECK-DAG: @fpt2 = addrspace(1) global ptr addrspace(20) null void (*__funcref fpt2)(); // CHECK-DAG: _Z2f1u11externref_t diff --git a/clang/test/Sema/wasm-refs-and-tables.c b/clang/test/Sema/wasm-refs-and-tables.c index dd8536c52cd03..35a7aeea4b79e 100644 --- a/clang/test/Sema/wasm-refs-and-tables.c +++ b/clang/test/Sema/wasm-refs-and-tables.c @@ -63,7 +63,7 @@ __externref_t func(__externref_t ref) { int foo = 40; (__externref_t *)(&foo); // expected-error {{pointer to WebAssembly reference type is not allowed}} (__externref_t ****)(&foo); // expected-error {{pointer to WebAssembly reference type is not allowed}} - sizeof(ref); // expected-error {{invalid application of 'sizeof' to sizeless type '__externref_t'}} + sizeof(ref); // expected-error {{invalid application of 'sizeof' to sizeless type '__externref __externref_t'}} sizeof(__externref_t); // expected-error {{invalid application of 'sizeof' to sizeless type '__externref_t'}} sizeof(__externref_t[0]); // expected-error {{invalid application of 'sizeof' to WebAssembly table}} sizeof(table); // expected-error {{invalid application of 'sizeof' to WebAssembly table}} @@ -71,7 +71,7 @@ __externref_t func(__externref_t ref) { sizeof(__externref_t *); // expected-error {{pointer to WebAssembly reference type is not allowed}} sizeof(__externref_t ***); // expected-error {{pointer to WebAssembly reference type is not allowed}}; // expected-warning@+1 {{'_Alignof' applied to an expression is a GNU extension}} - _Alignof(ref); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} + _Alignof(ref); // expected-error {{invalid application of 'alignof' to sizeless type '__externref __externref_t'}} _Alignof(__externref_t); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} _Alignof(__externref_t[]); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} _Alignof(__externref_t[0]); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} @@ -89,13 +89,13 @@ __externref_t func(__externref_t ref) { // cpp-error@+1 {{no matching function for call to 'illegal_argument_1'}} illegal_argument_1(table); varargs(1, table); // expected-error {{cannot use WebAssembly table as a function parameter}} - table == 1; // expected-error {{invalid operands to binary expression ('__attribute__((address_space(1))) __externref_t[0]' and 'int')}} - 1 >= table; // expected-error {{invalid operands to binary expression ('int' and '__attribute__((address_space(1))) __externref_t[0]')}} - table == other_table; // expected-error {{invalid operands to binary expression ('__attribute__((address_space(1))) __externref_t[0]' and '__attribute__((address_space(1))) __externref_t[0]')}} - table !=- table; // expected-error {{invalid argument type '__attribute__((address_space(1))) __externref_t *' to unary expression}} - !table; // expected-error {{invalid argument type '__attribute__((address_space(1))) __externref_t *' to unary expression}} - 1 && table; // expected-error {{invalid operands to binary expression ('int' and '__attribute__((address_space(1))) __externref_t[0]')}} - table || 1; // expected-error {{invalid operands to binary expression ('__attribute__((address_space(1))) __externref_t[0]' and 'int')}} + table == 1; // expected-error {{invalid operands to binary expression ('__externref __externref_t[0]' and 'int')}} + 1 >= table; // expected-error {{invalid operands to binary expression ('int' and '__externref __externref_t[0]')}} + table == other_table; // expected-error {{invalid operands to binary expression ('__externref __externref_t[0]' and '__externref __externref_t[0]')}} + table !=- table; // expected-error {{invalid argument type '__externref __externref_t *' to unary expression}} + !table; // expected-error {{invalid argument type '__externref __externref_t *' to unary expression}} + 1 && table; // expected-error {{invalid operands to binary expression ('int' and '__externref __externref_t[0]')}} + table || 1; // expected-error {{invalid operands to binary expression ('__externref __externref_t[0]' and 'int')}} 1 ? table : table; // expected-error {{cannot use a WebAssembly table within a branch of a conditional expression}} table ? : other_table; // expected-error {{cannot use a WebAssembly table within a branch of a conditional expression}} (void *)table; // expected-error {{cannot cast from a WebAssembly table}} diff --git a/clang/test/SemaTemplate/address_space-dependent.cpp b/clang/test/SemaTemplate/address_space-dependent.cpp index 3fdccb2c71a76..d6f25923b69b5 100644 --- a/clang/test/SemaTemplate/address_space-dependent.cpp +++ b/clang/test/SemaTemplate/address_space-dependent.cpp @@ -43,7 +43,7 @@ void neg() { template <long int I> void tooBig() { - __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388580)}} + __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388579)}} } template <long int I> @@ -101,7 +101,7 @@ int main() { car<1, 2, 3>(); // expected-note {{in instantiation of function template specialization 'car<1, 2, 3>' requested here}} HasASTemplateFields<1> HASTF; neg<-1>(); // expected-note {{in instantiation of function template specialization 'neg<-1>' requested here}} - correct<0x7FFFE4>(); + correct<0x7FFFE3>(); tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650L>' requested here}} __attribute__((address_space(1))) char *x; >From da1badccc4f901b2fa2c00c2ae8b1c7fabc11174 Mon Sep 17 00:00:00 2001 From: Jameson Nash <[email protected]> Date: Wed, 3 Jun 2026 17:13:57 +0000 Subject: [PATCH 3/4] review --- clang/lib/AST/TypePrinter.cpp | 2 +- clang/lib/Basic/TargetInfo.cpp | 2 +- clang/lib/Basic/Targets/AArch64.h | 2 +- clang/lib/Basic/Targets/DirectX.h | 2 +- clang/lib/Basic/Targets/NVPTX.h | 2 +- clang/lib/Basic/Targets/SPIR.h | 4 ++-- clang/lib/Basic/Targets/TCE.h | 2 +- clang/lib/Basic/Targets/X86.h | 2 +- clang/lib/CodeGen/CGExpr.cpp | 5 +++-- clang/lib/CodeGen/CodeGenFunction.h | 4 ++-- clang/test/Sema/wasm-refs-and-tables.c | 18 +++++++++--------- 11 files changed, 23 insertions(+), 22 deletions(-) diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 4c51754a2282f..e7e5ece85ab02 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2721,7 +2721,7 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) { case LangAS::wasm_funcref: return "__funcref"; case LangAS::wasm_var: - return "__externref"; + return "__wasm_var"; default: return std::to_string(toTargetAddressSpace(AS)); } diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 41ea62152aafb..a1690b15c7367 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -55,7 +55,7 @@ static const LangASMap FakeAddrSpaceMap = { 18, // hlsl_output 19, // hlsl_push_constant 20, // wasm_funcref - 21, // wasm_externref + 21, // wasm_var }; // TargetInfo Constructor. diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index 5bbda7313cc1c..6ed82e76f25cc 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -54,7 +54,7 @@ static const unsigned ARM64AddrSpaceMap[] = { // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 0, // wasm_funcref - 0, // wasm_var + 0, // wasm_var }; using AArch64FeatureSet = llvm::SmallDenseSet<StringRef, 32>; diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h index 7eeb169299fd3..bfac11e7da675 100644 --- a/clang/lib/Basic/Targets/DirectX.h +++ b/clang/lib/Basic/Targets/DirectX.h @@ -51,7 +51,7 @@ static const unsigned DirectXAddrSpaceMap[] = { // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 0, // wasm_funcref - 0, // wasm_var + 0, // wasm_var }; class LLVM_LIBRARY_VISIBILITY DirectXTargetInfo : public TargetInfo { diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h index ecce7f05dcd6c..5e1322a1119cd 100644 --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -55,7 +55,7 @@ static const unsigned NVPTXAddrSpaceMap[] = { // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 0, // wasm_funcref - 0, // wasm_var + 0, // wasm_var }; /// The DWARF address class. Taken from diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 798389dba4b33..28b8905e5844c 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -59,7 +59,7 @@ static const unsigned SPIRDefIsPrivMap[] = { // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 0, // wasm_funcref - 0, // wasm_var + 0, // wasm_var }; // Used by both the SPIR and SPIR-V targets. @@ -98,7 +98,7 @@ static const unsigned SPIRDefIsGenMap[] = { // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 0, // wasm_funcref - 0, // wasm_var + 0, // wasm_var }; // Base class for SPIR and SPIR-V target info. diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h index c7d25a3d696fd..37637fa0f92e7 100644 --- a/clang/lib/Basic/Targets/TCE.h +++ b/clang/lib/Basic/Targets/TCE.h @@ -60,7 +60,7 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = { // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 0, // wasm_funcref - 0, // wasm_var + 0, // wasm_var }; class LLVM_LIBRARY_VISIBILITY TCETargetInfo : public TargetInfo { diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 4dbc631742099..f211113ab3bc8 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -55,7 +55,7 @@ static const unsigned X86AddrSpaceMap[] = { // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 0, // wasm_funcref - 0, // wasm_var + 0, // wasm_var }; // X86 target abstract base class; x86-32 and x86-64 are very close, so diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 036e897c368dc..582be4f8b991a 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -104,8 +104,9 @@ static llvm::StringRef GetUBSanTrapForHandler(SanitizerHandler ID) { /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. -RawAddress -CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, LangAS UseAddrSpace, CharUnits Align, const Twine &Name, llvm::Value *ArraySize) { +RawAddress CodeGenFunction::CreateTempAllocaWithoutCast( + llvm::Type *Ty, LangAS UseAddrSpace, CharUnits Align, const Twine &Name, + llvm::Value *ArraySize) { if (getLangOpts().EmitLogicalPointer) { auto Alloca = Builder.CreateStructuredAlloca(Ty, Name); return RawAddress(Alloca, Ty, Align, KnownNonNull); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 3eb458154272d..71bcb4512e112 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -5654,8 +5654,8 @@ DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { auto align = CharUnits::fromQuantity( CGF.CGM.getDataLayout().getPrefTypeAlign(value->getType())) .getAsAlign(); - llvm::AllocaInst *AI = - CGF.CreateTempAlloca(value->getType(), LangAS::Default, "cond-cleanup.save"); + llvm::AllocaInst *AI = CGF.CreateTempAlloca(value->getType(), LangAS::Default, + "cond-cleanup.save"); AI->setAlignment(align); CGF.Builder.CreateAlignedStore(value, AI, align); diff --git a/clang/test/Sema/wasm-refs-and-tables.c b/clang/test/Sema/wasm-refs-and-tables.c index 35a7aeea4b79e..f078208e35f5a 100644 --- a/clang/test/Sema/wasm-refs-and-tables.c +++ b/clang/test/Sema/wasm-refs-and-tables.c @@ -63,7 +63,7 @@ __externref_t func(__externref_t ref) { int foo = 40; (__externref_t *)(&foo); // expected-error {{pointer to WebAssembly reference type is not allowed}} (__externref_t ****)(&foo); // expected-error {{pointer to WebAssembly reference type is not allowed}} - sizeof(ref); // expected-error {{invalid application of 'sizeof' to sizeless type '__externref __externref_t'}} + sizeof(ref); // expected-error {{invalid application of 'sizeof' to sizeless type '__wasm_var __externref_t'}} sizeof(__externref_t); // expected-error {{invalid application of 'sizeof' to sizeless type '__externref_t'}} sizeof(__externref_t[0]); // expected-error {{invalid application of 'sizeof' to WebAssembly table}} sizeof(table); // expected-error {{invalid application of 'sizeof' to WebAssembly table}} @@ -71,7 +71,7 @@ __externref_t func(__externref_t ref) { sizeof(__externref_t *); // expected-error {{pointer to WebAssembly reference type is not allowed}} sizeof(__externref_t ***); // expected-error {{pointer to WebAssembly reference type is not allowed}}; // expected-warning@+1 {{'_Alignof' applied to an expression is a GNU extension}} - _Alignof(ref); // expected-error {{invalid application of 'alignof' to sizeless type '__externref __externref_t'}} + _Alignof(ref); // expected-error {{invalid application of 'alignof' to sizeless type '__wasm_var __externref_t'}} _Alignof(__externref_t); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} _Alignof(__externref_t[]); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} _Alignof(__externref_t[0]); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} @@ -89,13 +89,13 @@ __externref_t func(__externref_t ref) { // cpp-error@+1 {{no matching function for call to 'illegal_argument_1'}} illegal_argument_1(table); varargs(1, table); // expected-error {{cannot use WebAssembly table as a function parameter}} - table == 1; // expected-error {{invalid operands to binary expression ('__externref __externref_t[0]' and 'int')}} - 1 >= table; // expected-error {{invalid operands to binary expression ('int' and '__externref __externref_t[0]')}} - table == other_table; // expected-error {{invalid operands to binary expression ('__externref __externref_t[0]' and '__externref __externref_t[0]')}} - table !=- table; // expected-error {{invalid argument type '__externref __externref_t *' to unary expression}} - !table; // expected-error {{invalid argument type '__externref __externref_t *' to unary expression}} - 1 && table; // expected-error {{invalid operands to binary expression ('int' and '__externref __externref_t[0]')}} - table || 1; // expected-error {{invalid operands to binary expression ('__externref __externref_t[0]' and 'int')}} + table == 1; // expected-error {{invalid operands to binary expression ('__wasm_var __externref_t[0]' and 'int')}} + 1 >= table; // expected-error {{invalid operands to binary expression ('int' and '__wasm_var __externref_t[0]')}} + table == other_table; // expected-error {{invalid operands to binary expression ('__wasm_var __externref_t[0]' and '__wasm_var __externref_t[0]')}} + table !=- table; // expected-error {{invalid argument type '__wasm_var __externref_t *' to unary expression}} + !table; // expected-error {{invalid argument type '__wasm_var __externref_t *' to unary expression}} + 1 && table; // expected-error {{invalid operands to binary expression ('int' and '__wasm_var __externref_t[0]')}} + table || 1; // expected-error {{invalid operands to binary expression ('__wasm_var __externref_t[0]' and 'int')}} 1 ? table : table; // expected-error {{cannot use a WebAssembly table within a branch of a conditional expression}} table ? : other_table; // expected-error {{cannot use a WebAssembly table within a branch of a conditional expression}} (void *)table; // expected-error {{cannot cast from a WebAssembly table}} >From efa2a4d7fdc77ec7c8e0fc11421a5285d638f173 Mon Sep 17 00:00:00 2001 From: Jameson Nash <[email protected]> Date: Mon, 8 Jun 2026 15:20:05 +0000 Subject: [PATCH 4/4] HLSL: explicitly annotate constant-to-local copy as expecting a different address space output --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 33d76cbda494a..04b1d151f9d9a 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -1542,13 +1542,15 @@ RawAddress CGHLSLRuntime::createBufferMatrixTempAddress(const LValue &LV, QualType MatQualTy = LV.getType(); llvm::Type *LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(MatQualTy); + llvm::Type *DestTy = CGF.ConvertTypeForMem(MatQualTy); Address SrcAddr = LV.getAddress(); - if (LayoutTy == CGF.ConvertTypeForMem(MatQualTy)) + if (LayoutTy == DestTy) return SrcAddr; - RawAddress DestAlloca = - CGF.CreateMemTempWithoutCast(MatQualTy, "matrix.buf.copy"); + RawAddress DestAlloca = CGF.CreateTempAllocaWithoutCast( + DestTy, LangAS::Default, CGF.getContext().getTypeAlignInChars(MatQualTy), + "matrix.buf.copy"); emitBufferCopy(CGF, DestAlloca, SrcAddr, MatQualTy); return DestAlloca; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
