summaryrefslogtreecommitdiffstats
path: root/mlir/lib
diff options
context:
space:
mode:
authorAlex Zinenko <zinenko@google.com>2019-08-09 08:59:45 -0700
committerA. Unique TensorFlower <gardener@tensorflow.org>2019-08-09 09:00:13 -0700
commit68451df267eda7961fca930ab29c6d38f43b97e2 (patch)
tree6ccdf1a904bfcd43a44e6cd94be08ac273af362e /mlir/lib
parentb9ff2dd87edef4a750f2caccbd4923500f3d8405 (diff)
downloadbcm5719-llvm-68451df267eda7961fca930ab29c6d38f43b97e2.tar.gz
bcm5719-llvm-68451df267eda7961fca930ab29c6d38f43b97e2.zip
LLVM dialect and translation: support global strings
Unlike regular constant values, strings must be placed in some memory and referred to through a pointer to that memory. Until now, they were not supported in function-local constant declarations with `llvm.constant`. Introduce support for global strings using `llvm.global`, which would translate them into global arrays in LLVM IR and thus make sure they have some memory allocated for storage. PiperOrigin-RevId: 262569316
Diffstat (limited to 'mlir/lib')
-rw-r--r--mlir/lib/LLVMIR/IR/LLVMDialect.cpp43
-rw-r--r--mlir/lib/Target/LLVMIR/ModuleTranslation.cpp11
2 files changed, 50 insertions, 4 deletions
diff --git a/mlir/lib/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/LLVMIR/IR/LLVMDialect.cpp
index c50a14ffff9..378907eff0b 100644
--- a/mlir/lib/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/LLVMIR/IR/LLVMDialect.cpp
@@ -840,29 +840,52 @@ static void printGlobalOp(OpAsmPrinter *p, GlobalOp op) {
*p << ')';
p->printOptionalAttrDict(op.getAttrs(), {SymbolTable::getSymbolAttrName(),
"type", "constant", "value"});
+
+ // Print the trailing type unless it's a string global.
+ if (op.value().isa<StringAttr>())
+ return;
*p << " : ";
p->printType(op.type());
}
// <operation> ::= `llvm.global` `constant`? `@` identifier `(` attribute `)`
-// attribute-list? : type
+// attribute-list? (`:` type)?
+//
+// The type can be omitted for string attributes, in which case it will be
+// inferred from the value of the string as [strlen(value) x i8].
static ParseResult parseGlobalOp(OpAsmParser *parser, OperationState *result) {
if (succeeded(parser->parseOptionalKeyword("constant")))
result->addAttribute("constant", parser->getBuilder().getUnitAttr());
Attribute value;
StringAttr name;
- Type type;
+ SmallVector<Type, 1> types;
if (parser->parseSymbolName(name, SymbolTable::getSymbolAttrName(),
result->attributes) ||
parser->parseLParen() ||
parser->parseAttribute(value, "value", result->attributes) ||
parser->parseRParen() ||
parser->parseOptionalAttributeDict(result->attributes) ||
- parser->parseColonType(type))
+ parser->parseOptionalColonTypeList(types))
return failure();
- result->addAttribute("type", parser->getBuilder().getTypeAttr(type));
+ if (types.size() > 1)
+ return parser->emitError(parser->getNameLoc(), "expected zero or one type");
+
+ if (types.empty()) {
+ if (auto strAttr = value.dyn_cast<StringAttr>()) {
+ MLIRContext *context = parser->getBuilder().getContext();
+ auto *dialect = context->getRegisteredDialect<LLVMDialect>();
+ auto arrayType = LLVM::LLVMType::getArrayTy(
+ LLVM::LLVMType::getInt8Ty(dialect), strAttr.getValue().size());
+ types.push_back(arrayType);
+ } else {
+ return parser->emitError(parser->getNameLoc(),
+ "type can only be omitted for string globals");
+ }
+ }
+
+ result->addAttribute("type", parser->getBuilder().getTypeAttr(types[0]));
return success();
}
@@ -872,6 +895,15 @@ static LogicalResult verify(GlobalOp op) {
"expects type to be a valid element type for an LLVM pointer");
if (op.getParentOp() && !isa<ModuleOp>(op.getParentOp()))
return op.emitOpError("must appear at the module level");
+ if (auto strAttr = op.value().dyn_cast<StringAttr>()) {
+ auto type = op.getType();
+ if (!type.getUnderlyingType()->isArrayTy() ||
+ !type.getArrayElementType().getUnderlyingType()->isIntegerTy(8) ||
+ type.getArrayNumElements() != strAttr.getValue().size())
+ return op.emitOpError(
+ "requires an i8 array type of the length equal to that of the string "
+ "attribute");
+ }
return success();
}
@@ -1200,6 +1232,9 @@ llvm::Type *LLVMType::getUnderlyingType() const {
LLVMType LLVMType::getArrayElementType() {
return get(getContext(), getUnderlyingType()->getArrayElementType());
}
+unsigned LLVMType::getArrayNumElements() {
+ return getUnderlyingType()->getArrayNumElements();
+}
/// Vector type utilities.
LLVMType LLVMType::getVectorElementType() {
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index bf43848c9ef..3cbf543bdfc 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -292,6 +292,17 @@ bool ModuleTranslation::convertBlock(Block &bb, bool ignoreArguments) {
// Create named global variables that correspond to llvm.global definitions.
void ModuleTranslation::convertGlobals() {
for (auto op : mlirModule.getOps<LLVM::GlobalOp>()) {
+ // String attributes are treated separately because they cannot appear as
+ // in-function constants and are thus not supported by getLLVMConstant.
+ if (auto strAttr = op.value().dyn_cast<StringAttr>()) {
+ llvm::Constant *cst = llvm::ConstantDataArray::getString(
+ llvmModule->getContext(), strAttr.getValue(), /*AddNull=*/false);
+ new llvm::GlobalVariable(*llvmModule, cst->getType(), op.constant(),
+ llvm::GlobalValue::InternalLinkage, cst,
+ op.sym_name());
+ return;
+ }
+
llvm::Type *type = op.getType().getUnderlyingType();
new llvm::GlobalVariable(
*llvmModule, type, op.constant(), llvm::GlobalValue::InternalLinkage,
OpenPOWER on IntegriCloud