Commit b097545a5f

Andrew Kelley <andrew@ziglang.org>
2021-11-27 03:59:33
zig cc: honor all -m and -mno- CPU feature flags
closes #9196
1 parent eec825c
lib/std/zig/cross_target.zig
@@ -323,6 +323,21 @@ pub const CrossTarget = struct {
         return result;
     }
 
+    /// Similar to `parse` except instead of fully parsing, it only determines the CPU
+    /// architecture and returns it if it can be determined, and returns `null` otherwise.
+    /// This is intended to be used if the API user of CrossTarget needs to learn the
+    /// target CPU architecture in order to fully populate `ParseOptions`.
+    pub fn parseCpuArch(args: ParseOptions) ?Target.Cpu.Arch {
+        var it = mem.split(u8, args.arch_os_abi, "-");
+        const arch_name = it.next().?;
+        const arch_is_native = mem.eql(u8, arch_name, "native");
+        if (arch_is_native) {
+            return builtin.cpu.arch;
+        } else {
+            return std.meta.stringToEnum(Target.Cpu.Arch, arch_name);
+        }
+    }
+
     /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
     pub fn getCpu(self: CrossTarget) Target.Cpu {
         switch (self.cpu_model) {
src/clang_options.zig
@@ -132,3 +132,13 @@ pub fn sepd1(name: []const u8) CliArg {
         .pd1 = true,
     };
 }
+
+/// Shortcut function for initializing a `CliArg`
+pub fn m(name: []const u8) CliArg {
+    return .{
+        .name = name,
+        .syntax = .flag,
+        .zig_equivalent = .m,
+        .pd1 = true,
+    };
+}
src/clang_options_data.zig
@@ -7,6 +7,7 @@ const flagpsl = clang_options.flagpsl;
 const joinpd1 = clang_options.joinpd1;
 const jspd1 = clang_options.jspd1;
 const sepd1 = clang_options.sepd1;
+const m = clang_options.m;
 pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{
 flagpd1("C"),
 flagpd1("CC"),
@@ -3771,8 +3772,8 @@ sepd1("lazy_library"),
 sepd1("load"),
 flagpd1("m16"),
 flagpd1("m32"),
-flagpd1("m3dnow"),
-flagpd1("m3dnowa"),
+m("m3dnow"),
+m("m3dnowa"),
 flagpd1("m64"),
 flagpd1("m68000"),
 flagpd1("m68010"),
@@ -3781,110 +3782,110 @@ flagpd1("m68030"),
 flagpd1("m68040"),
 flagpd1("m68060"),
 flagpd1("m80387"),
-flagpd1("mseses"),
+m("mseses"),
 flagpd1("mabi=ieeelongdouble"),
 flagpd1("mabi=vec-default"),
 flagpd1("mabi=vec-extabi"),
 flagpd1("mabicalls"),
-flagpd1("madx"),
-flagpd1("maes"),
+m("madx"),
+m("maes"),
 sepd1("main-file-name"),
 flagpd1("maix-struct-return"),
 flagpd1("malign-double"),
-flagpd1("maltivec"),
+m("maltivec"),
 flagpd1("mamdgpu-ieee"),
-flagpd1("mamx-bf16"),
-flagpd1("mamx-tile"),
+m("mamx-bf16"),
+m("mamx-tile"),
 flagpd1("marm"),
 flagpd1("massembler-fatal-warnings"),
 flagpd1("massembler-no-warn"),
-flagpd1("matomics"),
-flagpd1("mavx"),
-flagpd1("mavx2"),
-flagpd1("mavx512bf16"),
-flagpd1("mavx512bitalg"),
-flagpd1("mavx512bw"),
-flagpd1("mavx512cd"),
-flagpd1("mavx512dq"),
-flagpd1("mavx512er"),
-flagpd1("mavx512f"),
-flagpd1("mavx512ifma"),
-flagpd1("mavx512pf"),
-flagpd1("mavx512vbmi"),
-flagpd1("mavx512vbmi2"),
-flagpd1("mavx512vl"),
-flagpd1("mavx512vnni"),
-flagpd1("mavx512vp2intersect"),
-flagpd1("mavx512vpopcntdq"),
-flagpd1("mavxvnni"),
+m("matomics"),
+m("mavx"),
+m("mavx2"),
+m("mavx512bf16"),
+m("mavx512bitalg"),
+m("mavx512bw"),
+m("mavx512cd"),
+m("mavx512dq"),
+m("mavx512er"),
+m("mavx512f"),
+m("mavx512ifma"),
+m("mavx512pf"),
+m("mavx512vbmi"),
+m("mavx512vbmi2"),
+m("mavx512vl"),
+m("mavx512vnni"),
+m("mavx512vp2intersect"),
+m("mavx512vpopcntdq"),
+m("mavxvnni"),
 flagpd1("mbackchain"),
 flagpd1("mbig-endian"),
-flagpd1("mbmi"),
-flagpd1("mbmi2"),
+m("mbmi"),
+m("mbmi2"),
 flagpd1("mbranch-likely"),
 flagpd1("mbranch-target-enforce"),
 flagpd1("mbranches-within-32B-boundaries"),
-flagpd1("mbulk-memory"),
+m("mbulk-memory"),
 flagpd1("mcheck-zero-division"),
-flagpd1("mcldemote"),
-flagpd1("mclflushopt"),
-flagpd1("mclwb"),
-flagpd1("mclzero"),
+m("mcldemote"),
+m("mclflushopt"),
+m("mclwb"),
+m("mclzero"),
 flagpd1("mcmodel=medany"),
 flagpd1("mcmodel=medlow"),
-flagpd1("mcmpb"),
+m("mcmpb"),
 flagpd1("mcmse"),
 flagpd1("mcode-object-v3"),
 flagpd1("mconstant-cfstrings"),
 flagpd1("mconstructor-aliases"),
 flagpd1("mcpu=?"),
-flagpd1("mcrbits"),
-flagpd1("mcrc"),
-flagpd1("mcumode"),
-flagpd1("mcx16"),
+m("mcrbits"),
+m("mcrc"),
+m("mcumode"),
+m("mcx16"),
 sepd1("mdebug-pass"),
-flagpd1("mdirect-move"),
+m("mdirect-move"),
 flagpd1("mdisable-tail-calls"),
 flagpd1("mdouble-float"),
-flagpd1("mdsp"),
-flagpd1("mdspr2"),
+m("mdsp"),
+m("mdspr2"),
 sepd1("meabi"),
-flagpd1("mefpu2"),
+m("mefpu2"),
 flagpd1("membedded-data"),
 flagpd1("menable-experimental-extensions"),
 flagpd1("menable-no-infs"),
 flagpd1("menable-no-nans"),
 flagpd1("menable-unsafe-fp-math"),
-flagpd1("menqcmd"),
-flagpd1("mexception-handling"),
-flagpd1("mexecute-only"),
+m("menqcmd"),
+m("mexception-handling"),
+m("mexecute-only"),
 flagpd1("mextern-sdata"),
-flagpd1("mf16c"),
+m("mf16c"),
 flagpd1("mfancy-math-387"),
 flagpd1("mfentry"),
 flagpd1("mfix-and-continue"),
 flagpd1("mfix-cortex-a53-835769"),
-flagpd1("mfloat128"),
+m("mfloat128"),
 sepd1("mfloat-abi"),
-flagpd1("mfma"),
-flagpd1("mfma4"),
+m("mfma"),
+m("mfma4"),
 flagpd1("mfp32"),
-flagpd1("mfp64"),
+m("mfp64"),
 sepd1("mfpmath"),
-flagpd1("mfprnd"),
-flagpd1("mfpxx"),
-flagpd1("mfsgsbase"),
-flagpd1("mfxsr"),
+m("mfprnd"),
+m("mfpxx"),
+m("mfsgsbase"),
+m("mfxsr"),
 flagpd1("mgeneral-regs-only"),
-flagpd1("mgfni"),
-flagpd1("mginv"),
+m("mgfni"),
+m("mginv"),
 flagpd1("mglibc"),
 flagpd1("mglobal-merge"),
 flagpd1("mgpopt"),
-flagpd1("mhard-float"),
-flagpd1("mhvx"),
-flagpd1("mhreset"),
-flagpd1("mhtm"),
+m("mhard-float"),
+m("mhvx"),
+m("mhreset"),
+m("mhtm"),
 flagpd1("miamcu"),
 flagpd1("mieee-fp"),
 flagpd1("mieee-rnd-near"),
@@ -3895,8 +3896,8 @@ flagpd1("no-ns-alloc-error"),
 flagpd1("mimplicit-float"),
 flagpd1("mincremental-linker-compatible"),
 flagpd1("minline-all-stringops"),
-flagpd1("minvariant-function-descriptors"),
-flagpd1("minvpcid"),
+m("minvariant-function-descriptors"),
+m("minvpcid"),
 flagpd1("mips1"),
 flagpd1("mips16"),
 flagpd1("mips2"),
@@ -3913,9 +3914,9 @@ flagpd1("mips64r2"),
 flagpd1("mips64r3"),
 flagpd1("mips64r5"),
 flagpd1("mips64r6"),
-flagpd1("misel"),
+m("misel"),
 flagpd1("mkernel"),
-flagpd1("mkl"),
+m("mkl"),
 flagpd1("mldc1-sdc1"),
 sepd1("mlimit-float-precision"),
 sepd1("mlink-bitcode-file"),
@@ -3924,166 +3925,166 @@ sepd1("mlink-cuda-bitcode"),
 flagpd1("mlittle-endian"),
 sepd1("mllvm"),
 flagpd1("mlocal-sdata"),
-flagpd1("mlong-calls"),
+m("mlong-calls"),
 flagpd1("mlong-double-128"),
 flagpd1("mlong-double-64"),
 flagpd1("mlong-double-80"),
-flagpd1("mlongcall"),
-flagpd1("mlvi-cfi"),
+m("mlongcall"),
+m("mlvi-cfi"),
 flagpd1("mlvi-hardening"),
-flagpd1("mlwp"),
-flagpd1("mlzcnt"),
+m("mlwp"),
+m("mlzcnt"),
 flagpd1("mmadd4"),
 flagpd1("mmark-bti-property"),
-flagpd1("mmemops"),
+m("mmemops"),
 flagpd1("mmfcrf"),
-flagpd1("mmfocrf"),
-flagpd1("mmicromips"),
-flagpd1("mmma"),
-flagpd1("mmmx"),
-flagpd1("mmovbe"),
-flagpd1("mmovdir64b"),
-flagpd1("mmovdiri"),
+m("mmfocrf"),
+m("mmicromips"),
+m("mmma"),
+m("mmmx"),
+m("mmovbe"),
+m("mmovdir64b"),
+m("mmovdiri"),
 flagpd1("mmpx"),
 flagpd1("mms-bitfields"),
-flagpd1("mmsa"),
-flagpd1("mmt"),
-flagpd1("mmultivalue"),
-flagpd1("mmutable-globals"),
-flagpd1("mmwaitx"),
-flagpd1("mno-3dnow"),
-flagpd1("mno-3dnowa"),
+m("mmsa"),
+m("mmt"),
+m("mmultivalue"),
+m("mmutable-globals"),
+m("mmwaitx"),
+m("mno-3dnow"),
+m("mno-3dnowa"),
 flagpd1("mno-80387"),
 flagpd1("mno-abicalls"),
-flagpd1("mno-adx"),
-flagpd1("mno-aes"),
-flagpd1("mno-altivec"),
+m("mno-adx"),
+m("mno-aes"),
+m("mno-altivec"),
 flagpd1("mno-amdgpu-ieee"),
-flagpd1("mno-amx-bf16"),
-flagpd1("mno-amx-int8"),
-flagpd1("mno-amx-tile"),
-flagpd1("mno-atomics"),
-flagpd1("mno-avx"),
-flagpd1("mno-avx2"),
-flagpd1("mno-avx512bf16"),
-flagpd1("mno-avx512bitalg"),
-flagpd1("mno-avx512bw"),
-flagpd1("mno-avx512cd"),
-flagpd1("mno-avx512dq"),
-flagpd1("mno-avx512er"),
-flagpd1("mno-avx512f"),
-flagpd1("mno-avx512ifma"),
-flagpd1("mno-avx512pf"),
-flagpd1("mno-avx512vbmi"),
-flagpd1("mno-avx512vbmi2"),
-flagpd1("mno-avx512vl"),
-flagpd1("mno-avx512vnni"),
-flagpd1("mno-avx512vp2intersect"),
-flagpd1("mno-avx512vpopcntdq"),
-flagpd1("mno-avxvnni"),
+m("mno-amx-bf16"),
+m("mno-amx-int8"),
+m("mno-amx-tile"),
+m("mno-atomics"),
+m("mno-avx"),
+m("mno-avx2"),
+m("mno-avx512bf16"),
+m("mno-avx512bitalg"),
+m("mno-avx512bw"),
+m("mno-avx512cd"),
+m("mno-avx512dq"),
+m("mno-avx512er"),
+m("mno-avx512f"),
+m("mno-avx512ifma"),
+m("mno-avx512pf"),
+m("mno-avx512vbmi"),
+m("mno-avx512vbmi2"),
+m("mno-avx512vl"),
+m("mno-avx512vnni"),
+m("mno-avx512vp2intersect"),
+m("mno-avx512vpopcntdq"),
+m("mno-avxvnni"),
 flagpd1("mno-backchain"),
-flagpd1("mno-bmi"),
-flagpd1("mno-bmi2"),
+m("mno-bmi"),
+m("mno-bmi2"),
 flagpd1("mno-branch-likely"),
-flagpd1("mno-bulk-memory"),
+m("mno-bulk-memory"),
 flagpd1("mno-check-zero-division"),
-flagpd1("mno-cldemote"),
-flagpd1("mno-clflushopt"),
-flagpd1("mno-clwb"),
-flagpd1("mno-clzero"),
-flagpd1("mno-cmpb"),
+m("mno-cldemote"),
+m("mno-clflushopt"),
+m("mno-clwb"),
+m("mno-clzero"),
+m("mno-cmpb"),
 flagpd1("mno-code-object-v3"),
 flagpd1("mno-constant-cfstrings"),
-flagpd1("mno-crbits"),
-flagpd1("mno-crc"),
-flagpd1("mno-cumode"),
-flagpd1("mno-cx16"),
-flagpd1("mno-dsp"),
-flagpd1("mno-dspr2"),
+m("mno-crbits"),
+m("mno-crc"),
+m("mno-cumode"),
+m("mno-cx16"),
+m("mno-dsp"),
+m("mno-dspr2"),
 flagpd1("mno-embedded-data"),
-flagpd1("mno-enqcmd"),
-flagpd1("mno-exception-handling"),
+m("mno-enqcmd"),
+m("mno-exception-handling"),
 flagpd1("mnoexecstack"),
-flagpd1("mno-execute-only"),
+m("mno-execute-only"),
 flagpd1("mno-extern-sdata"),
-flagpd1("mno-f16c"),
+m("mno-f16c"),
 flagpd1("mno-fix-cortex-a53-835769"),
-flagpd1("mno-float128"),
-flagpd1("mno-fma"),
-flagpd1("mno-fma4"),
-flagpd1("mno-fprnd"),
-flagpd1("mno-fsgsbase"),
-flagpd1("mno-fxsr"),
-flagpd1("mno-gfni"),
-flagpd1("mno-ginv"),
+m("mno-float128"),
+m("mno-fma"),
+m("mno-fma4"),
+m("mno-fprnd"),
+m("mno-fsgsbase"),
+m("mno-fxsr"),
+m("mno-gfni"),
+m("mno-ginv"),
 flagpd1("mno-global-merge"),
 flagpd1("mno-gpopt"),
-flagpd1("mno-hvx"),
-flagpd1("mno-hreset"),
-flagpd1("mno-htm"),
+m("mno-hvx"),
+m("mno-hreset"),
+m("mno-htm"),
 flagpd1("mno-iamcu"),
 flagpd1("mno-implicit-float"),
 flagpd1("mno-incremental-linker-compatible"),
 flagpd1("mno-inline-all-stringops"),
-flagpd1("mno-invariant-function-descriptors"),
-flagpd1("mno-invpcid"),
-flagpd1("mno-isel"),
-flagpd1("mno-kl"),
+m("mno-invariant-function-descriptors"),
+m("mno-invpcid"),
+m("mno-isel"),
+m("mno-kl"),
 flagpd1("mno-ldc1-sdc1"),
 flagpd1("mno-local-sdata"),
-flagpd1("mno-long-calls"),
-flagpd1("mno-longcall"),
-flagpd1("mno-lvi-cfi"),
+m("mno-long-calls"),
+m("mno-longcall"),
+m("mno-lvi-cfi"),
 flagpd1("mno-lvi-hardening"),
-flagpd1("mno-lwp"),
-flagpd1("mno-lzcnt"),
+m("mno-lwp"),
+m("mno-lzcnt"),
 flagpd1("mno-madd4"),
-flagpd1("mno-memops"),
+m("mno-memops"),
 flagpd1("mno-mfcrf"),
-flagpd1("mno-mfocrf"),
-flagpd1("mno-micromips"),
-flagpd1("mno-mips16"),
-flagpd1("mno-mma"),
-flagpd1("mno-mmx"),
-flagpd1("mno-movbe"),
-flagpd1("mno-movdir64b"),
-flagpd1("mno-movdiri"),
-flagpd1("mno-movt"),
+m("mno-mfocrf"),
+m("mno-micromips"),
+m("mno-mips16"),
+m("mno-mma"),
+m("mno-mmx"),
+m("mno-movbe"),
+m("mno-movdir64b"),
+m("mno-movdiri"),
+m("mno-movt"),
 flagpd1("mno-mpx"),
 flagpd1("mno-ms-bitfields"),
-flagpd1("mno-msa"),
-flagpd1("mno-mt"),
-flagpd1("mno-multivalue"),
-flagpd1("mno-mutable-globals"),
-flagpd1("mno-mwaitx"),
-flagpd1("mno-neg-immediates"),
-flagpd1("mno-nontrapping-fptoint"),
-flagpd1("mno-nvj"),
-flagpd1("mno-nvs"),
+m("mno-msa"),
+m("mno-mt"),
+m("mno-multivalue"),
+m("mno-mutable-globals"),
+m("mno-mwaitx"),
+m("mno-neg-immediates"),
+m("mno-nontrapping-fptoint"),
+m("mno-nvj"),
+m("mno-nvs"),
 flagpd1("mno-odd-spreg"),
 flagpd1("mno-omit-leaf-frame-pointer"),
 flagpd1("mno-outline"),
-flagpd1("mno-outline-atomics"),
+m("mno-outline-atomics"),
 flagpd1("mno-packed-stack"),
-flagpd1("mno-packets"),
+m("mno-packets"),
 flagpd1("mno-pascal-strings"),
-flagpd1("mno-pclmul"),
-flagpd1("mno-pconfig"),
+m("mno-pclmul"),
+m("mno-pconfig"),
 flagpd1("mno-pcrel"),
-flagpd1("mno-pku"),
-flagpd1("mno-popcnt"),
-flagpd1("mno-popcntd"),
-flagpd1("mno-power10-vector"),
-flagpd1("mno-power8-vector"),
-flagpd1("mno-power9-vector"),
-flagpd1("mno-prefetchwt1"),
+m("mno-pku"),
+m("mno-popcnt"),
+m("mno-popcntd"),
+m("mno-power10-vector"),
+m("mno-power8-vector"),
+m("mno-power9-vector"),
+m("mno-prefetchwt1"),
 flagpd1("mno-prefixed"),
-flagpd1("mno-prfchw"),
-flagpd1("mno-ptwrite"),
+m("mno-prfchw"),
+m("mno-ptwrite"),
 flagpd1("mno-pure-code"),
-flagpd1("mno-rdpid"),
-flagpd1("mno-rdrnd"),
-flagpd1("mno-rdseed"),
+m("mno-rdpid"),
+m("mno-rdrnd"),
+m("mno-rdseed"),
 .{
     .name = "mno-red-zone",
     .syntax = .flag,
@@ -4092,73 +4093,73 @@ flagpd1("mno-rdseed"),
     .pd2 = false,
     .psl = false,
 },
-flagpd1("mno-reference-types"),
-flagpd1("mno-relax"),
+m("mno-reference-types"),
+m("mno-relax"),
 flagpd1("mno-relax-all"),
 flagpd1("mno-relax-pic-calls"),
 flagpd1("mno-restrict-it"),
-flagpd1("mno-retpoline"),
-flagpd1("mno-retpoline-external-thunk"),
+m("mno-retpoline"),
+m("mno-retpoline-external-thunk"),
 flagpd1("mno-rtd"),
-flagpd1("mno-rtm"),
-flagpd1("mno-sahf"),
-flagpd1("mno-save-restore"),
-flagpd1("mno-serialize"),
-flagpd1("mno-seses"),
-flagpd1("mno-sgx"),
-flagpd1("mno-sha"),
-flagpd1("mno-shstk"),
-flagpd1("mno-sign-ext"),
-flagpd1("mno-simd128"),
-flagpd1("mno-soft-float"),
-flagpd1("mno-spe"),
+m("mno-rtm"),
+m("mno-sahf"),
+m("mno-save-restore"),
+m("mno-serialize"),
+m("mno-seses"),
+m("mno-sgx"),
+m("mno-sha"),
+m("mno-shstk"),
+m("mno-sign-ext"),
+m("mno-simd128"),
+m("mno-soft-float"),
+m("mno-spe"),
 flagpd1("mno-speculative-load-hardening"),
-flagpd1("mno-sse"),
-flagpd1("mno-sse2"),
-flagpd1("mno-sse3"),
+m("mno-sse"),
+m("mno-sse2"),
+m("mno-sse3"),
 flagpd1("mno-sse4"),
-flagpd1("mno-sse4.1"),
-flagpd1("mno-sse4.2"),
-flagpd1("mno-sse4a"),
-flagpd1("mno-ssse3"),
+m("mno-sse4.1"),
+m("mno-sse4.2"),
+m("mno-sse4a"),
+m("mno-ssse3"),
 flagpd1("mno-stack-arg-probe"),
 flagpd1("mno-stackrealign"),
-flagpd1("mno-tail-call"),
-flagpd1("mno-tbm"),
-flagpd1("mno-tgsplit"),
+m("mno-tail-call"),
+m("mno-tbm"),
+m("mno-tgsplit"),
 flagpd1("mno-thumb"),
 flagpd1("mno-tls-direct-seg-refs"),
-flagpd1("mno-tsxldtrk"),
-flagpd1("mno-uintr"),
+m("mno-tsxldtrk"),
+m("mno-uintr"),
 flagpd1("mno-unaligned-access"),
 flagpd1("mno-unsafe-fp-atomics"),
-flagpd1("mno-vaes"),
-flagpd1("mno-virt"),
-flagpd1("mno-vpclmulqdq"),
-flagpd1("mno-vsx"),
+m("mno-vaes"),
+m("mno-virt"),
+m("mno-vpclmulqdq"),
+m("mno-vsx"),
 flagpd1("mno-vx"),
-flagpd1("mno-vzeroupper"),
-flagpd1("mno-waitpkg"),
+m("mno-vzeroupper"),
+m("mno-waitpkg"),
 flagpd1("mno-warn-nonportable-cfstrings"),
-flagpd1("mno-wavefrontsize64"),
-flagpd1("mno-wbnoinvd"),
-flagpd1("mno-widekl"),
-flagpd1("mno-x87"),
-flagpd1("mno-xgot"),
-flagpd1("mno-xop"),
-flagpd1("mno-xsave"),
-flagpd1("mno-xsavec"),
-flagpd1("mno-xsaveopt"),
-flagpd1("mno-xsaves"),
+m("mno-wavefrontsize64"),
+m("mno-wbnoinvd"),
+m("mno-widekl"),
+m("mno-x87"),
+m("mno-xgot"),
+m("mno-xop"),
+m("mno-xsave"),
+m("mno-xsavec"),
+m("mno-xsaveopt"),
+m("mno-xsaves"),
 flagpd1("mno-zvector"),
 flagpd1("mnocrc"),
-flagpd1("mno-direct-move"),
-flagpd1("mnontrapping-fptoint"),
+m("mno-direct-move"),
+m("mnontrapping-fptoint"),
 flagpd1("mnop-mcount"),
-flagpd1("mno-paired-vector-memops"),
-flagpd1("mno-crypto"),
-flagpd1("mnvj"),
-flagpd1("mnvs"),
+m("mno-paired-vector-memops"),
+m("mno-crypto"),
+m("mnvj"),
+m("mnvs"),
 flagpd1("modd-spreg"),
 sepd1("module-dependency-dir"),
 sepd1("module-dir"),
@@ -4167,31 +4168,31 @@ flagpd1("module-file-info"),
 sepd1("module-suffix"),
 flagpd1("momit-leaf-frame-pointer"),
 flagpd1("moutline"),
-flagpd1("moutline-atomics"),
+m("moutline-atomics"),
 flagpd1("mpacked-stack"),
-flagpd1("mpackets"),
-flagpd1("mpaired-vector-memops"),
+m("mpackets"),
+m("mpaired-vector-memops"),
 flagpd1("mpascal-strings"),
-flagpd1("mpclmul"),
-flagpd1("mpconfig"),
+m("mpclmul"),
+m("mpconfig"),
 flagpd1("mpcrel"),
-flagpd1("mpku"),
-flagpd1("mpopcnt"),
-flagpd1("mpopcntd"),
-flagpd1("mpower10-vector"),
-flagpd1("mcrypto"),
-flagpd1("mpower8-vector"),
-flagpd1("mpower9-vector"),
-flagpd1("mprefetchwt1"),
+m("mpku"),
+m("mpopcnt"),
+m("mpopcntd"),
+m("mpower10-vector"),
+m("mcrypto"),
+m("mpower8-vector"),
+m("mpower9-vector"),
+m("mprefetchwt1"),
 flagpd1("mprefixed"),
-flagpd1("mprfchw"),
-flagpd1("mprivileged"),
-flagpd1("mptwrite"),
+m("mprfchw"),
+m("mprivileged"),
+m("mptwrite"),
 flagpd1("mpure-code"),
 flagpd1("mqdsp6-compat"),
-flagpd1("mrdpid"),
-flagpd1("mrdrnd"),
-flagpd1("mrdseed"),
+m("mrdpid"),
+m("mrdrnd"),
+m("mrdseed"),
 flagpd1("mreassociate"),
 flagpd1("mrecip"),
 flagpd1("mrecord-mcount"),
@@ -4203,9 +4204,9 @@ flagpd1("mrecord-mcount"),
     .pd2 = false,
     .psl = false,
 },
-flagpd1("mreference-types"),
+m("mreference-types"),
 sepd1("mregparm"),
-flagpd1("mrelax"),
+m("mrelax"),
 flagpd1("mrelax-all"),
 flagpd1("mrelax-pic-calls"),
 .{
@@ -4218,86 +4219,86 @@ flagpd1("mrelax-pic-calls"),
 },
 sepd1("mrelocation-model"),
 flagpd1("mrestrict-it"),
-flagpd1("mretpoline"),
-flagpd1("mretpoline-external-thunk"),
-flagpd1("mrop-protect"),
+m("mretpoline"),
+m("mretpoline-external-thunk"),
+m("mrop-protect"),
 flagpd1("mrtd"),
-flagpd1("mrtm"),
-flagpd1("msahf"),
-flagpd1("msave-restore"),
+m("mrtm"),
+m("msahf"),
+m("msave-restore"),
 flagpd1("msave-temp-labels"),
-flagpd1("msecure-plt"),
-flagpd1("mserialize"),
-flagpd1("msgx"),
-flagpd1("msha"),
-flagpd1("mshstk"),
-flagpd1("msign-ext"),
+m("msecure-plt"),
+m("mserialize"),
+m("msgx"),
+m("msha"),
+m("mshstk"),
+m("msign-ext"),
 flagpd1("msim"),
-flagpd1("msimd128"),
-flagpd1("msingle-float"),
+m("msimd128"),
+m("msingle-float"),
 sepd1("msmall-data-limit"),
-flagpd1("msoft-float"),
-flagpd1("mspe"),
+m("msoft-float"),
+m("mspe"),
 flagpd1("mspeculative-load-hardening"),
-flagpd1("msse"),
-flagpd1("msse2"),
-flagpd1("msse3"),
+m("msse"),
+m("msse2"),
+m("msse3"),
 flagpd1("msse4"),
-flagpd1("msse4.1"),
-flagpd1("msse4.2"),
-flagpd1("msse4a"),
-flagpd1("mssse3"),
+m("msse4.1"),
+m("msse4.2"),
+m("msse4a"),
+m("mssse3"),
 flagpd1("mstack-arg-probe"),
 flagpd1("mstackrealign"),
-flagpd1("mstrict-align"),
+m("mstrict-align"),
 flagpd1("msvr4-struct-return"),
 sepd1("mt-migrate-directory"),
-flagpd1("mtail-call"),
-flagpd1("mamx-int8"),
-flagpd1("mtbm"),
-flagpd1("mtgsplit"),
+m("mtail-call"),
+m("mamx-int8"),
+m("mtbm"),
+m("mtgsplit"),
 sepd1("mthread-model"),
 flagpd1("mthumb"),
 flagpd1("mtls-direct-seg-refs"),
 sepd1("mtp"),
-flagpd1("mtsxldtrk"),
+m("mtsxldtrk"),
 flagpd1("mtune=?"),
 flagpd1("muclibc"),
-flagpd1("muintr"),
+m("muintr"),
 flagpd1("multi_module"),
 sepd1("multiply_defined"),
 sepd1("multiply_defined_unused"),
 flagpd1("munaligned-access"),
 flagpd1("munsafe-fp-atomics"),
 flagpd1("munwind-tables"),
-flagpd1("mv5"),
-flagpd1("mv55"),
-flagpd1("mv60"),
-flagpd1("mv62"),
-flagpd1("mv65"),
-flagpd1("mv66"),
-flagpd1("mv67"),
+m("mv5"),
+m("mv55"),
+m("mv60"),
+m("mv62"),
+m("mv65"),
+m("mv66"),
+m("mv67"),
 flagpd1("mv67t"),
-flagpd1("mv68"),
-flagpd1("mvaes"),
-flagpd1("mvirt"),
-flagpd1("mvpclmulqdq"),
-flagpd1("mvsx"),
+m("mv68"),
+m("mvaes"),
+m("mvirt"),
+m("mvpclmulqdq"),
+m("mvsx"),
 flagpd1("mvx"),
-flagpd1("mvzeroupper"),
-flagpd1("mwaitpkg"),
+m("mvzeroupper"),
+m("mwaitpkg"),
 flagpd1("mwarn-nonportable-cfstrings"),
-flagpd1("mwavefrontsize64"),
-flagpd1("mwbnoinvd"),
-flagpd1("mwidekl"),
+m("mwavefrontsize64"),
+m("mwbnoinvd"),
+m("mwidekl"),
 flagpd1("mx32"),
-flagpd1("mx87"),
-flagpd1("mxgot"),
-flagpd1("mxop"),
-flagpd1("mxsave"),
-flagpd1("mxsavec"),
-flagpd1("mxsaveopt"),
-flagpd1("mxsaves"),
+m("mx87"),
+m("mxgot"),
+m("mxop"),
+m("mxsave"),
+m("mxsavec"),
+m("mxsaveopt"),
+m("mxsaves"),
 flagpd1("mzvector"),
 flagpd1("n"),
 flagpd1("new-struct-path-tbaa"),
src/main.zig
@@ -665,6 +665,12 @@ fn buildOutputType(
     var enable_link_snapshots: bool = false;
     var native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null;
 
+    // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
+    // This array is populated by zig cc frontend and then has to be converted to zig-style
+    // CPU features.
+    var llvm_m_args = std.ArrayList([]const u8).init(gpa);
+    defer llvm_m_args.deinit();
+
     var system_libs = std.StringArrayHashMap(Compilation.SystemLib).init(gpa);
     defer system_libs.deinit();
 
@@ -1412,7 +1418,9 @@ fn buildOutputType(
                     .dry_run => {
                         verbose_link = true;
                         try clang_argv.append("-###");
-                        // XXX: Don't execute anything!
+                        // This flag is supposed to mean "dry run" but currently this
+                        // will actually still execute. The tracking issue for this is
+                        // https://github.com/ziglang/zig/issues/7170
                     },
                     .for_linker => try linker_args.append(it.only_arg),
                     .linker_input_z => {
@@ -1421,6 +1429,7 @@ fn buildOutputType(
                     },
                     .lib_dir => try lib_dirs.append(it.only_arg),
                     .mcpu => target_mcpu = it.only_arg,
+                    .m => try llvm_m_args.append(it.only_arg),
                     .dep_file => {
                         disable_c_depfile = true;
                         try clang_argv.appendSlice(it.other_args);
@@ -1798,12 +1807,62 @@ fn buildOutputType(
         }
     };
 
-    const cross_target = try parseCrossTargetOrReportFatalError(arena, .{
+    var target_parse_options: std.zig.CrossTarget.ParseOptions = .{
         .arch_os_abi = target_arch_os_abi,
         .cpu_features = target_mcpu,
         .dynamic_linker = target_dynamic_linker,
-    });
+    };
+
+    // Before passing the mcpu string in for parsing, we convert any -m flags that were
+    // passed in via zig cc to zig-style.
+    if (llvm_m_args.items.len != 0) {
+        // If this returns null, we let it fall through to the case below which will
+        // run the full parse function and do proper error handling.
+        if (std.zig.CrossTarget.parseCpuArch(target_parse_options)) |cpu_arch| {
+            var llvm_to_zig_name = std.StringHashMap([]const u8).init(gpa);
+            defer llvm_to_zig_name.deinit();
+
+            for (cpu_arch.allFeaturesList()) |feature| {
+                const llvm_name = feature.llvm_name orelse continue;
+                try llvm_to_zig_name.put(llvm_name, feature.name);
+            }
 
+            var mcpu_buffer = std.ArrayList(u8).init(gpa);
+            defer mcpu_buffer.deinit();
+
+            try mcpu_buffer.appendSlice(target_mcpu orelse "baseline");
+
+            for (llvm_m_args.items) |llvm_m_arg| {
+                if (mem.startsWith(u8, llvm_m_arg, "mno-")) {
+                    const llvm_name = llvm_m_arg["mno-".len..];
+                    const zig_name = llvm_to_zig_name.get(llvm_name) orelse {
+                        fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{
+                            @tagName(cpu_arch), llvm_name,
+                        });
+                    };
+                    try mcpu_buffer.append('-');
+                    try mcpu_buffer.appendSlice(zig_name);
+                } else if (mem.startsWith(u8, llvm_m_arg, "m")) {
+                    const llvm_name = llvm_m_arg["m".len..];
+                    const zig_name = llvm_to_zig_name.get(llvm_name) orelse {
+                        fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{
+                            @tagName(cpu_arch), llvm_name,
+                        });
+                    };
+                    try mcpu_buffer.append('+');
+                    try mcpu_buffer.appendSlice(zig_name);
+                } else {
+                    unreachable;
+                }
+            }
+
+            const adjusted_target_mcpu = try arena.dupe(u8, mcpu_buffer.items);
+            std.log.debug("adjusted target_mcpu: {s}", .{adjusted_target_mcpu});
+            target_parse_options.cpu_features = adjusted_target_mcpu;
+        }
+    }
+
+    const cross_target = try parseCrossTargetOrReportFatalError(arena, target_parse_options);
     const target_info = try detectNativeTargetInfo(gpa, cross_target);
 
     if (target_info.target.os.tag != .freestanding) {
@@ -2580,7 +2639,10 @@ fn buildOutputType(
     return cleanExit();
 }
 
-fn parseCrossTargetOrReportFatalError(allocator: *Allocator, opts: std.zig.CrossTarget.ParseOptions) !std.zig.CrossTarget {
+fn parseCrossTargetOrReportFatalError(
+    allocator: *Allocator,
+    opts: std.zig.CrossTarget.ParseOptions,
+) !std.zig.CrossTarget {
     var opts_with_diags = opts;
     var diags: std.zig.CrossTarget.ParseOptions.Diagnostics = .{};
     if (opts_with_diags.diagnostics == null) {
@@ -3948,6 +4010,7 @@ pub const ClangArgIterator = struct {
         target,
         o,
         c,
+        m,
         other,
         positional,
         l,
tools/update_clang_options.zig
@@ -426,11 +426,32 @@ fn knownOption(name: []const u8) ?[]const u8 {
     return null;
 }
 
+const cpu_targets = struct {
+    pub const aarch64 = std.Target.aarch64;
+    pub const arc = std.Target.arc;
+    pub const amdgpu = std.Target.amdgpu;
+    pub const arm = std.Target.arm;
+    pub const avr = std.Target.avr;
+    pub const bpf = std.Target.bpf;
+    pub const hexagon = std.Target.hexagon;
+    pub const mips = std.Target.mips;
+    pub const msp430 = std.Target.msp430;
+    pub const nvptx = std.Target.nvptx;
+    pub const powerpc = std.Target.powerpc;
+    pub const riscv = std.Target.riscv;
+    pub const sparc = std.Target.sparc;
+    pub const spirv = std.Target.spirv;
+    pub const systemz = std.Target.systemz;
+    pub const ve = std.Target.ve;
+    pub const wasm = std.Target.wasm;
+    pub const x86 = std.Target.x86;
+};
+
 pub fn main() anyerror!void {
     var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
     defer arena.deinit();
-
     const allocator = &arena.allocator;
+
     const args = try std.process.argsAlloc(allocator);
 
     if (args.len <= 1) {
@@ -453,6 +474,20 @@ pub fn main() anyerror!void {
         usageAndExit(std.io.getStdErr(), args[0], 1);
     }
 
+    var llvm_to_zig_cpu_features = std.StringHashMap([]const u8).init(allocator);
+
+    inline for (@typeInfo(cpu_targets).Struct.decls) |decl| {
+        const Feature = @field(cpu_targets, decl.name).Feature;
+        const all_features = @field(cpu_targets, decl.name).all_features;
+
+        for (all_features) |feat, i| {
+            const llvm_name = feat.llvm_name orelse continue;
+            const zig_feat = @intToEnum(Feature, i);
+            const zig_name = @tagName(zig_feat);
+            try llvm_to_zig_cpu_features.put(llvm_name, zig_name);
+        }
+    }
+
     const child_args = [_][]const u8{
         llvm_tblgen_exe,
         "--dump-json",
@@ -467,15 +502,15 @@ pub fn main() anyerror!void {
         .max_output_bytes = 100 * 1024 * 1024,
     });
 
-    std.debug.warn("{s}\n", .{child_result.stderr});
+    std.debug.print("{s}\n", .{child_result.stderr});
 
     const json_text = switch (child_result.term) {
         .Exited => |code| if (code == 0) child_result.stdout else {
-            std.debug.warn("llvm-tblgen exited with code {d}\n", .{code});
+            std.debug.print("llvm-tblgen exited with code {d}\n", .{code});
             std.process.exit(1);
         },
         else => {
-            std.debug.warn("llvm-tblgen crashed\n", .{});
+            std.debug.print("llvm-tblgen crashed\n", .{});
             std.process.exit(1);
         },
     };
@@ -516,6 +551,7 @@ pub fn main() anyerror!void {
         \\const joinpd1 = clang_options.joinpd1;
         \\const jspd1 = clang_options.jspd1;
         \\const sepd1 = clang_options.sepd1;
+        \\const m = clang_options.m;
         \\pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{
         \\
     );
@@ -534,7 +570,7 @@ pub fn main() anyerror!void {
             } else if (std.mem.eql(u8, prefix, "/")) {
                 pslash = true;
             } else {
-                std.debug.warn("{s} has unrecognized prefix '{s}'\n", .{ name, prefix });
+                std.debug.print("{s} has unrecognized prefix '{s}'\n", .{ name, prefix });
                 std.process.exit(1);
             }
         }
@@ -562,7 +598,15 @@ pub fn main() anyerror!void {
                 \\
             , .{ name, final_syntax, ident, pd1, pd2, pslash });
         } else if (pd1 and !pd2 and !pslash and syntax == .flag) {
-            try stdout.print("flagpd1(\"{s}\"),\n", .{name});
+            if ((std.mem.startsWith(u8, name, "mno-") and
+                llvm_to_zig_cpu_features.contains(name["mno-".len..])) or
+                (std.mem.startsWith(u8, name, "m") and
+                llvm_to_zig_cpu_features.contains(name["m".len..])))
+            {
+                try stdout.print("m(\"{s}\"),\n", .{name});
+            } else {
+                try stdout.print("flagpd1(\"{s}\"),\n", .{name});
+            }
         } else if (!pd1 and !pd2 and pslash and syntax == .flag) {
             try stdout.print("flagpsl(\"{s}\"),\n", .{name});
         } else if (pd1 and !pd2 and !pslash and syntax == .joined) {
@@ -683,9 +727,9 @@ fn objSyntax(obj: *json.ObjectMap) Syntax {
         return .flag;
     }
     const key = obj.get("!name").?.String;
-    std.debug.warn("{s} (key {s}) has unrecognized superclasses:\n", .{ name, key });
+    std.debug.print("{s} (key {s}) has unrecognized superclasses:\n", .{ name, key });
     for (obj.get("!superclasses").?.Array.items) |superclass_json| {
-        std.debug.warn(" {s}\n", .{superclass_json.String});
+        std.debug.print(" {s}\n", .{superclass_json.String});
     }
     std.process.exit(1);
 }