Skip to content

Commit 8f72155

Browse files
committed
[mlir][emitc] Fix creating pointer from constant array
When creating a pointer from a constant emitc array, check if it is constant. If it is, create the pointer as opaque<"const {type}">>. Move out C type string creation logic from TranslateToCpp.cpp to getCTypeString in EmitC.cpp as a shared utility function.
1 parent c793782 commit 8f72155

File tree

5 files changed

+93
-39
lines changed

5 files changed

+93
-39
lines changed

mlir/include/mlir/Dialect/EmitC/IR/EmitC.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "mlir/Dialect/EmitC/IR/EmitCDialect.h.inc"
2828
#include "mlir/Dialect/EmitC/IR/EmitCEnums.h.inc"
2929

30+
#include <string>
3031
#include <variant>
3132

3233
namespace mlir {
@@ -49,6 +50,10 @@ bool isSupportedFloatType(mlir::Type type);
4950
/// Determines whether \p type is a emitc.size_t/ssize_t type.
5051
bool isPointerWideType(mlir::Type type);
5152

53+
/// Convert an MLIR type to its C type string representation.
54+
/// Returns an empty string if the type cannot be represented as a C type.
55+
std::string getCTypeString(Type type);
56+
5257
// Either a literal string, or an placeholder for the fmtArgs.
5358
struct Placeholder {};
5459
using ReplacementItem = std::variant<StringRef, Placeholder>;

mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "mlir/IR/BuiltinTypes.h"
2020
#include "mlir/IR/Diagnostics.h"
2121
#include "mlir/IR/PatternMatch.h"
22+
#include "mlir/IR/SymbolTable.h"
2223
#include "mlir/IR/TypeRange.h"
2324
#include "mlir/IR/Value.h"
2425
#include "mlir/Transforms/DialectConversion.h"
@@ -134,8 +135,26 @@ createPointerFromEmitcArray(Location loc, OpBuilder &builder,
134135
llvm::SmallVector<mlir::Value> indices(arrayType.getRank(), zeroIndex);
135136
emitc::SubscriptOp subPtr =
136137
emitc::SubscriptOp::create(builder, loc, arrayValue, ValueRange(indices));
138+
139+
// Determine the pointer type
140+
Type pointerElementType = arrayType.getElementType();
141+
142+
// Check if the array comes from a const global
143+
if (auto getGlobalOp = arrayValue.getDefiningOp<emitc::GetGlobalOp>()) {
144+
auto globalOp = SymbolTable::lookupNearestSymbolFrom<emitc::GlobalOp>(
145+
getGlobalOp, getGlobalOp.getNameAttr());
146+
if (globalOp && globalOp.getConstSpecifier()) {
147+
// Create a const pointer type using opaque type
148+
std::string cTypeString = emitc::getCTypeString(pointerElementType);
149+
if (!cTypeString.empty()) {
150+
pointerElementType = emitc::OpaqueType::get(builder.getContext(),
151+
"const " + cTypeString);
152+
}
153+
}
154+
}
155+
137156
emitc::ApplyOp ptr = emitc::ApplyOp::create(
138-
builder, loc, emitc::PointerType::get(arrayType.getElementType()),
157+
builder, loc, emitc::PointerType::get(pointerElementType),
139158
builder.getStringAttr("&"), subPtr);
140159

141160
return ptr;

mlir/lib/Dialect/EmitC/IR/EmitC.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,43 @@ bool mlir::emitc::isFundamentalType(Type type) {
139139
isa<emitc::PointerType>(type);
140140
}
141141

142+
std::string mlir::emitc::getCTypeString(Type type) {
143+
if (auto intType = dyn_cast<IntegerType>(type)) {
144+
switch (intType.getWidth()) {
145+
case 1:
146+
return "bool";
147+
case 8:
148+
return intType.isUnsigned() ? "uint8_t" : "int8_t";
149+
case 16:
150+
return intType.isUnsigned() ? "uint16_t" : "int16_t";
151+
case 32:
152+
return intType.isUnsigned() ? "uint32_t" : "int32_t";
153+
case 64:
154+
return intType.isUnsigned() ? "uint64_t" : "int64_t";
155+
default:
156+
return "";
157+
}
158+
}
159+
if (auto floatType = dyn_cast<FloatType>(type)) {
160+
if (floatType.getWidth() == 16) {
161+
if (isa<Float16Type>(type))
162+
return "_Float16";
163+
if (isa<BFloat16Type>(type))
164+
return "__bf16";
165+
return "";
166+
}
167+
if (floatType.getWidth() == 32)
168+
return "float";
169+
if (floatType.getWidth() == 64)
170+
return "double";
171+
return "";
172+
}
173+
if (auto opaqueType = dyn_cast<emitc::OpaqueType>(type))
174+
return opaqueType.getValue().str();
175+
176+
return "";
177+
}
178+
142179
/// Check that the type of the initial value is compatible with the operations
143180
/// result type.
144181
static LogicalResult verifyInitializationAttribute(Operation *op,

mlir/lib/Target/Cpp/TranslateToCpp.cpp

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,40 +1792,15 @@ LogicalResult CppEmitter::emitVariableDeclaration(Location loc, Type type,
17921792
}
17931793

17941794
LogicalResult CppEmitter::emitType(Location loc, Type type) {
1795-
if (auto iType = dyn_cast<IntegerType>(type)) {
1796-
switch (iType.getWidth()) {
1797-
case 1:
1798-
return (os << "bool"), success();
1799-
case 8:
1800-
case 16:
1801-
case 32:
1802-
case 64:
1803-
if (shouldMapToUnsigned(iType.getSignedness()))
1804-
return (os << "uint" << iType.getWidth() << "_t"), success();
1805-
else
1806-
return (os << "int" << iType.getWidth() << "_t"), success();
1807-
default:
1808-
return emitError(loc, "cannot emit integer type ") << type;
1809-
}
1810-
}
1811-
if (auto fType = dyn_cast<FloatType>(type)) {
1812-
switch (fType.getWidth()) {
1813-
case 16: {
1814-
if (llvm::isa<Float16Type>(type))
1815-
return (os << "_Float16"), success();
1816-
if (llvm::isa<BFloat16Type>(type))
1817-
return (os << "__bf16"), success();
1818-
else
1819-
return emitError(loc, "cannot emit float type ") << type;
1820-
}
1821-
case 32:
1822-
return (os << "float"), success();
1823-
case 64:
1824-
return (os << "double"), success();
1825-
default:
1826-
return emitError(loc, "cannot emit float type ") << type;
1827-
}
1828-
}
1795+
std::string cTypeString = emitc::getCTypeString(type);
1796+
if (!cTypeString.empty())
1797+
return (os << cTypeString), success();
1798+
1799+
// Handle integer and float cases that failed above
1800+
if (isa<IntegerType>(type))
1801+
return emitError(loc, "cannot emit integer type ") << type;
1802+
if (isa<FloatType>(type))
1803+
return emitError(loc, "cannot emit float type ") << type;
18291804
if (auto iType = dyn_cast<IndexType>(type))
18301805
return (os << "size_t"), success();
18311806
if (auto sType = dyn_cast<emitc::SizeTType>(type))
@@ -1854,10 +1829,6 @@ LogicalResult CppEmitter::emitType(Location loc, Type type) {
18541829
}
18551830
if (auto tType = dyn_cast<TupleType>(type))
18561831
return emitTupleType(loc, tType.getTypes());
1857-
if (auto oType = dyn_cast<emitc::OpaqueType>(type)) {
1858-
os << oType.getValue();
1859-
return success();
1860-
}
18611832
if (auto aType = dyn_cast<emitc::ArrayType>(type)) {
18621833
if (failed(emitType(loc, aType.getElementType())))
18631834
return failure();

mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,25 @@ module @globals {
5858
return
5959
}
6060
}
61+
62+
// -----
63+
64+
// CHECK-LABEL: const_global_copy
65+
module @const_global_copy {
66+
memref.global "private" constant @const_data : memref<4xi8> = dense<[1, 2, 3, 4]>
67+
// CHECK: emitc.global static const @const_data : !emitc.array<4xi8> = dense<[1, 2, 3, 4]>
68+
69+
func.func @copy_from_const_global() {
70+
// CHECK: get_global @const_data : !emitc.array<4xi8>
71+
%0 = memref.get_global @const_data : memref<4xi8>
72+
// CHECK: "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4xi8>
73+
%1 = memref.alloca() : memref<4xi8>
74+
75+
// Verify that pointer from const global has const qualifier
76+
// CHECK: apply "&"({{.*}}) : (!emitc.lvalue<i8>) -> !emitc.ptr<!emitc.opaque<"const int8_t">>
77+
// CHECK: apply "&"({{.*}}) : (!emitc.lvalue<i8>) -> !emitc.ptr<i8>
78+
// CHECK: call_opaque "memcpy"({{.*}}, {{.*}}, {{.*}}) : (!emitc.ptr<i8>, !emitc.ptr<!emitc.opaque<"const int8_t">>, !emitc.size_t) -> ()
79+
memref.copy %0, %1 : memref<4xi8> to memref<4xi8>
80+
return
81+
}
82+
}

0 commit comments

Comments
 (0)