2019-01-15 10:53:22 -08:00
|
|
|
//===- LLVMDialect.cpp - LLVM IR Ops and Dialect registration -------------===//
|
|
|
|
//
|
|
|
|
// Copyright 2019 The MLIR Authors.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
// =============================================================================
|
|
|
|
//
|
|
|
|
// This file defines the types and operation details for the LLVM IR dialect in
|
|
|
|
// MLIR, and the LLVM IR dialect. It also registers the dialect.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir/LLVMIR/LLVMDialect.h"
|
|
|
|
#include "mlir/IR/MLIRContext.h"
|
2019-03-06 09:34:53 -08:00
|
|
|
#include "llvm/IR/Function.h"
|
2019-01-15 10:53:22 -08:00
|
|
|
|
|
|
|
#include "llvm/AsmParser/Parser.h"
|
2019-03-06 09:34:53 -08:00
|
|
|
#include "llvm/IR/Attributes.h"
|
2019-01-15 10:53:22 -08:00
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/Support/SourceMgr.h"
|
|
|
|
|
|
|
|
using namespace mlir;
|
|
|
|
using namespace mlir::LLVM;
|
|
|
|
|
|
|
|
namespace mlir {
|
|
|
|
namespace LLVM {
|
|
|
|
namespace detail {
|
2019-03-24 21:41:36 -07:00
|
|
|
struct LLVMTypeStorage : public ::mlir::TypeStorage {
|
2019-01-15 12:54:01 -08:00
|
|
|
LLVMTypeStorage(llvm::Type *ty) : underlyingType(ty) {}
|
|
|
|
|
2019-01-15 10:53:22 -08:00
|
|
|
// LLVM types are pointer-unique.
|
|
|
|
using KeyTy = llvm::Type *;
|
2019-01-15 12:54:01 -08:00
|
|
|
bool operator==(const KeyTy &key) const { return key == underlyingType; }
|
2019-01-15 10:53:22 -08:00
|
|
|
|
|
|
|
static LLVMTypeStorage *construct(TypeStorageAllocator &allocator,
|
2019-01-15 12:54:01 -08:00
|
|
|
llvm::Type *ty) {
|
|
|
|
return new (allocator.allocate<LLVMTypeStorage>()) LLVMTypeStorage(ty);
|
2019-01-15 10:53:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Type *underlyingType;
|
|
|
|
};
|
|
|
|
} // end namespace detail
|
|
|
|
} // end namespace LLVM
|
|
|
|
} // end namespace mlir
|
|
|
|
|
|
|
|
LLVMType LLVMType::get(MLIRContext *context, llvm::Type *llvmType) {
|
|
|
|
return Base::get(context, FIRST_LLVM_TYPE, llvmType);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Type *LLVMType::getUnderlyingType() const {
|
2019-03-24 23:51:05 -07:00
|
|
|
return getImpl()->underlyingType;
|
2019-01-15 10:53:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*---- LLVM IR Dialect and its registration ----------------------------- */
|
|
|
|
|
|
|
|
LLVMDialect::LLVMDialect(MLIRContext *context)
|
|
|
|
: Dialect("llvm", context), module("LLVMDialectModule", llvmContext) {
|
|
|
|
addTypes<LLVMType>();
|
|
|
|
addOperations<
|
2019-03-20 17:25:34 -07:00
|
|
|
#define GET_OP_LIST
|
|
|
|
#include "mlir/LLVMIR/LLVMOps.cpp.inc"
|
2019-01-15 10:53:22 -08:00
|
|
|
>();
|
2019-03-31 23:30:22 -07:00
|
|
|
|
|
|
|
// Support unknown operations because not all LLVM operations are registered.
|
|
|
|
allowUnknownOperations();
|
2019-02-25 13:16:24 -08:00
|
|
|
}
|
|
|
|
|
2019-03-20 17:25:34 -07:00
|
|
|
#define GET_OP_CLASSES
|
|
|
|
#include "mlir/LLVMIR/LLVMOps.cpp.inc"
|
|
|
|
|
2019-02-25 13:16:24 -08:00
|
|
|
/// Parse a type registered to this dialect.
|
2019-03-29 14:06:51 -07:00
|
|
|
Type LLVMDialect::parseType(StringRef tyData, Location loc) const {
|
2019-02-25 13:16:24 -08:00
|
|
|
llvm::SMDiagnostic errorMessage;
|
|
|
|
llvm::Type *type = llvm::parseType(tyData, errorMessage, module);
|
|
|
|
if (!type)
|
2019-03-29 14:06:51 -07:00
|
|
|
return (getContext()->emitError(loc, errorMessage.getMessage()), nullptr);
|
|
|
|
return LLVMType::get(getContext(), type);
|
2019-02-25 13:16:24 -08:00
|
|
|
}
|
2019-01-15 10:53:22 -08:00
|
|
|
|
2019-02-25 13:16:24 -08:00
|
|
|
/// Print a type registered to this dialect.
|
|
|
|
void LLVMDialect::printType(Type type, raw_ostream &os) const {
|
|
|
|
auto llvmType = type.dyn_cast<LLVMType>();
|
|
|
|
assert(llvmType && "printing wrong type");
|
|
|
|
assert(llvmType.getUnderlyingType() && "no underlying LLVM type");
|
|
|
|
llvmType.getUnderlyingType()->print(os);
|
2019-01-15 10:53:22 -08:00
|
|
|
}
|
|
|
|
|
2019-03-06 09:34:53 -08:00
|
|
|
/// Verify LLVMIR function argument attributes.
|
2019-03-21 11:39:22 -07:00
|
|
|
bool LLVMDialect::verifyFunctionArgAttribute(Function *func, unsigned argIdx,
|
2019-03-06 09:34:53 -08:00
|
|
|
NamedAttribute argAttr) {
|
|
|
|
// Check that llvm.noalias is a boolean attribute.
|
2019-03-06 11:05:43 -08:00
|
|
|
if (argAttr.first == "llvm.noalias" && !argAttr.second.isa<BoolAttr>())
|
|
|
|
return func->emitError(
|
|
|
|
"llvm.noalias argument attribute of non boolean type");
|
2019-03-06 09:34:53 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-01-15 10:53:22 -08:00
|
|
|
static DialectRegistration<LLVMDialect> llvmDialect;
|