Index: include/llvm/IR/Module.h =================================================================== --- include/llvm/IR/Module.h +++ include/llvm/IR/Module.h @@ -16,6 +16,7 @@ #define LLVM_IR_MODULE_H #include "llvm-c/Types.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -840,6 +841,17 @@ void setPIELevel(PIELevel::Level PL); /// @} + /// @} + /// @name Utility function for querying and setting code model + /// @{ + + /// Returns the code model (tiny, small, kernel, medium or large model) + Optional getCodeModel() const; + + /// Set the code model (tiny, small, kernel, medium or large) + void setCodeModel(CodeModel::Model CL); + /// @} + /// @name Utility functions for querying and setting PGO summary /// @{ Index: lib/IR/Module.cpp =================================================================== --- lib/IR/Module.cpp +++ lib/IR/Module.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/Module.h" #include "SymbolTableListTraitsImpl.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -507,6 +508,24 @@ addModuleFlag(ModFlagBehavior::Max, "PIE Level", PL); } +Optional Module::getCodeModel() const { + auto *Val = cast_or_null(getModuleFlag("Code Model")); + + if (!Val) + return None; + + return static_cast( + cast(Val->getValue())->getZExtValue()); +} + +void Module::setCodeModel(CodeModel::Model CL) { + // Linking object files with different code models is undefined behavior + // because the compiler would have to generate additional code (to span + // longer jumps) if a larger code model is used with a smaller one. + // Therefore we will treat attempts to mix code models as an error. + addModuleFlag(ModFlagBehavior::Error, "Code Model", CL); +} + void Module::setProfileSummary(Metadata *M) { addModuleFlag(ModFlagBehavior::Error, "ProfileSummary", M); } Index: lib/LTO/LTOBackend.cpp =================================================================== --- lib/LTO/LTOBackend.cpp +++ lib/LTO/LTOBackend.cpp @@ -138,9 +138,15 @@ RelocModel = M.getPICLevel() == PICLevel::NotPIC ? Reloc::Static : Reloc::PIC_; + Optional CodeModel; + if (Conf.CodeModel) + CodeModel = *Conf.CodeModel; + else if (M.getCodeModel()) + CodeModel = M.getCodeModel(); + return std::unique_ptr(TheTarget->createTargetMachine( TheTriple, Conf.CPU, Features.getString(), Conf.Options, RelocModel, - Conf.CodeModel, Conf.CGOptLevel)); + CodeModel, Conf.CGOptLevel)); } static void runNewPMPasses(Config &Conf, Module &Mod, TargetMachine *TM, Index: test/LTO/X86/Inputs/codemodel-3.ll =================================================================== --- test/LTO/X86/Inputs/codemodel-3.ll +++ test/LTO/X86/Inputs/codemodel-3.ll @@ -0,0 +1,16 @@ +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"Code Model", i32 1} + +%struct.rtx_def = type { i16, i16 } + +define void @bar(%struct.rtx_def* %a, i8 %b, i32 %c) { + call void @llvm.memset.p0struct.rtx_def.i32(%struct.rtx_def* align 4 %a, i8 %b, i32 %c, i1 true) + ret void +} + +declare void @llvm.memset.p0struct.rtx_def.i32(%struct.rtx_def*, i8, i32, i1) Index: test/LTO/X86/codemodel-1.ll =================================================================== --- test/LTO/X86/codemodel-1.ll +++ test/LTO/X86/codemodel-1.ll @@ -0,0 +1,20 @@ +; RUN: llvm-as %s -o %t.o +; RUN: llvm-lto2 run -r %t.o,_start,px %t.o -o %t.s +; RUN: llvm-objdump -d %t.s.0 | FileCheck %s --check-prefix=CHECK-SMALL + +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"Code Model", i32 1} + +@data = internal constant [0 x i32] [] + +define i32* @_start() nounwind readonly { +entry: +; CHECK-SMALL-LABEL: _start: +; CHECK-SMALL: leaq (%rip), %rax + ret i32* getelementptr ([0 x i32], [0 x i32]* @data, i64 0, i64 0) +} Index: test/LTO/X86/codemodel-2.ll =================================================================== --- test/LTO/X86/codemodel-2.ll +++ test/LTO/X86/codemodel-2.ll @@ -0,0 +1,20 @@ +; RUN: llvm-as %s -o %t.o +; RUN: llvm-lto2 run -r %t.o,_start,px %t.o -o %t.s +; RUN: llvm-objdump -d %t.s.0 | FileCheck %s --check-prefix=CHECK-LARGE + +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"Code Model", i32 4} + +@data = internal constant [0 x i32] [] + +define i32* @_start() nounwind readonly { +entry: +; CHECK-LARGE-LABEL: _start: +; CHECK-LARGE: movabsq $0, %rax + ret i32* getelementptr ([0 x i32], [0 x i32]* @data, i64 0, i64 0) +} Index: test/LTO/X86/codemodel-3.ll =================================================================== --- test/LTO/X86/codemodel-3.ll +++ test/LTO/X86/codemodel-3.ll @@ -0,0 +1,20 @@ +; RUN: llvm-as %s -o %t0.o +; RUN: llvm-as < %p/Inputs/codemodel-3.ll > %t1.o +; RUN: not llvm-lto2 run -r %t0.o,_start,px -r %t1.o,bar,px %t0.o %t1.o -o %t2.s 2>&1 | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"Code Model", i32 4} + +@data = internal constant [0 x i32] [] + +define i32* @_start() nounwind readonly { +entry: + ret i32* getelementptr ([0 x i32], [0 x i32]* @data, i64 0, i64 0) +} + +; CHECK: 'Code Model': IDs have conflicting values