blob: e114e87fd809b0836d9cac72a3c7246335ec67dd [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
#pragma once
#include "gandiva/llvm_includes.h"
namespace gandiva::internal {
inline bool HasRetAttr(const llvm::AttributeList& attributes,
llvm::Attribute::AttrKind kind) {
#if LLVM_VERSION_MAJOR >= 14
return attributes.hasRetAttr(kind);
#else
return attributes.hasAttribute(llvm::AttributeList::ReturnIndex, kind);
#endif
}
inline llvm::AttributeList AddRetAttr(llvm::LLVMContext& context,
const llvm::AttributeList& attributes,
llvm::Attribute::AttrKind kind) {
#if LLVM_VERSION_MAJOR >= 14
return attributes.addRetAttribute(context, kind);
#else
return attributes.addAttribute(context, llvm::AttributeList::ReturnIndex, kind);
#endif
}
inline void AddNativeBoolZExtAttrs(llvm::Function& function) {
// Gandiva uses i1 parameters and results in native C++ mappings only for bool.
const auto* function_type = function.getFunctionType();
if (function_type->getReturnType()->isIntegerTy(1)) {
// A native bool result must be zero-extended by the callee before it crosses
// the ABI boundary. This matches Clang's lowering of C++ bool.
function.setAttributes(AddRetAttr(function.getContext(), function.getAttributes(),
llvm::Attribute::ZExt));
}
for (unsigned i = 0; i < function_type->getNumParams(); ++i) {
if (function_type->getParamType(i)->isIntegerTy(1)) {
// The caller must pass a native bool as 0 or 1.
// LLVM 23 can replace `icmp ne (and X, 1), 0` with `trunc X to i1`; i1 only defines
// bit 0, so this ABI attribute is required to normalize the value at the call.
// https://github.com/llvm/llvm-project/pull/178977
function.addParamAttr(i, llvm::Attribute::ZExt);
}
}
}
inline void CopyZExtAttrs(const llvm::Function& function, llvm::CallInst& call) {
// https://llvm.org/docs/LangRef.html#parameter-attributes
// "ABI attributes must be specified both at the function declaration/definition and
// call-site, otherwise the behavior may be undefined. ABI attributes cannot be safely
// dropped."
//
// TODO: Copy other ABI attributes as well. This currently copies only `zeroext`,
// which is required for Gandiva's native bool parameters and results.
if (HasRetAttr(function.getAttributes(), llvm::Attribute::ZExt)) {
call.setAttributes(
AddRetAttr(call.getContext(), call.getAttributes(), llvm::Attribute::ZExt));
}
for (unsigned i = 0; i < function.arg_size(); ++i) {
if (function.hasParamAttribute(i, llvm::Attribute::ZExt)) {
call.addParamAttr(i, llvm::Attribute::ZExt);
}
}
}
} // namespace gandiva::internal