Skip to content

Commit 90523f4

Browse files
Merge branch 'main' into rename-do-something-fixture
2 parents f86c5f2 + 5372c6b commit 90523f4

File tree

4 files changed

+86
-98
lines changed

4 files changed

+86
-98
lines changed

python/runtime/cudaq/platform/py_alt_launch_kernel.cpp

Lines changed: 6 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "common/ArgumentConversion.h"
1313
#include "common/ArgumentWrapper.h"
1414
#include "common/Environment.h"
15+
#include "common/LayoutInfo.h"
1516
#include "cudaq/Optimizer/Builder/Marshal.h"
1617
#include "cudaq/Optimizer/Builder/Runtime.h"
1718
#include "cudaq/Optimizer/CAPI/Dialects.h"
@@ -169,31 +170,6 @@ py::args cudaq::simplifiedValidateInputArguments(py::args &args) {
169170
return processed;
170171
}
171172

172-
std::pair<std::size_t, std::vector<std::size_t>>
173-
cudaq::getTargetLayout(mlir::ModuleOp mod, cudaq::cc::StructType structTy) {
174-
mlir::StringRef dataLayoutSpec = "";
175-
if (auto attr = mod->getAttr(cudaq::opt::factory::targetDataLayoutAttrName))
176-
dataLayoutSpec = mlir::cast<mlir::StringAttr>(attr);
177-
else
178-
throw std::runtime_error("No data layout attribute is set on the module.");
179-
180-
auto dataLayout = llvm::DataLayout(dataLayoutSpec);
181-
// Convert bufferTy to llvm.
182-
llvm::LLVMContext context;
183-
mlir::LLVMTypeConverter converter(structTy.getContext());
184-
cudaq::opt::initializeTypeConversions(converter);
185-
auto llvmDialectTy = converter.convertType(structTy);
186-
mlir::LLVM::TypeToLLVMIRTranslator translator(context);
187-
auto *llvmStructTy =
188-
mlir::cast<llvm::StructType>(translator.translateType(llvmDialectTy));
189-
auto *layout = dataLayout.getStructLayout(llvmStructTy);
190-
auto strSize = layout->getSizeInBytes();
191-
std::vector<std::size_t> fieldOffsets;
192-
for (std::size_t i = 0, I = structTy.getMembers().size(); i != I; ++i)
193-
fieldOffsets.emplace_back(layout->getElementOffset(i));
194-
return {strSize, fieldOffsets};
195-
}
196-
197173
void cudaq::handleStructMemberVariable(void *data, std::size_t offset,
198174
mlir::Type memberType,
199175
py::object value) {
@@ -626,75 +602,11 @@ cudaq::OpaqueArguments *cudaq::toOpaqueArgs(py::args &args, MlirModule mod,
626602
static void appendTheResultValue(ModuleOp module, const std::string &name,
627603
cudaq::OpaqueArguments &runtimeArgs,
628604
Type returnType) {
629-
TypeSwitch<Type, void>(returnType)
630-
.Case([&](IntegerType type) {
631-
if (type.getIntOrFloatBitWidth() == 1) {
632-
bool *ourAllocatedArg = new bool();
633-
*ourAllocatedArg = 0;
634-
runtimeArgs.emplace_back(ourAllocatedArg, [](void *ptr) {
635-
delete static_cast<bool *>(ptr);
636-
});
637-
return;
638-
}
639-
640-
long *ourAllocatedArg = new long();
641-
*ourAllocatedArg = 0;
642-
runtimeArgs.emplace_back(ourAllocatedArg, [](void *ptr) {
643-
delete static_cast<long *>(ptr);
644-
});
645-
})
646-
.Case([&](ComplexType type) {
647-
Py_complex *ourAllocatedArg = new Py_complex();
648-
ourAllocatedArg->real = 0.0;
649-
ourAllocatedArg->imag = 0.0;
650-
runtimeArgs.emplace_back(ourAllocatedArg, [](void *ptr) {
651-
delete static_cast<Py_complex *>(ptr);
652-
});
653-
})
654-
.Case([&](Float64Type type) {
655-
double *ourAllocatedArg = new double();
656-
*ourAllocatedArg = 0.;
657-
runtimeArgs.emplace_back(ourAllocatedArg, [](void *ptr) {
658-
delete static_cast<double *>(ptr);
659-
});
660-
})
661-
.Case([&](Float32Type type) {
662-
float *ourAllocatedArg = new float();
663-
*ourAllocatedArg = 0.;
664-
runtimeArgs.emplace_back(ourAllocatedArg, [](void *ptr) {
665-
delete static_cast<float *>(ptr);
666-
});
667-
})
668-
.Case([&](cudaq::cc::StdvecType ty) {
669-
// Vector is a span: `{ data, length }`.
670-
struct vec {
671-
char *data;
672-
std::size_t length;
673-
};
674-
vec *ourAllocatedArg = new vec{nullptr, 0};
675-
runtimeArgs.emplace_back(
676-
ourAllocatedArg, [](void *ptr) { delete static_cast<vec *>(ptr); });
677-
})
678-
.Case([&](cudaq::cc::StructType ty) {
679-
auto [size, offsets] = cudaq::getTargetLayout(module, ty);
680-
auto ourAllocatedArg = std::malloc(size);
681-
runtimeArgs.emplace_back(ourAllocatedArg,
682-
[](void *ptr) { std::free(ptr); });
683-
})
684-
.Case([&](cudaq::cc::CallableType ty) {
685-
// Callables may not be returned from entry-point kernels. Append a
686-
// dummy value as a placeholder.
687-
runtimeArgs.emplace_back(nullptr, [](void *) {});
688-
})
689-
.Default([](Type ty) {
690-
std::string msg;
691-
{
692-
llvm::raw_string_ostream os(msg);
693-
ty.print(os);
694-
}
695-
throw std::runtime_error("Unsupported CUDA-Q kernel return type - " +
696-
msg + ".\n");
697-
});
605+
auto [bufferSize, offsets] = cudaq::getResultBufferLayout(module, returnType);
606+
if (bufferSize == 0)
607+
return;
608+
auto *buf = std::calloc(1, bufferSize);
609+
runtimeArgs.emplace_back(buf, [](void *ptr) { std::free(ptr); });
698610
}
699611

700612
// Launching the module \p mod will modify its content, such as by argument

python/utils/OpaqueArguments.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,6 @@ void valueArgument(OpaqueArguments &argData, T *arg) {
111111

112112
std::string mlirTypeToString(mlir::Type ty);
113113

114-
/// @brief Return the size and member variable offsets for the input struct.
115-
std::pair<std::size_t, std::vector<std::size_t>>
116-
getTargetLayout(mlir::ModuleOp mod, cudaq::cc::StructType structTy);
117-
118114
/// For the current struct member variable type, insert the value into the
119115
/// dynamically constructed struct.
120116
void handleStructMemberVariable(void *data, std::size_t offset,

runtime/common/LayoutInfo.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "cudaq/Optimizer/Builder/Runtime.h"
1313
#include "cudaq/Optimizer/CodeGen/QIROpaqueStructTypes.h"
1414
#include "cudaq/runtime/logger/logger.h"
15+
#include "llvm/ADT/TypeSwitch.h"
1516
#include "llvm/IR/DataLayout.h"
1617
#include "mlir/IR/BuiltinOps.h"
1718
#include "mlir/IR/Types.h"
@@ -100,4 +101,65 @@ LayoutInfoType getLayoutInfo(const std::string &name, void *opt_module) {
100101
return extractLayout(name, quakeCode);
101102
return {};
102103
}
104+
105+
LayoutInfoType getTargetLayout(ModuleOp mod, cc::StructType structTy) {
106+
StringRef dataLayoutSpec = "";
107+
if (auto attr = mod->getAttr(opt::factory::targetDataLayoutAttrName))
108+
dataLayoutSpec = cast<StringAttr>(attr);
109+
else
110+
throw std::runtime_error("No data layout attribute is set on the module.");
111+
112+
auto dataLayout = llvm::DataLayout(dataLayoutSpec);
113+
llvm::LLVMContext context;
114+
LLVMTypeConverter converter(structTy.getContext());
115+
opt::initializeTypeConversions(converter);
116+
auto llvmDialectTy = converter.convertType(structTy);
117+
LLVM::TypeToLLVMIRTranslator translator(context);
118+
auto *llvmStructTy =
119+
cast<llvm::StructType>(translator.translateType(llvmDialectTy));
120+
auto *layout = dataLayout.getStructLayout(llvmStructTy);
121+
auto strSize = layout->getSizeInBytes();
122+
std::vector<std::size_t> fieldOffsets;
123+
for (std::size_t i = 0, I = structTy.getMembers().size(); i != I; ++i)
124+
fieldOffsets.emplace_back(layout->getElementOffset(i));
125+
return {strSize, fieldOffsets};
126+
}
127+
128+
LayoutInfoType getResultBufferLayout(ModuleOp mod, Type resultTy) {
129+
std::size_t bufferSize = 0;
130+
std::vector<std::size_t> fieldOffsets;
131+
132+
TypeSwitch<Type, void>(resultTy)
133+
.Case([&](IntegerType ty) {
134+
bufferSize =
135+
ty.getIntOrFloatBitWidth() == 1 ? sizeof(bool) : sizeof(long);
136+
})
137+
.Case([&](ComplexType) { bufferSize = 2 * sizeof(double); })
138+
.Case([&](Float64Type) { bufferSize = sizeof(double); })
139+
.Case([&](Float32Type) { bufferSize = sizeof(float); })
140+
.Case([&](cc::StdvecType) {
141+
struct vec {
142+
void *data;
143+
std::size_t length;
144+
};
145+
bufferSize = sizeof(vec);
146+
})
147+
.Case([&](cc::StructType ty) {
148+
auto [size, offsets] = getTargetLayout(mod, ty);
149+
bufferSize = size;
150+
fieldOffsets = std::move(offsets);
151+
})
152+
.Case([&](cc::CallableType) {})
153+
.Default([](Type ty) {
154+
std::string msg;
155+
{
156+
llvm::raw_string_ostream os(msg);
157+
ty.print(os);
158+
}
159+
throw std::runtime_error("Unsupported CUDA-Q kernel return type - " +
160+
msg + ".\n");
161+
});
162+
163+
return {bufferSize, std::move(fieldOffsets)};
164+
}
103165
} // namespace cudaq

runtime/common/LayoutInfo.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,28 @@
1010
#include <string>
1111
#include <vector>
1212

13+
namespace mlir {
14+
class ModuleOp;
15+
class Type;
16+
} // namespace mlir
17+
1318
namespace cudaq {
19+
namespace cc {
20+
class StructType;
21+
} // namespace cc
1422

1523
using LayoutInfoType = std::pair<std::size_t, std::vector<std::size_t>>;
1624

1725
LayoutInfoType getLayoutInfo(const std::string &name,
1826
void *opt_module = nullptr);
27+
28+
/// @brief Compute struct size and field offsets using the module's data layout.
29+
LayoutInfoType getTargetLayout(mlir::ModuleOp mod, cc::StructType structTy);
30+
31+
/// @brief Compute the host-side buffer size (and struct field offsets, if
32+
/// applicable) for the given MLIR kernel return type. Returns {0, {}} for
33+
/// types that do not require a result buffer (e.g. `CallableType`). Throws on
34+
/// unsupported types.
35+
LayoutInfoType getResultBufferLayout(mlir::ModuleOp mod, mlir::Type resultTy);
36+
1937
} // namespace cudaq

0 commit comments

Comments
 (0)