1 2# Right now this is focused on arm-specific tune features. 3# We get away with this for now as one can only use x86-64 as the build host 4# (not arm). 5# Note that TUNE_FEATURES is _always_ refering to the target, so we really 6# don't want to use this for the host/build. 7def llvm_features_from_tune(d): 8 f = [] 9 feat = d.getVar('TUNE_FEATURES') 10 if not feat: 11 return [] 12 feat = frozenset(feat.split()) 13 14 mach_overrides = d.getVar('MACHINEOVERRIDES') 15 mach_overrides = frozenset(mach_overrides.split(':')) 16 17 if 'vfpv4' in feat: 18 f.append("+vfp4") 19 if 'vfpv3' in feat: 20 f.append("+vfp3") 21 if 'vfpv3d16' in feat: 22 f.append("+d16") 23 24 if 'vfpv2' in feat or 'vfp' in feat: 25 f.append("+vfp2") 26 27 if 'neon' in feat: 28 f.append("+neon") 29 30 if 'mips32' in feat: 31 f.append("+mips32") 32 33 if 'mips32r2' in feat: 34 f.append("+mips32r2") 35 36 if target_is_armv7(d): 37 f.append('+v7') 38 39 if ('armv6' in mach_overrides) or ('armv6' in feat): 40 f.append("+v6") 41 if 'armv5te' in feat: 42 f.append("+strict-align") 43 f.append("+v5te") 44 elif 'armv5' in feat: 45 f.append("+strict-align") 46 f.append("+v5") 47 48 if ('armv4' in mach_overrides) or ('armv4' in feat): 49 f.append("+strict-align") 50 51 if 'dsp' in feat: 52 f.append("+dsp") 53 54 if 'thumb' in feat: 55 if d.getVar('ARM_THUMB_OPT') == "thumb": 56 if target_is_armv7(d): 57 f.append('+thumb2') 58 f.append("+thumb-mode") 59 60 if 'cortexa5' in feat: 61 f.append("+a5") 62 if 'cortexa7' in feat: 63 f.append("+a7") 64 if 'cortexa9' in feat: 65 f.append("+a9") 66 if 'cortexa15' in feat: 67 f.append("+a15") 68 if 'cortexa17' in feat: 69 f.append("+a17") 70 if ('riscv64' in feat) or ('riscv32' in feat): 71 f.append("+a,+c,+d,+f,+m") 72 return f 73llvm_features_from_tune[vardepvalue] = "${@llvm_features_from_tune(d)}" 74 75# TARGET_CC_ARCH changes from build/cross/target so it'll do the right thing 76# this should go away when https://github.com/rust-lang/rust/pull/31709 is 77# stable (1.9.0?) 78def llvm_features_from_cc_arch(d): 79 f = [] 80 feat = d.getVar('TARGET_CC_ARCH') 81 if not feat: 82 return [] 83 feat = frozenset(feat.split()) 84 85 if '-mmmx' in feat: 86 f.append("+mmx") 87 if '-msse' in feat: 88 f.append("+sse") 89 if '-msse2' in feat: 90 f.append("+sse2") 91 if '-msse3' in feat: 92 f.append("+sse3") 93 if '-mssse3' in feat: 94 f.append("+ssse3") 95 if '-msse4.1' in feat: 96 f.append("+sse4.1") 97 if '-msse4.2' in feat: 98 f.append("+sse4.2") 99 if '-msse4a' in feat: 100 f.append("+sse4a") 101 if '-mavx' in feat: 102 f.append("+avx") 103 if '-mavx2' in feat: 104 f.append("+avx2") 105 106 return f 107 108def llvm_features_from_target_fpu(d): 109 # TARGET_FPU can be hard or soft. +soft-float tell llvm to use soft float 110 # ABI. There is no option for hard. 111 112 fpu = d.getVar('TARGET_FPU') 113 return ["+soft-float"] if fpu == "soft" else [] 114 115def llvm_features(d): 116 return ','.join(llvm_features_from_tune(d) + 117 llvm_features_from_cc_arch(d) + 118 llvm_features_from_target_fpu(d)) 119 120 121## arm-unknown-linux-gnueabihf 122DATA_LAYOUT[arm] = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 123TARGET_ENDIAN[arm] = "little" 124TARGET_POINTER_WIDTH[arm] = "32" 125TARGET_C_INT_WIDTH[arm] = "32" 126MAX_ATOMIC_WIDTH[arm] = "64" 127FEATURES[arm] = "+v6,+vfp2" 128 129## armv7-unknown-linux-gnueabihf 130DATA_LAYOUT[armv7-eabi] = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 131TARGET_ENDIAN[armv7-eabi] = "little" 132TARGET_POINTER_WIDTH[armv7-eabi] = "32" 133TARGET_C_INT_WIDTH[armv7-eabi] = "32" 134MAX_ATOMIC_WIDTH[armv7-eabi] = "64" 135FEATURES[armv7-eabi] = "+v7,+vfp2,+thumb2" 136 137## aarch64-unknown-linux-{gnu, musl} 138DATA_LAYOUT[aarch64] = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 139TARGET_ENDIAN[aarch64] = "little" 140TARGET_POINTER_WIDTH[aarch64] = "64" 141TARGET_C_INT_WIDTH[aarch64] = "32" 142MAX_ATOMIC_WIDTH[aarch64] = "128" 143 144## x86_64-unknown-linux-{gnu, musl} 145DATA_LAYOUT[x86_64] = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 146TARGET_ENDIAN[x86_64] = "little" 147TARGET_POINTER_WIDTH[x86_64] = "64" 148TARGET_C_INT_WIDTH[x86_64] = "32" 149MAX_ATOMIC_WIDTH[x86_64] = "64" 150 151## x86_64-unknown-linux-gnux32 152DATA_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" 153TARGET_ENDIAN[x86_64-x32] = "little" 154TARGET_POINTER_WIDTH[x86_64-x32] = "32" 155TARGET_C_INT_WIDTH[x86_64-x32] = "32" 156MAX_ATOMIC_WIDTH[x86_64-x32] = "64" 157 158## i686-unknown-linux-{gnu, musl} 159DATA_LAYOUT[i686] = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" 160TARGET_ENDIAN[i686] = "little" 161TARGET_POINTER_WIDTH[i686] = "32" 162TARGET_C_INT_WIDTH[i686] = "32" 163MAX_ATOMIC_WIDTH[i686] = "64" 164 165## XXX: a bit of a hack so qemux86 builds, clone of i686-unknown-linux-{gnu, musl} above 166DATA_LAYOUT[i586] = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" 167TARGET_ENDIAN[i586] = "little" 168TARGET_POINTER_WIDTH[i586] = "32" 169TARGET_C_INT_WIDTH[i586] = "32" 170MAX_ATOMIC_WIDTH[i586] = "64" 171 172## mips-unknown-linux-{gnu, musl} 173DATA_LAYOUT[mips] = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64" 174TARGET_ENDIAN[mips] = "big" 175TARGET_POINTER_WIDTH[mips] = "32" 176TARGET_C_INT_WIDTH[mips] = "32" 177MAX_ATOMIC_WIDTH[mips] = "32" 178 179## mipsel-unknown-linux-{gnu, musl} 180DATA_LAYOUT[mipsel] = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64" 181TARGET_ENDIAN[mipsel] = "little" 182TARGET_POINTER_WIDTH[mipsel] = "32" 183TARGET_C_INT_WIDTH[mipsel] = "32" 184MAX_ATOMIC_WIDTH[mipsel] = "32" 185 186## mips64-unknown-linux-{gnu, musl} 187DATA_LAYOUT[mips64] = "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128" 188TARGET_ENDIAN[mips64] = "big" 189TARGET_POINTER_WIDTH[mips64] = "64" 190TARGET_C_INT_WIDTH[mips64] = "64" 191MAX_ATOMIC_WIDTH[mips64] = "64" 192 193## mips64el-unknown-linux-{gnu, musl} 194DATA_LAYOUT[mips64el] = "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128" 195TARGET_ENDIAN[mips64el] = "little" 196TARGET_POINTER_WIDTH[mips64el] = "64" 197TARGET_C_INT_WIDTH[mips64el] = "64" 198MAX_ATOMIC_WIDTH[mips64el] = "64" 199 200## powerpc-unknown-linux-{gnu, musl} 201DATA_LAYOUT[powerpc] = "E-m:e-p:32:32-i64:64-n32" 202TARGET_ENDIAN[powerpc] = "big" 203TARGET_POINTER_WIDTH[powerpc] = "32" 204TARGET_C_INT_WIDTH[powerpc] = "32" 205MAX_ATOMIC_WIDTH[powerpc] = "32" 206 207## powerpc64-unknown-linux-{gnu, musl} 208DATA_LAYOUT[powerpc64] = "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512" 209TARGET_ENDIAN[powerpc64] = "big" 210TARGET_POINTER_WIDTH[powerpc64] = "64" 211TARGET_C_INT_WIDTH[powerpc64] = "64" 212MAX_ATOMIC_WIDTH[powerpc64] = "64" 213 214## powerpc64le-unknown-linux-{gnu, musl} 215DATA_LAYOUT[powerpc64le] = "e-m:e-i64:64-n32:64-v256:256:256-v512:512:512" 216TARGET_ENDIAN[powerpc64le] = "little" 217TARGET_POINTER_WIDTH[powerpc64le] = "64" 218TARGET_C_INT_WIDTH[powerpc64le] = "64" 219MAX_ATOMIC_WIDTH[powerpc64le] = "64" 220 221## riscv32-unknown-linux-{gnu, musl} 222DATA_LAYOUT[riscv32] = "e-m:e-p:32:32-i64:64-n32-S128" 223TARGET_ENDIAN[riscv32] = "little" 224TARGET_POINTER_WIDTH[riscv32] = "32" 225TARGET_C_INT_WIDTH[riscv32] = "32" 226MAX_ATOMIC_WIDTH[riscv32] = "32" 227 228## riscv64-unknown-linux-{gnu, musl} 229DATA_LAYOUT[riscv64] = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" 230TARGET_ENDIAN[riscv64] = "little" 231TARGET_POINTER_WIDTH[riscv64] = "64" 232TARGET_C_INT_WIDTH[riscv64] = "64" 233MAX_ATOMIC_WIDTH[riscv64] = "64" 234 235def sys_for(d, thing): 236 return d.getVar('{}_SYS'.format(thing)) 237 238def prefix_for(d, thing): 239 return d.getVar('{}_PREFIX'.format(thing)) 240 241# Convert a normal arch (HOST_ARCH, TARGET_ARCH, BUILD_ARCH, etc) to something 242# rust's internals won't choke on. 243def arch_to_rust_target_arch(arch): 244 if arch == "i586" or arch == "i686": 245 return "x86" 246 elif arch == "mipsel": 247 return "mips" 248 elif arch == "mip64sel": 249 return "mips64" 250 elif arch == "armv7": 251 return "arm" 252 elif arch == "powerpc64le": 253 return "powerpc64" 254 else: 255 return arch 256 257# generates our target CPU value 258def llvm_cpu(d): 259 cpu = d.getVar('PACKAGE_ARCH') 260 target = d.getVar('TRANSLATED_TARGET_ARCH') 261 262 trans = {} 263 trans['corei7-64'] = "corei7" 264 trans['core2-32'] = "core2" 265 trans['x86-64'] = "x86-64" 266 trans['i686'] = "i686" 267 trans['i586'] = "i586" 268 trans['powerpc'] = "powerpc" 269 trans['mips64'] = "mips64" 270 trans['mips64el'] = "mips64" 271 trans['riscv64'] = "generic-rv64" 272 trans['riscv32'] = "generic-rv32" 273 274 if target in ["mips", "mipsel"]: 275 feat = frozenset(d.getVar('TUNE_FEATURES').split()) 276 if "mips32r2" in feat: 277 trans['mipsel'] = "mips32r2" 278 trans['mips'] = "mips32r2" 279 elif "mips32" in feat: 280 trans['mipsel'] = "mips32" 281 trans['mips'] = "mips32" 282 283 try: 284 return trans[cpu] 285 except: 286 return trans.get(target, "generic") 287 288TARGET_LLVM_CPU="${@llvm_cpu(d)}" 289TARGET_LLVM_FEATURES = "${@llvm_features(d)}" 290 291# class-native implies TARGET=HOST, and TUNE_FEATURES only describes the real 292# (original) target. 293TARGET_LLVM_FEATURES:class-native = "${@','.join(llvm_features_from_cc_arch(d))}" 294 295def rust_gen_target(d, thing, wd, features, cpu, arch, abi=""): 296 import json 297 sys = sys_for(d, thing) 298 prefix = prefix_for(d, thing) 299 300 rust_arch = oe.rust.arch_to_rust_arch(arch) 301 302 if abi: 303 arch_abi = "{}-{}".format(rust_arch, abi) 304 else: 305 arch_abi = rust_arch 306 307 features = features or d.getVarFlag('FEATURES', arch_abi) or "" 308 features = features.strip() 309 310 # build tspec 311 tspec = {} 312 tspec['llvm-target'] = d.getVar('RUST_TARGET_SYS', arch_abi) 313 tspec['data-layout'] = d.getVarFlag('DATA_LAYOUT', arch_abi) 314 tspec['max-atomic-width'] = int(d.getVarFlag('MAX_ATOMIC_WIDTH', arch_abi)) 315 tspec['target-pointer-width'] = d.getVarFlag('TARGET_POINTER_WIDTH', arch_abi) 316 tspec['target-c-int-width'] = d.getVarFlag('TARGET_C_INT_WIDTH', arch_abi) 317 tspec['target-endian'] = d.getVarFlag('TARGET_ENDIAN', arch_abi) 318 tspec['arch'] = arch_to_rust_target_arch(rust_arch) 319 tspec['os'] = "linux" 320 if "musl" in tspec['llvm-target']: 321 tspec['env'] = "musl" 322 else: 323 tspec['env'] = "gnu" 324 if "riscv64" in tspec['llvm-target']: 325 tspec['llvm-abiname'] = "lp64d" 326 if "riscv32" in tspec['llvm-target']: 327 tspec['llvm-abiname'] = "ilp32d" 328 tspec['vendor'] = "unknown" 329 tspec['target-family'] = "unix" 330 tspec['linker'] = "{}{}gcc".format(d.getVar('CCACHE'), prefix) 331 tspec['cpu'] = cpu 332 if features != "": 333 tspec['features'] = features 334 tspec['dynamic-linking'] = True 335 tspec['executables'] = True 336 tspec['linker-is-gnu'] = True 337 tspec['linker-flavor'] = "gcc" 338 tspec['has-rpath'] = True 339 tspec['has-elf-tls'] = True 340 tspec['position-independent-executables'] = True 341 tspec['panic-strategy'] = d.getVar("RUST_PANIC_STRATEGY") 342 343 # write out the target spec json file 344 with open(wd + sys + '.json', 'w') as f: 345 json.dump(tspec, f, indent=4) 346 347# These are accounted for in tmpdir path names so don't need to be in the task sig 348rust_gen_target[vardepsexclude] += "RUST_HOST_SYS RUST_TARGET_SYS" 349 350do_rust_gen_targets[vardeps] += "DATA_LAYOUT TARGET_ENDIAN TARGET_POINTER_WIDTH TARGET_C_INT_WIDTH MAX_ATOMIC_WIDTH FEATURES" 351 352python do_rust_gen_targets () { 353 wd = d.getVar('WORKDIR') + '/targets/' 354 build_arch = d.getVar('BUILD_ARCH') 355 rust_gen_target(d, 'BUILD', wd, "", "generic", build_arch) 356} 357 358addtask rust_gen_targets after do_patch before do_compile 359do_rust_gen_targets[dirs] += "${WORKDIR}/targets" 360 361