diff options
author | Alex Zinenko <zinenko@google.com> | 2019-08-09 08:59:45 -0700 |
---|---|---|
committer | A. Unique TensorFlower <gardener@tensorflow.org> | 2019-08-09 09:00:13 -0700 |
commit | 68451df267eda7961fca930ab29c6d38f43b97e2 (patch) | |
tree | 6ccdf1a904bfcd43a44e6cd94be08ac273af362e /mlir/lib | |
parent | b9ff2dd87edef4a750f2caccbd4923500f3d8405 (diff) | |
download | bcm5719-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.cpp | 43 | ||||
-rw-r--r-- | mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 11 |
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, |