1# 2# Copyright OpenEmbedded Contributors 3# 4# SPDX-License-Identifier: MIT 5# 6 7# Right now this is focused on arm-specific tune features. 8# We get away with this for now as one can only use x86-64 as the build host 9# (not arm). 10# Note that TUNE_FEATURES is _always_ refering to the target, so we really 11# don't want to use this for the host/build. 12def llvm_features_from_tune(d): 13 f = [] 14 feat = d.getVar('TUNE_FEATURES') 15 if not feat: 16 return [] 17 feat = frozenset(feat.split()) 18 19 mach_overrides = d.getVar('MACHINEOVERRIDES') 20 mach_overrides = frozenset(mach_overrides.split(':')) 21 22 if 'vfpv4' in feat: 23 f.append("+vfp4") 24 elif 'vfpv3' in feat: 25 f.append("+vfp3") 26 elif 'vfpv3d16' in feat: 27 f.append("+vfp3") 28 f.append("-d32") 29 elif 'vfpv2' in feat or 'vfp' in feat: 30 f.append("+vfp2") 31 32 if 'neon' in feat: 33 f.append("+neon") 34 elif target_is_armv7(d): 35 f.append("-neon") 36 37 if 'mips32' in feat: 38 f.append("+mips32") 39 40 if 'mips32r2' in feat: 41 f.append("+mips32r2") 42 43 if target_is_armv7(d): 44 f.append('+v7') 45 46 if ('armv6' in mach_overrides) or ('armv6' in feat): 47 f.append("+v6") 48 if 'armv5te' in feat: 49 f.append("+strict-align") 50 f.append("+v5te") 51 elif 'armv5' in feat: 52 f.append("+strict-align") 53 f.append("+v5") 54 55 if ('armv4' in mach_overrides) or ('armv4' in feat): 56 f.append("+strict-align") 57 58 if 'dsp' in feat: 59 f.append("+dsp") 60 61 if 'thumb' in feat: 62 if d.getVar('ARM_THUMB_OPT') == "thumb": 63 if target_is_armv7(d): 64 f.append('+thumb2') 65 f.append("+thumb-mode") 66 67 if 'cortexa5' in feat: 68 f.append("+a5") 69 if 'cortexa7' in feat: 70 f.append("+a7") 71 if 'cortexa9' in feat: 72 f.append("+a9") 73 if 'cortexa15' in feat: 74 f.append("+a15") 75 if 'cortexa17' in feat: 76 f.append("+a17") 77 if ('riscv64' in feat) or ('riscv32' in feat): 78 f.append("+a,+c,+d,+f,+m") 79 return f 80llvm_features_from_tune[vardepvalue] = "${@llvm_features_from_tune(d)}" 81 82# TARGET_CC_ARCH changes from build/cross/target so it'll do the right thing 83# this should go away when https://github.com/rust-lang/rust/pull/31709 is 84# stable (1.9.0?) 85def llvm_features_from_cc_arch(d): 86 f = [] 87 feat = d.getVar('TARGET_CC_ARCH') 88 if not feat: 89 return [] 90 feat = frozenset(feat.split()) 91 92 if '-mmmx' in feat: 93 f.append("+mmx") 94 if '-msse' in feat: 95 f.append("+sse") 96 if '-msse2' in feat: 97 f.append("+sse2") 98 if '-msse3' in feat: 99 f.append("+sse3") 100 if '-mssse3' in feat: 101 f.append("+ssse3") 102 if '-msse4.1' in feat: 103 f.append("+sse4.1") 104 if '-msse4.2' in feat: 105 f.append("+sse4.2") 106 if '-msse4a' in feat: 107 f.append("+sse4a") 108 if '-mavx' in feat: 109 f.append("+avx") 110 if '-mavx2' in feat: 111 f.append("+avx2") 112 113 return f 114 115def llvm_features_from_target_fpu(d): 116 # TARGET_FPU can be hard or soft. +soft-float tell llvm to use soft float 117 # ABI. There is no option for hard. 118 119 fpu = d.getVar('TARGET_FPU') 120 return ["+soft-float"] if fpu == "soft" else [] 121 122def llvm_features(d): 123 return ','.join(llvm_features_from_tune(d) + 124 llvm_features_from_cc_arch(d) + 125 llvm_features_from_target_fpu(d)) 126 127llvm_features[vardepvalue] = "${@llvm_features(d)}" 128 129## arm-unknown-linux-gnueabihf 130DATA_LAYOUT[arm-eabi] = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 131TARGET_ENDIAN[arm-eabi] = "little" 132TARGET_POINTER_WIDTH[arm-eabi] = "32" 133TARGET_C_INT_WIDTH[arm-eabi] = "32" 134MAX_ATOMIC_WIDTH[arm-eabi] = "64" 135FEATURES[arm-eabi] = "+v6,+vfp2" 136 137## armv7-unknown-linux-gnueabihf 138DATA_LAYOUT[armv7-eabi] = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 139TARGET_ENDIAN[armv7-eabi] = "little" 140TARGET_POINTER_WIDTH[armv7-eabi] = "32" 141TARGET_C_INT_WIDTH[armv7-eabi] = "32" 142MAX_ATOMIC_WIDTH[armv7-eabi] = "64" 143FEATURES[armv7-eabi] = "+v7,+vfp2,+thumb2" 144 145## aarch64-unknown-linux-{gnu, musl} 146DATA_LAYOUT[aarch64] = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 147TARGET_ENDIAN[aarch64] = "little" 148TARGET_POINTER_WIDTH[aarch64] = "64" 149TARGET_C_INT_WIDTH[aarch64] = "32" 150MAX_ATOMIC_WIDTH[aarch64] = "128" 151 152## x86_64-unknown-linux-{gnu, musl} 153DATA_LAYOUT[x86_64] = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 154TARGET_ENDIAN[x86_64] = "little" 155TARGET_POINTER_WIDTH[x86_64] = "64" 156TARGET_C_INT_WIDTH[x86_64] = "32" 157MAX_ATOMIC_WIDTH[x86_64] = "64" 158 159## x86_64-unknown-linux-gnux32 160DATA_LAYOUT[x86_64-x32] = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 161TARGET_ENDIAN[x86_64-x32] = "little" 162TARGET_POINTER_WIDTH[x86_64-x32] = "32" 163TARGET_C_INT_WIDTH[x86_64-x32] = "32" 164MAX_ATOMIC_WIDTH[x86_64-x32] = "64" 165 166## i686-unknown-linux-{gnu, musl} 167DATA_LAYOUT[i686] = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" 168TARGET_ENDIAN[i686] = "little" 169TARGET_POINTER_WIDTH[i686] = "32" 170TARGET_C_INT_WIDTH[i686] = "32" 171MAX_ATOMIC_WIDTH[i686] = "64" 172 173## XXX: a bit of a hack so qemux86 builds, clone of i686-unknown-linux-{gnu, musl} above 174DATA_LAYOUT[i586] = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" 175TARGET_ENDIAN[i586] = "little" 176TARGET_POINTER_WIDTH[i586] = "32" 177TARGET_C_INT_WIDTH[i586] = "32" 178MAX_ATOMIC_WIDTH[i586] = "64" 179 180## mips-unknown-linux-{gnu, musl} 181DATA_LAYOUT[mips] = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64" 182TARGET_ENDIAN[mips] = "big" 183TARGET_POINTER_WIDTH[mips] = "32" 184TARGET_C_INT_WIDTH[mips] = "32" 185MAX_ATOMIC_WIDTH[mips] = "32" 186 187## mipsel-unknown-linux-{gnu, musl} 188DATA_LAYOUT[mipsel] = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64" 189TARGET_ENDIAN[mipsel] = "little" 190TARGET_POINTER_WIDTH[mipsel] = "32" 191TARGET_C_INT_WIDTH[mipsel] = "32" 192MAX_ATOMIC_WIDTH[mipsel] = "32" 193 194## mips64-unknown-linux-{gnu, musl} 195DATA_LAYOUT[mips64] = "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128" 196TARGET_ENDIAN[mips64] = "big" 197TARGET_POINTER_WIDTH[mips64] = "64" 198TARGET_C_INT_WIDTH[mips64] = "64" 199MAX_ATOMIC_WIDTH[mips64] = "64" 200 201## mips64-n32-unknown-linux-{gnu, musl} 202DATA_LAYOUT[mips64-n32] = "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128" 203TARGET_ENDIAN[mips64-n32] = "big" 204TARGET_POINTER_WIDTH[mips64-n32] = "32" 205TARGET_C_INT_WIDTH[mips64-n32] = "32" 206MAX_ATOMIC_WIDTH[mips64-n32] = "64" 207 208## mips64el-unknown-linux-{gnu, musl} 209DATA_LAYOUT[mips64el] = "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128" 210TARGET_ENDIAN[mips64el] = "little" 211TARGET_POINTER_WIDTH[mips64el] = "64" 212TARGET_C_INT_WIDTH[mips64el] = "64" 213MAX_ATOMIC_WIDTH[mips64el] = "64" 214 215## powerpc-unknown-linux-{gnu, musl} 216DATA_LAYOUT[powerpc] = "E-m:e-p:32:32-i64:64-n32" 217TARGET_ENDIAN[powerpc] = "big" 218TARGET_POINTER_WIDTH[powerpc] = "32" 219TARGET_C_INT_WIDTH[powerpc] = "32" 220MAX_ATOMIC_WIDTH[powerpc] = "32" 221 222## powerpc64-unknown-linux-{gnu, musl} 223DATA_LAYOUT[powerpc64] = "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512" 224TARGET_ENDIAN[powerpc64] = "big" 225TARGET_POINTER_WIDTH[powerpc64] = "64" 226TARGET_C_INT_WIDTH[powerpc64] = "64" 227MAX_ATOMIC_WIDTH[powerpc64] = "64" 228 229## powerpc64le-unknown-linux-{gnu, musl} 230DATA_LAYOUT[powerpc64le] = "e-m:e-i64:64-n32:64-v256:256:256-v512:512:512" 231TARGET_ENDIAN[powerpc64le] = "little" 232TARGET_POINTER_WIDTH[powerpc64le] = "64" 233TARGET_C_INT_WIDTH[powerpc64le] = "64" 234MAX_ATOMIC_WIDTH[powerpc64le] = "64" 235 236## riscv32gc-unknown-linux-{gnu, musl} 237DATA_LAYOUT[riscv32gc] = "e-m:e-p:32:32-i64:64-n32-S128" 238TARGET_ENDIAN[riscv32gc] = "little" 239TARGET_POINTER_WIDTH[riscv32gc] = "32" 240TARGET_C_INT_WIDTH[riscv32gc] = "32" 241MAX_ATOMIC_WIDTH[riscv32gc] = "32" 242 243## riscv64gc-unknown-linux-{gnu, musl} 244DATA_LAYOUT[riscv64gc] = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" 245TARGET_ENDIAN[riscv64gc] = "little" 246TARGET_POINTER_WIDTH[riscv64gc] = "64" 247TARGET_C_INT_WIDTH[riscv64gc] = "64" 248MAX_ATOMIC_WIDTH[riscv64gc] = "64" 249 250## loongarch64-unknown-linux-{gnu, musl} 251DATA_LAYOUT[loongarch64] = "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128" 252TARGET_ENDIAN[loongarch64] = "little" 253TARGET_POINTER_WIDTH[loongarch64] = "64" 254TARGET_C_INT_WIDTH[loongarch64] = "32" 255MAX_ATOMIC_WIDTH[loongarch64] = "64" 256FEATURES[loongarch64] = "+d" 257 258# Convert a normal arch (HOST_ARCH, TARGET_ARCH, BUILD_ARCH, etc) to something 259# rust's internals won't choke on. 260def arch_to_rust_target_arch(arch): 261 if arch == "i586" or arch == "i686": 262 return "x86" 263 elif arch == "mipsel": 264 return "mips" 265 elif arch == "mip64sel": 266 return "mips64" 267 elif arch == "armv7": 268 return "arm" 269 elif arch == "powerpc64le": 270 return "powerpc64" 271 elif arch == "riscv32gc": 272 return "riscv32" 273 elif arch == "riscv64gc": 274 return "riscv64" 275 else: 276 return arch 277 278# Convert a rust target string to a llvm-compatible triplet 279def rust_sys_to_llvm_target(sys): 280 if sys.startswith('riscv32gc-'): 281 return sys.replace('riscv32gc-', 'riscv32-', 1) 282 if sys.startswith('riscv64gc-'): 283 return sys.replace('riscv64gc-', 'riscv64-', 1) 284 return sys 285 286# generates our target CPU value 287def llvm_cpu(d): 288 cpu = d.getVar('PACKAGE_ARCH') 289 target = d.getVar('TRANSLATED_TARGET_ARCH') 290 291 trans = {} 292 trans['corei7-64'] = "corei7" 293 trans['core2-32'] = "core2" 294 trans['x86-64'] = "x86-64" 295 trans['i686'] = "i686" 296 trans['i586'] = "i586" 297 trans['mips64'] = "mips64" 298 trans['mips64el'] = "mips64" 299 trans['powerpc64le'] = "ppc64le" 300 trans['powerpc64'] = "ppc64" 301 trans['riscv64'] = "generic-rv64" 302 trans['riscv32'] = "generic-rv32" 303 trans['loongarch64'] = "la464" 304 305 if target in ["mips", "mipsel", "powerpc"]: 306 feat = frozenset(d.getVar('TUNE_FEATURES').split()) 307 if "mips32r2" in feat: 308 trans['mipsel'] = "mips32r2" 309 trans['mips'] = "mips32r2" 310 elif "mips32" in feat: 311 trans['mipsel'] = "mips32" 312 trans['mips'] = "mips32" 313 elif "ppc7400" in feat: 314 trans['powerpc'] = "7400" 315 316 try: 317 return trans[cpu] 318 except: 319 return trans.get(target, "generic") 320 321llvm_cpu[vardepvalue] = "${@llvm_cpu(d)}" 322 323def rust_gen_target(d, thing, wd, arch): 324 import json 325 326 build_sys = d.getVar('BUILD_SYS') 327 target_sys = d.getVar('TARGET_SYS') 328 329 sys = d.getVar('{}_SYS'.format(thing)) 330 prefix = d.getVar('{}_PREFIX'.format(thing)) 331 rustsys = d.getVar('RUST_{}_SYS'.format(thing)) 332 333 abi = None 334 cpu = "generic" 335 features = "" 336 337 # Need to apply the target tuning consitently, only if the triplet applies to the target 338 # and not in the native case 339 if sys == target_sys and sys != build_sys: 340 abi = d.getVar('ABIEXTENSION') 341 cpu = llvm_cpu(d) 342 if bb.data.inherits_class('native', d): 343 features = ','.join(llvm_features_from_cc_arch(d)) 344 else: 345 features = llvm_features(d) or "" 346 # arm and armv7 have different targets in llvm 347 if arch == "arm" and target_is_armv7(d): 348 arch = 'armv7' 349 350 rust_arch = oe.rust.arch_to_rust_arch(arch) 351 352 if abi: 353 arch_abi = "{}-{}".format(rust_arch, abi) 354 else: 355 arch_abi = rust_arch 356 357 features = features or d.getVarFlag('FEATURES', arch_abi) or "" 358 features = features.strip() 359 360 # build tspec 361 tspec = {} 362 tspec['llvm-target'] = rust_sys_to_llvm_target(rustsys) 363 tspec['data-layout'] = d.getVarFlag('DATA_LAYOUT', arch_abi) 364 if tspec['data-layout'] is None: 365 bb.fatal("No rust target defined for %s" % arch_abi) 366 tspec['max-atomic-width'] = int(d.getVarFlag('MAX_ATOMIC_WIDTH', arch_abi)) 367 tspec['target-pointer-width'] = d.getVarFlag('TARGET_POINTER_WIDTH', arch_abi) 368 tspec['target-c-int-width'] = d.getVarFlag('TARGET_C_INT_WIDTH', arch_abi) 369 tspec['target-endian'] = d.getVarFlag('TARGET_ENDIAN', arch_abi) 370 tspec['arch'] = arch_to_rust_target_arch(rust_arch) 371 if "baremetal" in d.getVar('TCLIBC'): 372 tspec['os'] = "none" 373 else: 374 tspec['os'] = "linux" 375 if "musl" in tspec['llvm-target']: 376 tspec['env'] = "musl" 377 else: 378 tspec['env'] = "gnu" 379 if "riscv64" in tspec['llvm-target']: 380 tspec['llvm-abiname'] = "lp64d" 381 if "riscv32" in tspec['llvm-target']: 382 tspec['llvm-abiname'] = "ilp32d" 383 if "loongarch64" in tspec['llvm-target']: 384 tspec['llvm-abiname'] = "lp64d" 385 tspec['vendor'] = "unknown" 386 tspec['target-family'] = "unix" 387 tspec['linker'] = "{}{}gcc".format(d.getVar('CCACHE'), prefix) 388 tspec['cpu'] = cpu 389 if features != "": 390 tspec['features'] = features 391 tspec['dynamic-linking'] = True 392 tspec['executables'] = True 393 tspec['linker-is-gnu'] = True 394 tspec['linker-flavor'] = "gcc" 395 tspec['has-rpath'] = True 396 tspec['position-independent-executables'] = True 397 tspec['panic-strategy'] = d.getVar("RUST_PANIC_STRATEGY") 398 399 # write out the target spec json file 400 with open(wd + rustsys + '.json', 'w') as f: 401 json.dump(tspec, f, indent=4) 402 403# These are accounted for in tmpdir path names so don't need to be in the task sig 404rust_gen_target[vardepsexclude] += "ABIEXTENSION llvm_cpu" 405 406do_rust_gen_targets[vardeps] += "DATA_LAYOUT TARGET_ENDIAN TARGET_POINTER_WIDTH TARGET_C_INT_WIDTH MAX_ATOMIC_WIDTH FEATURES" 407 408RUST_TARGETS_DIR = "${WORKDIR}/rust-targets/" 409export RUST_TARGET_PATH = "${RUST_TARGETS_DIR}" 410 411python do_rust_gen_targets () { 412 wd = d.getVar('RUST_TARGETS_DIR') 413 # Order of BUILD, HOST, TARGET is important in case the files overwrite, most specific last 414 rust_gen_target(d, 'BUILD', wd, d.getVar('BUILD_ARCH')) 415 rust_gen_target(d, 'HOST', wd, d.getVar('HOST_ARCH')) 416 rust_gen_target(d, 'TARGET', wd, d.getVar('TARGET_ARCH')) 417} 418 419addtask rust_gen_targets after do_patch before do_compile 420do_rust_gen_targets[dirs] += "${RUST_TARGETS_DIR}" 421 422# For building target C dependecies use only compiler parameters defined in OE 423# and ignore the CC crate defaults which conflicts with OE ones in some cases. 424# https://github.com/rust-lang/cc-rs#external-configuration-via-environment-variables 425# Some CC crate compiler flags are still required. 426# We apply them conditionally in rust wrappers. 427 428CRATE_CC_FLAGS:class-native = "" 429CRATE_CC_FLAGS:class-nativesdk = "" 430CRATE_CC_FLAGS:class-target = " -ffunction-sections -fdata-sections -fPIC" 431 432do_compile:prepend:class-target() { 433 export CRATE_CC_NO_DEFAULTS=1 434} 435do_install:prepend:class-target() { 436 export CRATE_CC_NO_DEFAULTS=1 437} 438