Index: mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td =================================================================== --- mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td +++ mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td @@ -379,12 +379,34 @@ let arguments = (ins TypeAttr:$type, StrAttr:$sym_name, - OptionalAttr:$initializer + OptionalAttr:$initializer, + OptionalAttr:$location, + OptionalAttr:$binding, + OptionalAttr:$descriptorSet, + OptionalAttr:$builtin ); let results = (outs); let builders = [ + OpBuilder<(ins "TypeAttr":$type, + "StringAttr":$sym_name, + CArg<"FlatSymbolRefAttr", "nullptr">:$initializer), + [{ + $_state.addAttribute("type", type); + $_state.addAttribute(sym_nameAttrName($_state.name), sym_name); + if(initializer) + $_state.addAttribute(initializerAttrName($_state.name), initializer); + }]>, + OpBuilder<(ins "Type":$type, + "StringRef":$sym_name, + CArg<"FlatSymbolRefAttr", "{}">:$initializer), + [{ + $_state.addAttribute("type", TypeAttr::get(type)); + $_state.addAttribute(sym_nameAttrName($_state.name), $_builder.getStringAttr(sym_name)); + if(initializer) + $_state.addAttribute(initializerAttrName($_state.name), initializer); + }]>, OpBuilder<(ins "TypeAttr":$type, "ArrayRef":$namedAttrs), [{ $_state.addAttribute("type", type); Index: mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp =================================================================== --- mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp +++ mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp @@ -736,14 +736,16 @@ if (storageClass != spirv::StorageClass::Input && storageClass != spirv::StorageClass::Private && storageClass != spirv::StorageClass::Output && - storageClass != spirv::StorageClass::StorageBuffer) { + storageClass != spirv::StorageClass::StorageBuffer && + storageClass != spirv::StorageClass::UniformConstant) { return failure(); } // LLVM dialect spec: "If the global value is a constant, storing into it is // not allowed.". This corresponds to SPIR-V 'Input' storage class that is // read-only. - bool isConstant = storageClass == spirv::StorageClass::Input; + bool isConstant = (storageClass == spirv::StorageClass::Input) || + (storageClass == spirv::StorageClass::UniformConstant); // SPIR-V spec: "By default, functions and global variables are private to a // module and cannot be accessed by other modules. However, a module may be // written to export or import functions and global (module scope) @@ -752,9 +754,14 @@ auto linkage = storageClass == spirv::StorageClass::Private ? LLVM::Linkage::Private : LLVM::Linkage::External; - rewriter.replaceOpWithNewOp( + auto newGlobalOp = rewriter.replaceOpWithNewOp( op, dstType, isConstant, linkage, op.sym_name(), Attribute(), /*alignment=*/0); + + // Attach location attribute if applicable + if (op.locationAttr()) + newGlobalOp->setAttr(op.locationAttrName(), op.locationAttr()); + return success(); } }; Index: mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp =================================================================== --- mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp +++ mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp @@ -92,7 +92,12 @@ if (!integerValueAttr) { return failure(); } - value = integerValueAttr.getInt(); + + if (integerValueAttr.getType().isSignlessInteger()) + value = integerValueAttr.getInt(); + else + value = integerValueAttr.getSInt(); + return success(); } @@ -2067,8 +2072,7 @@ void spirv::GlobalVariableOp::build(OpBuilder &builder, OperationState &state, Type type, StringRef name, unsigned descriptorSet, unsigned binding) { - build(builder, state, TypeAttr::get(type), builder.getStringAttr(name), - nullptr); + build(builder, state, TypeAttr::get(type), builder.getStringAttr(name)); state.addAttribute( spirv::SPIRVDialect::getAttributeName(spirv::Decoration::DescriptorSet), builder.getI32IntegerAttr(descriptorSet)); @@ -2080,8 +2084,7 @@ void spirv::GlobalVariableOp::build(OpBuilder &builder, OperationState &state, Type type, StringRef name, spirv::BuiltIn builtin) { - build(builder, state, TypeAttr::get(type), builder.getStringAttr(name), - nullptr); + build(builder, state, TypeAttr::get(type), builder.getStringAttr(name)); state.addAttribute( spirv::SPIRVDialect::getAttributeName(spirv::Decoration::BuiltIn), builder.getStringAttr(spirv::stringifyBuiltIn(builtin))); Index: mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp =================================================================== --- mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp +++ mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp @@ -262,6 +262,7 @@ case spirv::Decoration::NonWritable: case spirv::Decoration::NoPerspective: case spirv::Decoration::Restrict: + case spirv::Decoration::RelaxedPrecision: if (words.size() != 2) { return emitError(unknownLoc, "OpDecoration with ") << decorationName << "needs a single target "; Index: mlir/test/Conversion/SPIRVToLLVM/memory-ops-to-llvm.mlir =================================================================== --- mlir/test/Conversion/SPIRVToLLVM/memory-ops-to-llvm.mlir +++ mlir/test/Conversion/SPIRVToLLVM/memory-ops-to-llvm.mlir @@ -67,6 +67,16 @@ } } +spv.module Logical GLSL450 { + // CHECK: llvm.mlir.global external @bar() {location = 1 : i32} : i32 + // CHECK-LABEL: @foo + spv.GlobalVariable @bar {location = 1 : i32} : !spv.ptr + spv.func @foo() "None" { + %0 = spv.mlir.addressof @bar : !spv.ptr + spv.Return + } +} + //===----------------------------------------------------------------------===// // spv.Load //===----------------------------------------------------------------------===//