diff --git a/clang/test/CodeGen/stackrealign-main.c b/clang/test/CodeGen/stackrealign-main.c --- a/clang/test/CodeGen/stackrealign-main.c +++ b/clang/test/CodeGen/stackrealign-main.c @@ -18,5 +18,5 @@ // CHECK-NOT: "stackrealign" // CHECK: } // CHECK: attributes [[MAIN]] = { noinline nounwind optnone {{.*}}"stackrealign"{{.*}} } -// CHECK: !{i32 1, !"override-stack-alignment", i32 64} +// CHECK: !{i32 8, !"override-stack-alignment", i32 64} // DEFAULT-NOT: "override-stack-alignment" diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -398,7 +398,8 @@ typedef enum { /** * Emits an error if two values disagree, otherwise the resulting value is - * that of the operands. + * that of the operands. Does not error if one module has a value but the + * other does not. * * @see Module::ModFlagBehavior::Error */ @@ -444,6 +445,14 @@ * @see Module::ModFlagBehavior::AppendUnique */ LLVMModuleFlagBehaviorAppendUnique, + + /** + * Emits an error if two values disagree, or when a value is specified for + * one module, but not another. + * + * @see Module::ModFlagBehavior::ErrorWhenMissing + */ + LLVMModuleFlagBehaviorErrorWhenMissing, } LLVMModuleFlagBehavior; /** diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -116,7 +116,8 @@ /// This enumeration defines the supported behaviors of module flags. enum ModFlagBehavior { /// Emits an error if two values disagree, otherwise the resulting value is - /// that of the operands. + /// that of the operands. Does not produce an error if one module is + /// missing a value. Error = 1, /// Emits a warning if two values disagree. The result value will be the @@ -148,9 +149,13 @@ /// Takes the max of the two values, which are required to be integers. Max = 7, + /// Emits an error if two values disagree, or when a value is specified for + /// one module, but not another. + ErrorWhenMissing = 8, + // Markers: ModFlagBehaviorFirstVal = Error, - ModFlagBehaviorLastVal = Max + ModFlagBehaviorLastVal = ErrorWhenMissing }; /// Checks if Metadata represents a valid ModFlagBehavior, and stores the diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -322,6 +322,8 @@ return Module::ModFlagBehavior::Append; case LLVMModuleFlagBehaviorAppendUnique: return Module::ModFlagBehavior::AppendUnique; + case LLVMModuleFlagBehaviorErrorWhenMissing: + return Module::ModFlagBehavior::ErrorWhenMissing; } llvm_unreachable("Unknown LLVMModuleFlagBehavior"); } @@ -341,6 +343,8 @@ return LLVMModuleFlagBehaviorAppend; case Module::ModFlagBehavior::AppendUnique: return LLVMModuleFlagBehaviorAppendUnique; + case Module::ModFlagBehavior::ErrorWhenMissing: + return LLVMModuleFlagBehaviorErrorWhenMissing; default: llvm_unreachable("Unhandled Flag Behavior"); } diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -729,7 +729,8 @@ } void Module::setOverrideStackAlignment(unsigned Align) { - addModuleFlag(ModFlagBehavior::Error, "override-stack-alignment", Align); + addModuleFlag(ModFlagBehavior::ErrorWhenMissing, "override-stack-alignment", + Align); } void Module::setSDKVersion(const VersionTuple &V) { diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1561,6 +1561,7 @@ case Module::Error: case Module::Warning: case Module::Override: + case Module::ErrorWhenMissing: // These behavior types accept any value. break; diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1216,17 +1216,41 @@ /// Merge the linker flags in Src into the Dest module. Error IRLinker::linkModuleFlagsMetadata() { - // If the source module has no module flags, we are done. - const NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata(); - if (!SrcModFlags) + NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata(); + NamedMDNode *DstModFlags = DstM.getOrInsertModuleFlagsMetadata(); + + // If the source module has no module flags, we still need to scan the + // destination module for any ErrorWhenMissing, otherwise we are done. + if (!SrcModFlags) { + for (MDNode *Op : DstModFlags->operands()) { + ConstantInt *Behavior = mdconst::extract(Op->getOperand(0)); + if (Behavior->getZExtValue() == Module::ErrorWhenMissing) { + MDString *ID = cast(Op->getOperand(1)); + return stringErr("linking module flags '" + ID->getString() + + "': IDs have conflicting behaviors in '" + + SrcM->getModuleIdentifier() + "' and '" + + DstM.getModuleIdentifier() + "'"); + } + } return Error::success(); + } // If the destination module doesn't have module flags yet, then just copy - // over the source module's flags. - NamedMDNode *DstModFlags = DstM.getOrInsertModuleFlagsMetadata(); + // over the source module's flags. Make sure to check for any + // ErrorWhenMissing. if (DstModFlags->getNumOperands() == 0) { - for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I) - DstModFlags->addOperand(SrcModFlags->getOperand(I)); + for (MDNode *Op : SrcModFlags->operands()) { + ConstantInt *Behavior = mdconst::extract(Op->getOperand(0)); + if (Behavior->getZExtValue() == Module::ErrorWhenMissing) { + MDString *ID = cast(Op->getOperand(1)); + // TODO: main case is now failing. + return stringErr("linking module flags '" + ID->getString() + + "': IDs have conflicting behaviors in '" + + SrcM->getModuleIdentifier() + "' and '" + + DstM.getModuleIdentifier() + "'"); + } + DstModFlags->addOperand(Op); + } return Error::success(); } @@ -1360,7 +1384,8 @@ case Module::Require: case Module::Override: llvm_unreachable("not possible"); - case Module::Error: { + case Module::Error: + case Module::ErrorWhenMissing: { // Emit an error if the values differ. if (SrcOp->getOperand(2) != DstOp->getOperand(2)) return stringErr("linking module flags '" + ID->getString() + diff --git a/llvm/test/Linker/stack-alignment.ll b/llvm/test/Linker/stack-alignment.ll --- a/llvm/test/Linker/stack-alignment.ll +++ b/llvm/test/Linker/stack-alignment.ll @@ -1,22 +1,19 @@ ; RUN: split-file %s %t -; TODO: it seems that ModFlagBehavior::Error doesn't error when a module is -; missing a module level attribute. IRLinker::linkModuleFlagsMetadata -; seems to think this is ok. Debugging stack mismatch errors is not a fun -; time. -; RUN not llvm-link %t/main.ll %t/none.ll 2>&1 | FileCheck --check-prefix=NONE %s +; RUN: not llvm-link %t/main.ll %t/none.ll 2>&1 | FileCheck --check-prefix=NONE %s +; RUN: not llvm-link %t/none.ll %t/main.ll 2>&1 | FileCheck --check-prefix=NONE %s ; RUN: llvm-link %t/main.ll %t/8.ll ; RUN: not llvm-link %t/main.ll %t/16.ll 2>&1 | FileCheck --check-prefix=CHECK-16 %s ;--- main.ll -; NONE: error: linking module flags 'override-stack-alignment': IDs have conflicting values -; CHECK-16: error: linking module flags 'override-stack-alignment': IDs have conflicting values +; NONE: error: linking module flags 'override-stack-alignment': IDs have conflicting behaviors +; CHECK-16: error: linking module flags 'override-stack-alignment': IDs have conflicting behaviors !llvm.module.flags = !{!0} -!0 = !{i32 1, !"override-stack-alignment", i32 8} +!0 = !{i32 8, !"override-stack-alignment", i32 8} ;--- none.ll ;--- 8.ll !llvm.module.flags = !{!0} -!0 = !{i32 1, !"override-stack-alignment", i32 8} +!0 = !{i32 8, !"override-stack-alignment", i32 8} ;--- 16.ll !llvm.module.flags = !{!0} -!0 = !{i32 1, !"override-stack-alignment", i32 16} +!0 = !{i32 8, !"override-stack-alignment", i32 16}