michaelplatings updated this revision to Diff 188184. michaelplatings added a comment. Herald added subscribers: cfe-commits, jdoerfert, mgorny, dschuff. Herald added projects: clang, LLVM.
Hi @efriedma, sorry for the delayed response. I've added the features you asked for to DataLayout. It is intended that this patch preserves the existing behaviour if no function pointer alignment is specified.* Therefore I hope you'll agree that it isn't necessary for me to provide code to use the new feature on all platforms. I did also look into using a target hook but doing so would require modifying a //lot// of functions to take a TargetTransformInfo argument. Given that we're in agreement that the DataLayout is an appropriate choice, it seemed like the best option. - The exception to this is the case where the Function object doesn't have a parent - no alignment is assumed whereas previously 4-byte alignment was assumed. Hopefully this case is rare enough that code size won't be significantly impacted. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D57335/new/ https://reviews.llvm.org/D57335 Files: clang/lib/Basic/Targets/ARM.cpp clang/test/CodeGen/armv7k-abi.c clang/test/CodeGen/target-data.c llvm/docs/LangRef.rst llvm/include/llvm/IR/ConstantFold.h llvm/include/llvm/IR/DataLayout.h llvm/lib/IR/ConstantFold.cpp llvm/lib/IR/ConstantFold.h llvm/lib/IR/Constants.cpp llvm/lib/IR/DataLayout.cpp llvm/lib/IR/Value.cpp llvm/lib/Target/ARM/ARMTargetMachine.cpp llvm/unittests/IR/CMakeLists.txt llvm/unittests/IR/ConstantFoldTest.cpp llvm/unittests/IR/DataLayoutTest.cpp llvm/unittests/IR/FunctionTest.cpp
Index: llvm/unittests/IR/FunctionTest.cpp =================================================================== --- llvm/unittests/IR/FunctionTest.cpp +++ llvm/unittests/IR/FunctionTest.cpp @@ -129,4 +129,29 @@ EXPECT_TRUE(F->hasSection()); } +TEST(FunctionTest, GetPointerAlignment) { + LLVMContext Context; + Type *VoidType(Type::getVoidTy(Context)); + FunctionType *FuncType(FunctionType::get(VoidType, false)); + Function *Func = Function::Create( + FuncType, GlobalValue::ExternalLinkage); + EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout(""))); + EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8"))); + EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fn8"))); + EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16"))); + EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fn16"))); + EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32"))); + EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32"))); + + Func->setAlignment(4U); + + EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout(""))); + EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8"))); + EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn8"))); + EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16"))); + EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn16"))); + EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32"))); + EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32"))); +} + } // end namespace Index: llvm/unittests/IR/DataLayoutTest.cpp =================================================================== --- /dev/null +++ llvm/unittests/IR/DataLayoutTest.cpp @@ -0,0 +1,47 @@ +//===- ConstantRangeTest.cpp - ConstantRange tests ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/DataLayout.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(DataLayoutTest, FunctionPtrAlign) { + EXPECT_EQ(0U, DataLayout("").getFunctionPtrAlign()); + EXPECT_EQ(1U, DataLayout("Fi8").getFunctionPtrAlign()); + EXPECT_EQ(2U, DataLayout("Fi16").getFunctionPtrAlign()); + EXPECT_EQ(4U, DataLayout("Fi32").getFunctionPtrAlign()); + EXPECT_EQ(8U, DataLayout("Fi64").getFunctionPtrAlign()); + EXPECT_EQ(1U, DataLayout("Fn8").getFunctionPtrAlign()); + EXPECT_EQ(2U, DataLayout("Fn16").getFunctionPtrAlign()); + EXPECT_EQ(4U, DataLayout("Fn32").getFunctionPtrAlign()); + EXPECT_EQ(8U, DataLayout("Fn64").getFunctionPtrAlign()); + EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \ + DataLayout("").getFunctionPtrAlignType()); + EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \ + DataLayout("Fi8").getFunctionPtrAlignType()); + EXPECT_EQ(DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign, \ + DataLayout("Fn8").getFunctionPtrAlignType()); + EXPECT_EQ(DataLayout("Fi8"), DataLayout("Fi8")); + EXPECT_NE(DataLayout("Fi8"), DataLayout("Fi16")); + EXPECT_NE(DataLayout("Fi8"), DataLayout("Fn8")); + + DataLayout a(""), b("Fi8"), c("Fn8"); + EXPECT_NE(a, b); + EXPECT_NE(a, c); + EXPECT_NE(b, c); + + a = b; + EXPECT_EQ(a, b); + a = c; + EXPECT_EQ(a, c); +} + +} // anonymous namespace Index: llvm/unittests/IR/ConstantFoldTest.cpp =================================================================== --- /dev/null +++ llvm/unittests/IR/ConstantFoldTest.cpp @@ -0,0 +1,127 @@ +//===- ConstantRangeTest.cpp - ConstantRange tests ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/ConstantFold.h" +#include "llvm/IR/Constants.h" +#include <llvm/IR/Function.h> +#include "llvm/IR/Instruction.h" +#include <llvm/IR/Module.h> +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +ConstantInt *foldFunctionPtrAndConstant(LLVMContext &Context, Module *TheModule, + uint64_t AndValue, + unsigned FunctionAlign = 0) { + Type *VoidType(Type::getVoidTy(Context)); + FunctionType *FuncType(FunctionType::get(VoidType, false)); + Function *Func(Function::Create( + FuncType, GlobalValue::ExternalLinkage, "", TheModule)); + + if (FunctionAlign) Func->setAlignment(FunctionAlign); + + IntegerType *ConstantIntType(Type::getInt32Ty(Context)); + ConstantInt *TheConstant(ConstantInt::get(ConstantIntType, AndValue)); + + Constant *TheConstantExpr( + ConstantExpr::getPtrToInt(Func, ConstantIntType)); + + return cast_or_null<ConstantInt>(ConstantFoldBinaryInstruction( + Instruction::And, TheConstantExpr, TheConstant)); +} + +TEST(ConstantFoldBinaryInstructionTest, FoldFunctionPtrAlignUnknownAnd2) { + LLVMContext Context; + Module TheModule("TestModule", Context); + ConstantInt *Result = foldFunctionPtrAndConstant(Context, &TheModule, 2); + // When the DataLayout doesn't specify a function pointer alignment we + // assume in this case that it is 4 byte aligned. This is a bug but we can't + // fix it directly because it causes a code size regression on X86. + ASSERT_TRUE(Result && Result->getValue().isNullValue()); +} + +TEST(ConstantFoldBinaryInstructionTest, DontFoldFunctionPtrAlignUnknownAnd4) { + LLVMContext Context; + Module TheModule("TestModule", Context); + ASSERT_EQ(nullptr, foldFunctionPtrAndConstant(Context, &TheModule, 4)); +} + +TEST(ConstantFoldBinaryInstructionTest, FoldFunctionPtrAlign4) { + LLVMContext Context; + Module TheModule("TestModule", Context); + const char* AlignmentStrings[] = { "Fi32", "Fn32" }; + + for (unsigned AndValue = 1; AndValue <= 2; ++AndValue) { + for (const char *AlignmentString : AlignmentStrings) { + TheModule.setDataLayout(AlignmentString); + ConstantInt *Result = foldFunctionPtrAndConstant( + Context, &TheModule, AndValue); + ASSERT_TRUE(Result && Result->getValue().isNullValue()); + } + } +} + +TEST(ConstantFoldBinaryInstructionTest, DontFoldFunctionPtrAlign1) { + LLVMContext Context; + Module TheModule("TestModule", Context); + const char* AlignmentStrings[] = { "Fi8", "Fn8" }; + + for (const char* AlignmentString : AlignmentStrings) { + TheModule.setDataLayout(AlignmentString); + ASSERT_EQ(nullptr, foldFunctionPtrAndConstant(Context, &TheModule, 2)); + } +} + +TEST(ConstantFoldBinaryInstructionTest, \ + FoldFunctionAlign4PtrAlignMultiple) { + LLVMContext Context; + Module TheModule("TestModule", Context); + TheModule.setDataLayout("Fn8"); + ConstantInt *Result = foldFunctionPtrAndConstant(Context, &TheModule, 2, 4); + ASSERT_TRUE(Result && Result->getValue().isNullValue()); +} + +TEST(ConstantFoldBinaryInstructionTest, \ + DontFoldFunctionAlign4PtrAlignIndependent) { + LLVMContext Context; + Module TheModule("TestModule", Context); + TheModule.setDataLayout("Fi8"); + ASSERT_EQ(nullptr, foldFunctionPtrAndConstant(Context, &TheModule, 2, 4)); +} + +TEST(ConstantFoldBinaryInstructionTest, DontFoldFunctionPtrIfNoModule) { + LLVMContext Context; + // Even though the function is explicitly 4 byte aligned, in the absence of a + // DataLayout we can't assume that the function pointer is aligned. + ASSERT_EQ(nullptr, foldFunctionPtrAndConstant(Context, nullptr, 2, 4)); +} + +TEST(ConstantFoldBinaryInstructionTest, FoldGlobalVariablePtr) { + LLVMContext Context; + + + IntegerType *IntType(Type::getInt32Ty(Context)); + + GlobalVariable Global(IntType, true, GlobalValue::ExternalLinkage); + + Global.setAlignment(4); + + ConstantInt *TheConstant(ConstantInt::get(IntType, 2)); + + Constant *TheConstantExpr( + ConstantExpr::getPtrToInt(&Global, IntType)); + + ConstantInt *Result = cast_or_null<ConstantInt>(ConstantFoldBinaryInstruction( + Instruction::And, TheConstantExpr, TheConstant)); + + ASSERT_TRUE(Result && Result->getValue().isNullValue()); +} + +} // anonymous namespace Index: llvm/unittests/IR/CMakeLists.txt =================================================================== --- llvm/unittests/IR/CMakeLists.txt +++ llvm/unittests/IR/CMakeLists.txt @@ -12,7 +12,9 @@ BasicBlockTest.cpp CFGBuilder.cpp ConstantRangeTest.cpp + ConstantFoldTest.cpp ConstantsTest.cpp + DataLayoutTest.cpp DebugInfoTest.cpp DebugTypeODRUniquingTest.cpp DominatorTreeTest.cpp Index: llvm/lib/Target/ARM/ARMTargetMachine.cpp =================================================================== --- llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -141,6 +141,10 @@ // Pointers are 32 bits and aligned to 32 bits. Ret += "-p:32:32"; + // Function pointers are aligned to 8 bits (because the LSB stores the + // ARM/Thumb state). + Ret += "-Fi8"; + // ABIs other than APCS have 64 bit integers with natural alignment. if (ABI != ARMBaseTargetMachine::ARM_ABI_APCS) Ret += "-i64:64"; Index: llvm/lib/IR/Value.cpp =================================================================== --- llvm/lib/IR/Value.cpp +++ llvm/lib/IR/Value.cpp @@ -650,8 +650,16 @@ if (auto *GO = dyn_cast<GlobalObject>(this)) { // Don't make any assumptions about function pointer alignment. Some // targets use the LSBs to store additional information. - if (isa<Function>(GO)) - return 0; + if (isa<Function>(GO)) { + switch (DL.getFunctionPtrAlignType()) { + case DataLayout::FunctionPtrAlignType::Independent: + return DL.getFunctionPtrAlign(); + case DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign: + return std::max(DL.getFunctionPtrAlign(), GO->getAlignment()); + default: + llvm_unreachable("unknown function pointer align type"); + } + } Align = GO->getAlignment(); if (Align == 0) { if (auto *GVar = dyn_cast<GlobalVariable>(GO)) { Index: llvm/lib/IR/DataLayout.cpp =================================================================== --- llvm/lib/IR/DataLayout.cpp +++ llvm/lib/IR/DataLayout.cpp @@ -184,6 +184,8 @@ AllocaAddrSpace = 0; StackNaturalAlign = 0; ProgramAddrSpace = 0; + FunctionPtrAlign = 0; + TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; ManglingMode = MM_None; NonIntegralAddressSpaces.clear(); @@ -379,6 +381,22 @@ StackNaturalAlign = inBytes(getInt(Tok)); break; } + case 'F': { + switch (Tok.front()) { + case 'i': + TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; + break; + case 'n': + TheFunctionPtrAlignType = FunctionPtrAlignType::MultipleOfFunctionAlign; + break; + default: + report_fatal_error("Unknown function pointer alignment type in " + "datalayout string"); + } + Tok = Tok.substr(1); + FunctionPtrAlign = inBytes(getInt(Tok)); + break; + } case 'P': { // Function address space. ProgramAddrSpace = getAddrSpace(Tok); break; @@ -432,6 +450,8 @@ AllocaAddrSpace == Other.AllocaAddrSpace && StackNaturalAlign == Other.StackNaturalAlign && ProgramAddrSpace == Other.ProgramAddrSpace && + FunctionPtrAlign == Other.FunctionPtrAlign && + TheFunctionPtrAlignType == Other.TheFunctionPtrAlignType && ManglingMode == Other.ManglingMode && LegalIntWidths == Other.LegalIntWidths && Alignments == Other.Alignments && Pointers == Other.Pointers; Index: llvm/lib/IR/Constants.cpp =================================================================== --- llvm/lib/IR/Constants.cpp +++ llvm/lib/IR/Constants.cpp @@ -11,11 +11,11 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/Constants.h" -#include "ConstantFold.h" #include "LLVMContextImpl.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/IR/ConstantFold.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/GlobalValue.h" Index: llvm/lib/IR/ConstantFold.h =================================================================== --- llvm/lib/IR/ConstantFold.h +++ /dev/null @@ -1,55 +0,0 @@ -//===-- ConstantFolding.h - Internal Constant Folding Interface -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the (internal) constant folding interfaces for LLVM. These -// interfaces are used by the ConstantExpr::get* methods to automatically fold -// constants when possible. -// -// These operators may return a null object if they don't know how to perform -// the specified operation on the specified constant types. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_IR_CONSTANTFOLD_H -#define LLVM_LIB_IR_CONSTANTFOLD_H - -#include "llvm/ADT/Optional.h" - -namespace llvm { -template <typename T> class ArrayRef; - class Value; - class Constant; - class Type; - - // Constant fold various types of instruction... - Constant *ConstantFoldCastInstruction( - unsigned opcode, ///< The opcode of the cast - Constant *V, ///< The source constant - Type *DestTy ///< The destination type - ); - Constant *ConstantFoldSelectInstruction(Constant *Cond, - Constant *V1, Constant *V2); - Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx); - Constant *ConstantFoldInsertElementInstruction(Constant *Val, Constant *Elt, - Constant *Idx); - Constant *ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2, - Constant *Mask); - Constant *ConstantFoldExtractValueInstruction(Constant *Agg, - ArrayRef<unsigned> Idxs); - Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, - ArrayRef<unsigned> Idxs); - Constant *ConstantFoldBinaryInstruction(unsigned Opcode, Constant *V1, - Constant *V2); - Constant *ConstantFoldCompareInstruction(unsigned short predicate, - Constant *C1, Constant *C2); - Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool InBounds, - Optional<unsigned> InRangeIndex, - ArrayRef<Value *> Idxs); -} // End llvm namespace - -#endif Index: llvm/lib/IR/ConstantFold.cpp =================================================================== --- llvm/lib/IR/ConstantFold.cpp +++ llvm/lib/IR/ConstantFold.cpp @@ -16,7 +16,7 @@ // //===----------------------------------------------------------------------===// -#include "ConstantFold.h" +#include "llvm/IR/ConstantFold.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/Constants.h" @@ -26,6 +26,7 @@ #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/PatternMatch.h" #include "llvm/Support/ErrorHandling.h" @@ -1076,10 +1077,27 @@ isa<GlobalValue>(CE1->getOperand(0))) { GlobalValue *GV = cast<GlobalValue>(CE1->getOperand(0)); - // Functions are at least 4-byte aligned. - unsigned GVAlign = GV->getAlignment(); - if (isa<Function>(GV)) - GVAlign = std::max(GVAlign, 4U); + unsigned GVAlign; + + if (Module *TheModule = GV->getParent()) { + GVAlign = GV->getPointerAlignment(TheModule->getDataLayout()); + + // If the function alignment is not specified then assume that it + // is 4. + // This is dangerous; on x86, the alignment of the pointer + // corresponds to the alignment of the function, but might be less + // than 4 if it isn't explicitly specified. + // However, a fix for this behaviour was reverted because it + // increased code size (see https://reviews.llvm.org/D55115) + if (GVAlign == 0U && isa<Function>(GV)) + GVAlign = 4U; + } else if (isa<Function>(GV)) { + // Without a datalayout we have to assume the worst case: that the + // function pointer isn't aligned at all. + GVAlign = 0U; + } else { + GVAlign = GV->getAlignment(); + } if (GVAlign > 1) { unsigned DstWidth = CI2->getType()->getBitWidth(); Index: llvm/include/llvm/IR/DataLayout.h =================================================================== --- llvm/include/llvm/IR/DataLayout.h +++ llvm/include/llvm/IR/DataLayout.h @@ -108,6 +108,13 @@ /// generating LLVM IR is required to generate the right target data for the /// target being codegen'd to. class DataLayout { +public: + enum class FunctionPtrAlignType { + /// The function pointer alignment is independent of the function alignment. + Independent, + /// The function pointer alignment is a multiple of the function alignment. + MultipleOfFunctionAlign, + }; private: /// Defaults to false. bool BigEndian; @@ -116,6 +123,9 @@ unsigned StackNaturalAlign; unsigned ProgramAddrSpace; + unsigned FunctionPtrAlign; + FunctionPtrAlignType TheFunctionPtrAlignType; + enum ManglingModeT { MM_None, MM_ELF, @@ -199,6 +209,8 @@ BigEndian = DL.isBigEndian(); AllocaAddrSpace = DL.AllocaAddrSpace; StackNaturalAlign = DL.StackNaturalAlign; + FunctionPtrAlign = DL.FunctionPtrAlign; + TheFunctionPtrAlignType = DL.TheFunctionPtrAlignType; ProgramAddrSpace = DL.ProgramAddrSpace; ManglingMode = DL.ManglingMode; LegalIntWidths = DL.LegalIntWidths; @@ -256,6 +268,17 @@ unsigned getStackAlignment() const { return StackNaturalAlign; } unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; } + /// Returns the alignment of function pointers, which may or may not be + /// related to the alignment of functions. + /// \see getFunctionPtrAlignType + unsigned getFunctionPtrAlign() const { return FunctionPtrAlign; } + + /// Return the type of function pointer alignment. + /// \see getFunctionPtrAlign + FunctionPtrAlignType getFunctionPtrAlignType() const { + return TheFunctionPtrAlignType; + } + unsigned getProgramAddressSpace() const { return ProgramAddrSpace; } bool hasMicrosoftFastStdCallMangling() const { Index: llvm/include/llvm/IR/ConstantFold.h =================================================================== --- /dev/null +++ llvm/include/llvm/IR/ConstantFold.h @@ -0,0 +1,55 @@ +//===-- ConstantFolding.h - Internal Constant Folding Interface -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the (internal) constant folding interfaces for LLVM. These +// interfaces are used by the ConstantExpr::get* methods to automatically fold +// constants when possible. +// +// These operators may return a null object if they don't know how to perform +// the specified operation on the specified constant types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_IR_CONSTANTFOLD_H +#define LLVM_LIB_IR_CONSTANTFOLD_H + +#include "llvm/ADT/Optional.h" + +namespace llvm { +template <typename T> class ArrayRef; + class Value; + class Constant; + class Type; + + // Constant fold various types of instruction... + Constant *ConstantFoldCastInstruction( + unsigned opcode, ///< The opcode of the cast + Constant *V, ///< The source constant + Type *DestTy ///< The destination type + ); + Constant *ConstantFoldSelectInstruction(Constant *Cond, + Constant *V1, Constant *V2); + Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx); + Constant *ConstantFoldInsertElementInstruction(Constant *Val, Constant *Elt, + Constant *Idx); + Constant *ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2, + Constant *Mask); + Constant *ConstantFoldExtractValueInstruction(Constant *Agg, + ArrayRef<unsigned> Idxs); + Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, + ArrayRef<unsigned> Idxs); + Constant *ConstantFoldBinaryInstruction(unsigned Opcode, Constant *V1, + Constant *V2); + Constant *ConstantFoldCompareInstruction(unsigned short predicate, + Constant *C1, Constant *C2); + Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool InBounds, + Optional<unsigned> InRangeIndex, + ArrayRef<Value *> Idxs); +} // End llvm namespace + +#endif Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -2003,6 +2003,14 @@ targets. ``a:<abi>:<pref>`` This specifies the alignment for an object of aggregate type. +``F<type><abi>`` + This specifies the alignment for function pointers. + The options for ``<type>`` are: + + * ``i``: The alignment of function pointers is independent of the alignment + of functions, and is a multiple of ``<abi>``. + * ``n``: The alignment of function pointers is a multiple of the explicit + alignment specified on the function, and is a multiple of ``<abi>``. ``m:<mangling>`` If present, specifies that llvm names are mangled in the output. Symbols prefixed with the mangling escape character ``\01`` are passed through Index: clang/test/CodeGen/target-data.c =================================================================== --- clang/test/CodeGen/target-data.c +++ clang/test/CodeGen/target-data.c @@ -96,7 +96,7 @@ // RUN: %clang_cc1 -triple arm-nacl -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=ARM-NACL -// ARM-NACL: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128" +// ARM-NACL: target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S128" // RUN: %clang_cc1 -triple mipsel-nacl -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=MIPS-NACL @@ -165,19 +165,19 @@ // RUN: %clang_cc1 -triple thumb-unknown-gnueabi -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=THUMB -// THUMB: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" +// THUMB: target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" // RUN: %clang_cc1 -triple arm-unknown-gnueabi -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=ARM -// ARM: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" +// ARM: target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" // RUN: %clang_cc1 -triple thumb-unknown -o - -emit-llvm -target-abi apcs-gnu \ // RUN: %s | FileCheck %s -check-prefix=THUMB-GNU -// THUMB-GNU: target datalayout = "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" +// THUMB-GNU: target datalayout = "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" // RUN: %clang_cc1 -triple arm-unknown -o - -emit-llvm -target-abi apcs-gnu \ // RUN: %s | FileCheck %s -check-prefix=ARM-GNU -// ARM-GNU: target datalayout = "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" +// ARM-GNU: target datalayout = "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" // RUN: %clang_cc1 -triple arc-unknown-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=ARC Index: clang/test/CodeGen/armv7k-abi.c =================================================================== --- clang/test/CodeGen/armv7k-abi.c +++ clang/test/CodeGen/armv7k-abi.c @@ -4,7 +4,7 @@ // Make sure 64 and 128 bit types are naturally aligned by the v7k ABI: -// CHECK: target datalayout = "e-m:o-p:32:32-i64:64-a:0:32-n32-S128" +// CHECK: target datalayout = "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128" typedef struct { float arr[4]; Index: clang/lib/Basic/Targets/ARM.cpp =================================================================== --- clang/lib/Basic/Targets/ARM.cpp +++ clang/lib/Basic/Targets/ARM.cpp @@ -40,13 +40,14 @@ // so set preferred for small types to 32. if (T.isOSBinFormatMachO()) { resetDataLayout(BigEndian - ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" - : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); + ? "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"); } else if (T.isOSWindows()) { assert(!BigEndian && "Windows on ARM does not support big endian"); resetDataLayout("e" "-m:w" "-p:32:32" + "-Fi8" "-i64:64" "-v128:64:128" "-a:0:32" @@ -54,11 +55,11 @@ "-S64"); } else if (T.isOSNaCl()) { assert(!BigEndian && "NaCl on ARM does not support big endian"); - resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128"); + resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S128"); } else { resetDataLayout(BigEndian - ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" - : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); + ? "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + : "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"); } // FIXME: Enumerated types are variable width in straight AAPCS. @@ -87,17 +88,17 @@ if (T.isOSBinFormatMachO() && IsAAPCS16) { assert(!BigEndian && "AAPCS16 does not support big-endian"); - resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128"); + resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128"); } else if (T.isOSBinFormatMachO()) resetDataLayout( BigEndian - ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" - : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); + ? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" + : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); else resetDataLayout( BigEndian - ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" - : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); + ? "E-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" + : "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); // FIXME: Override "preferred align" for double and long long. } @@ -1055,7 +1056,7 @@ this->WCharType = TargetInfo::UnsignedShort; TLSSupported = false; DoubleAlign = LongLongAlign = 64; - resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); + resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"); } void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits