20#include "llvm/Support/Casting.h"
31 if (keyword ==
"else")
33 return ParseResult::success();
38 if (elseRegion.
empty())
46#include "mlir/Dialect/WasmSSA/IR/WasmSSAOps.cpp.inc"
50#include "llvm/Support/LogicalResult.h"
60 auto opType = dyn_cast<LocalRefType>(operands.front().
getType());
63 inferredReturnTypes.push_back(opType.getElementType());
68 std::string importName;
71 result.addAttribute(
"importName", StringAttr::get(ctx, importName));
75 if (failed(res) || fromStr !=
"from")
78 std::string moduleName;
82 result.addAttribute(
"moduleName", StringAttr::get(ctx, moduleName));
86 if (failed(res) || asStr !=
"as")
89 StringAttr symbolName;
92 result.getOrAddProperties<GlobalImportOp::Properties>().sym_name =
102Block *BlockOp::getLabelTarget() {
return getTarget(); }
108std::size_t BlockReturnOp::getExitLevel() {
return 0; }
110Block *BlockReturnOp::getTarget() {
111 return cast<LabelBranchingOpInterface>(getOperation())
121LogicalResult ExtendLowBitsSOp::verify() {
122 auto bitsToTake = getBitsToTake().getValue().getLimitedValue();
123 if (bitsToTake != 32 && bitsToTake != 16 && bitsToTake != 8)
124 return emitError(
"extend op can only take 8, 16 or 32 bits. Got ")
127 if (bitsToTake >= getInput().
getType().getIntOrFloatBitWidth())
128 return emitError(
"trying to extend the ")
129 << bitsToTake <<
" low bits from a " << getInput().getType()
130 <<
" value is illegal";
138Block *FuncOp::addEntryBlock() {
139 if (!getBody().empty()) {
140 emitError(
"adding entry block to a FuncOp which already has one");
141 return &getBody().front();
143 Block &block = getBody().emplaceBlock();
144 for (
auto argType : getFunctionType().getInputs())
145 block.
addArgument(LocalRefType::get(argType), getLoc());
150 StringRef symbol, FunctionType funcType) {
151 FuncOp::build(odsBuilder, odsState, symbol, funcType, {}, {});
156 std::string visibilityString;
159 bool exported{
false};
160 if (res.succeeded()) {
161 if (visibilityString !=
"exported")
163 loc,
"expecting either `exported` or symbol name. got ")
173 argTypesWithoutLocal.reserve(argTypes.size());
174 llvm::for_each(argTypes, [&parser, &argTypesWithoutLocal](
Type argType) {
175 auto refType = dyn_cast<LocalRefType>(argType);
179 "!wasm<local T>, got ")
183 argTypesWithoutLocal.push_back(refType.getElementType());
190 getFunctionTypeAttrName(
result.name), buildFuncType,
191 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
193 result.addAttribute(getExportedAttrName(
result.name), UnitAttr::get(ctx));
197LogicalResult FuncOp::verifyBody() {
198 if (getBody().empty())
202 return emitError(
"entry block should have same number of arguments as "
203 "function type. Function type has ")
204 << getFunctionType().getNumInputs() <<
", entry block has "
207 for (
auto [argNo, funcSignatureType, blockType] : llvm::enumerate(
209 auto blockLocalRefType = dyn_cast<LocalRefType>(blockType);
210 if (!blockLocalRefType)
211 return emitError(
"entry block argument type should be LocalRefType, got ")
212 << blockType <<
" for block argument " << argNo;
213 if (blockLocalRefType.getElementType() != funcSignatureType)
215 << argNo <<
"(" << funcSignatureType
216 <<
") doesn't match entry block referenced type ("
217 << blockLocalRefType.getElementType() <<
")";
225 auto exported = getExported();
228 removeExportedAttr();
231 p, *
this,
false, getFunctionTypeAttrName(),
232 getArgAttrsAttrName(), getResAttrsAttrName());
242 StringRef symbol, StringRef moduleName,
243 StringRef importName, FunctionType type) {
244 FuncImportOp::build(odsBuilder, odsState, symbol, moduleName, importName,
252Operation *getGlobalOpTerminatorOp(GlobalOp gop) {
253 return gop.getInitializer().begin()->getTerminator();
257ReturnOp GlobalOp::getInitTerminator() {
258 return llvm::cast<wasmssa::ReturnOp>(getGlobalOpTerminatorOp(*
this));
263 StringAttr symbolName;
266 std::string visibilityString;
269 if (res.succeeded()) {
270 if (visibilityString !=
"exported")
272 loc,
"expecting either `exported` or symbol name. got ")
274 result.addAttribute(getExportedAttrName(
result.name), UnitAttr::get(ctx));
280 result.addAttribute(getTypeAttrName(
result.name), TypeAttr::get(globalType));
281 std::string mutableString;
283 if (res.succeeded() && mutableString ==
"mutable")
284 result.addAttribute(
"isMutable", UnitAttr::get(ctx));
294 printer <<
" exported";
295 printer <<
" @" << getSymName().str() <<
" " <<
getType();
297 printer <<
" mutable";
299 Region &body = getRegion();
307LogicalResult GlobalOp::verify() {
308 return success(llvm::isa<ReturnOp>(getGlobalOpTerminatorOp(*
this)));
319 if (!this->getOperation()
320 ->getParentWithTrait<ConstantExpressionInitializerOpTrait>())
323 StringRef referencedSymbol = getGlobal();
325 symTabOp, StringAttr::get(this->
getContext(), referencedSymbol));
327 return emitError() <<
"symbol @" << referencedSymbol <<
" is undefined";
328 auto definitionImport = dyn_cast<GlobalImportOp>(definitionOp);
329 if (!definitionImport || definitionImport.getIsMutable()) {
330 return emitError(
"global.get op is considered constant if it's referring "
331 "to a import.global symbol marked non-mutable");
343 StringRef referencedSymbol = getGlobal();
345 symTabOp, StringAttr::get(this->
getContext(), referencedSymbol));
347 return emitError() <<
"symbol @" << referencedSymbol <<
" is undefined";
350 bool isMutable =
false;
351 if (
auto global = dyn_cast<GlobalOp>(definitionOp)) {
352 globalType = global.getType();
353 isMutable = global.getIsMutable();
354 }
else if (
auto globalImport = dyn_cast<GlobalImportOp>(definitionOp)) {
355 globalType = globalImport.getType();
356 isMutable = globalImport.getIsMutable();
358 return emitError() <<
"symbol @" << referencedSymbol
359 <<
" is not a global symbol";
363 return emitError(
"global.set target must be mutable");
365 Type valueType = getValue().getType();
366 if (globalType != valueType)
367 return emitError(
"global.set value type does not match target global "
369 << globalType <<
" but got " << valueType;
380 ParseResult res = parseImportOp(parser,
result);
383 std::string mutableOrSymVisString;
385 if (res.succeeded() && mutableOrSymVisString ==
"mutable") {
386 result.addAttribute(
"isMutable", UnitAttr::get(ctx));
395 TypeAttr::get(importedType));
400 printer <<
" \"" << getImportName() <<
"\" from \"" << getModuleName()
401 <<
"\" as @" << getSymName();
403 printer <<
" mutable";
411Block *IfOp::getLabelTarget() {
return getTarget(); }
417LogicalResult LocalOp::inferReturnTypes(
418 MLIRContext *context, ::std::optional<Location> location,
421 LocalOp::GenericAdaptor<ValueRange> adaptor{operands, attributes, properties,
423 auto type = adaptor.getTypeAttr();
426 auto resType = LocalRefType::get(type.getContext(), type.getValue());
427 inferredReturnTypes.push_back(resType);
435LogicalResult LocalGetOp::inferReturnTypes(
436 MLIRContext *context, ::std::optional<Location> location,
439 return inferTeeGetResType(operands, inferredReturnTypes);
446LogicalResult LocalSetOp::verify() {
448 return emitError(
"input type and result type of local.set do not match");
456LogicalResult LocalTeeOp::inferReturnTypes(
457 MLIRContext *context, ::std::optional<Location> location,
460 return inferTeeGetResType(operands, inferredReturnTypes);
463LogicalResult LocalTeeOp::verify() {
466 return emitError(
"input type and output type of local.tee do not match");
474Block *LoopOp::getLabelTarget() {
return &getBody().
front(); }
480LogicalResult ReinterpretOp::verify() {
481 auto inT = getInput().getType();
482 auto resT = getResult().getType();
484 return emitError(
"reinterpret input and output type should be distinct");
485 if (inT.getIntOrFloatBitWidth() != resT.getIntOrFloatBitWidth())
486 return emitError() <<
"input type (" << inT <<
") and output type (" << resT
487 <<
") have incompatible bit widths";
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
virtual ParseResult parseOptionalKeywordOrString(std::string *result)=0
Parse an optional keyword or string.
MLIRContext * getContext() const
virtual Location getEncodedSourceLoc(SMLoc loc)=0
Re-encode the given source location as an MLIR location and return it.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
ParseResult parseKeywordOrString(std::string *result)
Parse a keyword or a quoted string.
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual void printKeywordOrString(StringRef keyword)
Print the given string as a keyword, or a quoted and escaped string if it has any special or non-prin...
Block represents an ordered list of Operations.
ValueTypeRange< BlockArgListType > getArgumentTypes()
Return a range containing the types of the arguments for this block.
unsigned getNumArguments()
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Block * getSuccessor(unsigned i)
This class is a general helper class for creating context-global objects like types,...
FunctionType getFunctionType(TypeRange inputs, TypeRange results)
MLIRContext is the top-level object for a collection of MLIR operations.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
Type-safe wrapper around a void* for passing properties, including the properties structs of operatio...
This class provides an abstraction over the different types of ranges over Regions.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This class represents a collection of SymbolTables.
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
static Operation * getNearestSymbolTable(Operation *from)
Returns the nearest symbol table from a given operation from.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
type_range getType() const
A named class for passing around the variadic flag.
void printFunctionOp(OpAsmPrinter &p, FunctionOpInterface op, bool isVariadic, StringRef typeAttrName, StringAttr argAttrsName, StringAttr resAttrsName)
Printer implementation for function-like operations.
ParseResult parseFunctionOp(OpAsmParser &parser, OperationState &result, bool allowVariadic, StringAttr typeAttrName, FuncTypeBuilder funcTypeBuilder, StringAttr argAttrsName, StringAttr resAttrsName)
Parser implementation for function-like operations.
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
This represents an operation in an abstracted form, suitable for use with the builder APIs.