Auto merge of #28079 - huonw:simd, r=alexcrichton

This adds a new Python script (compatible with 2.7 and 3.x) that will consume some JSON files that define a platform's intrinsics. It can output a file that defines the intrinsics in the compiler, or an `extern` block that will import them.

The complexity of the generator is to be DRY: platforms (especially ARM and AArch64) have a lot of repetition with their intrinsics, for different versions with different types, so being able to write it once is nice.
This commit is contained in:
bors 2015-08-31 21:34:08 +00:00
commit 2d3e8379c8
19 changed files with 8173 additions and 610 deletions

View File

@ -0,0 +1,550 @@
{
"platform": "aarch64",
"intrinsic_prefix": "aarch64_v",
"llvm_prefix": "llvm.aarch64.neon.",
"number_info": {
"signed": {
"kind": "s",
"data_type": { "pattern": "s{bitwidth}" }
},
"unsigned": {
"kind": "u",
"data_type": { "pattern": "u{bitwidth}" }
},
"float": {
"kind": "f",
"data_type": { "pattern": "f{bitwidth}" }
}
},
"width_info": {
"64": { "width": "" },
"128": { "width": "q" }
},
"intrinsics": [
{
"intrinsic": "hadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}hadd.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "rhadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}rhadd.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}qadd.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "uqadd_{0.data_type}",
"width": [128],
"llvm": "suqadd.{0.llvm_name}",
"ret": "s(8-64)",
"args": ["0", "0u"]
},
{
"intrinsic": "sqadd_{0.data_type}",
"width": [128],
"llvm": "usqadd.{0.llvm_name}",
"ret": "u(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "raddhn_{1.data_type}",
"width": [64],
"llvm": "raddhn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "0w"]
},
{
"intrinsic": "fmulx{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "fmulx.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "fma{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.fma.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "qdmulh{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqdmulh.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qrdmulh{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqrdmulh.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "mull_{1.data_type}",
"width": [128],
"llvm": "{0.kind}mull.{0.llvm_name}",
"ret": "i(16-64)",
"args": ["0n", "0n"]
},
{
"intrinsic": "qdmull{0.width}_{1.data_type}",
"width": [128],
"llvm": "sqdmull.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0n", "0n"]
},
{
"intrinsic": "hsub{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "{0.kind}hsub.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qsub{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "{0.kind}qsub.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "rsubhn_{1.data_type}",
"width": [64],
"llvm": "rsubhn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "0w"]
},
{
"intrinsic": "abd{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "{0.kind}abd.{0.llvm_name}",
"ret": ["i(8-32)","f(32-64)"],
"args": ["0", "0"]
},
{
"intrinsic": "max{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}max.{0.llvm_name}",
"ret": ["i(8-32)","f(32-64)"],
"args": ["0", "0"]
},
{
"intrinsic": "min{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}min.{0.llvm_name}",
"ret": ["i(8-32)","f(32-64)"],
"args": ["0", "0"]
},
{
"intrinsic": "maxnm{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxnm.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "minnm{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minnm.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "shl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}shl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}qshl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "rshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}rshl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qrshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}qrshl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qshrun_n_{1.data_type}",
"width": [64],
"llvm": "sqshrun.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qrshrun_n_{1.data_type}",
"width": [64],
"llvm": "sqrshrun.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qshrn_n_{1.data_type}",
"width": [64],
"llvm": "{0.kind}qshrn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "rshrn_n_{1.data_type}",
"width": [64],
"llvm": "rshrn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qrshrn_n_{1.data_type}",
"width": [64],
"llvm": "{0.kind}qrshrn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "sri{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "vsri.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "sli{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "vsli.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "vqmovn_{1.data_type}",
"width": [64],
"llvm": "{0.kind}qxtn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w"]
},
{
"intrinsic": "abs{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "abs.{0.llvm_name}",
"ret": "s(8-64)",
"args": ["0"]
},
{
"intrinsic": "abs{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.fabs.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0"]
},
{
"intrinsic": "qabs{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "sqabs.{0.llvm_name}",
"ret": "s(8-64)",
"args": ["0"]
},
{
"intrinsic": "qneg{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqneg.{0.llvm_name}",
"ret": "s(8-64)",
"args": ["0"]
},
{
"intrinsic": "clz{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.ctlz.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0"]
},
{
"intrinsic": "cls{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "cls.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0"]
},
{
"intrinsic": "cnt{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.ctpop.{0.llvm_name}",
"ret": "i8",
"args": ["0"]
},
{
"intrinsic": "recpe{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}recpe.{0.llvm_name}",
"ret": ["u32","f(32-64)"],
"args": ["0"]
},
{
"intrinsic": "recps{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "frecps.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "sqrt{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.sqrt.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0"]
},
{
"intrinsic": "rsqrte{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}rsqrte.{0.llvm_name}",
"ret": ["u32","f(32-64)"],
"args": ["0"]
},
{
"intrinsic": "rsqrts{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "frsqrts.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "rbit{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "rbit.{0.llvm_name}",
"ret": "i8",
"args": ["0"]
},
{
"intrinsic": "padd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "addp.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "padd{0.width}_{0.data_type}",
"width": [128],
"llvm": "addp.{0.llvm_name}",
"ret": ["i64","f64"],
"args": ["0", "0"]
},
{
"intrinsic": "paddl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}addlp.{0.llvm_name}.{1.llvm_name}",
"ret": "i(16-64)",
"args": ["0dn"]
},
{
"intrinsic": "pmax{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxp.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "pmax{0.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}maxp.{0.llvm_name}",
"ret": ["i64","f64"],
"args": ["0", "0"]
},
{
"intrinsic": "pmin{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minp.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "pmin{0.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}minp.{0.llvm_name}",
"ret": ["i64","f64"],
"args": ["0", "0"]
},
{
"intrinsic": "pmaxnm{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxnmp.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "pmaxnm{0.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}maxnmp.{0.llvm_name}",
"ret": ["i64","f64"],
"args": ["0", "0"]
},
{
"intrinsic": "pminnm{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minnmp.{0.llvm_name}",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "pminnm{0.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}minnmp.{0.llvm_name}",
"ret": "f64",
"args": ["0", "0"]
},
{
"intrinsic": "addv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}addv.{0.llvm_name}.{1.llvm_name}",
"ret": ["I(8-32)","F32"],
"args": ["0v"]
},
{
"intrinsic": "addv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}addv.{0.llvm_name}.{1.llvm_name}",
"ret": ["I64","F64"],
"args": ["0v"]
},
{
"intrinsic": "addlv{1.width}_{1.data_type}",
"width": [64, 128],
"llvm": "{0.kind}addlv.{0.llvm_name}.{1.llvm_name}",
"ret": "I(16-64)",
"args": ["0vdn"]
},
{
"intrinsic": "maxv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxv.{0.llvm_name}.{1.llvm_name}",
"ret": ["I(8-32)","F32"],
"args": ["0v"]
},
{
"intrinsic": "maxv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}maxv.{0.llvm_name}.{1.llvm_name}",
"ret": "F64",
"args": ["0v"]
},
{
"intrinsic": "minv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minv.{0.llvm_name}.{1.llvm_name}",
"ret": ["I(8-32)","F32"],
"args": ["0v"]
},
{
"intrinsic": "minv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}minv.{0.llvm_name}.{1.llvm_name}",
"ret": "F64",
"args": ["0v"]
},
{
"intrinsic": "maxnmv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxnmv.{0.llvm_name}.{1.llvm_name}",
"ret": "F32",
"args": ["0v"]
},
{
"intrinsic": "maxnmv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}maxnmv.{0.llvm_name}.{1.llvm_name}",
"ret": "F64",
"args": ["0v"]
},
{
"intrinsic": "minnmv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minnmv.{0.llvm_name}.{1.llvm_name}",
"ret": "F32",
"args": ["0v"]
},
{
"intrinsic": "minnmv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}minnmv.{0.llvm_name}.{1.llvm_name}",
"ret": "F64",
"args": ["0v"]
},
{
"intrinsic": "qtbl1{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbl1.{0.llvm_name}",
"ret": "i8",
"args": ["0x128", "0u"]
},
{
"intrinsic": "qtbx1{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbx1.{0.llvm_name}",
"ret": "i8",
"args": ["0", "0x128", "0u"]
},
{
"intrinsic": "qtbl2{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbl2.{0.llvm_name}",
"ret": "i8",
"args": ["(0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbx2{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbx2.{0.llvm_name}",
"ret": "i8",
"args": ["(0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbl3{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbl3.{0.llvm_name}",
"ret": "i8",
"args": ["(0x128,0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbx3{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbx3.{0.llvm_name}",
"ret": "i8",
"args": ["0", "(0x128,0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbl4{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbl4.{0.llvm_name}",
"ret": "i8",
"args": ["(0x128,0x128,0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbx4{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbx4.{0.llvm_name}",
"ret": "i8",
"args": ["0", "(0x128,0x128,0x128,0x128)f", "0u"]
}
]
}

View File

@ -0,0 +1,396 @@
{
"platform": "arm",
"intrinsic_prefix": "arm_v",
"llvm_prefix": "llvm.neon.v",
"number_info": {
"signed": {
"kind": "s",
"data_type": { "pattern": "s{bitwidth}" }
},
"unsigned": {
"kind": "u",
"data_type": { "pattern": "u{bitwidth}" }
},
"float": {
"kind": "f",
"data_type": { "pattern": "f{bitwidth}" }
}
},
"width_info": {
"64": { "width": "" },
"128": { "width": "q" }
},
"intrinsics": [
{
"intrinsic": "hadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "hadd{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "rhadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "rhadd{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "qadd{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "raddhn_{1.data_type}",
"width": [64],
"llvm": "raddhn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "0w"]
},
{
"intrinsic": "fma{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.fma.{0.llvm_name}",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "qdmulh{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqdmulh.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qrdmulh{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqrdmulh.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "mull_{1.data_type}",
"width": [128],
"llvm": "mull{0.kind}.{0.llvm_name}",
"ret": "i(16-64)",
"args": ["0n", "0n"]
},
{
"intrinsic": "qdmull{0.width}_{1.data_type}",
"width": [128],
"llvm": "sqdmull.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0n", "0n"]
},
{
"intrinsic": "hsub{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "hsub{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qsub{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "qsub{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "rsubhn_{1.data_type}",
"width": [64],
"llvm": "rsubhn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "0w"]
},
{
"intrinsic": "abd{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "abd{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "max{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "max{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "min{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "min{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "shl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "shl{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "qshl{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "rshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "rshl{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qrshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "qrshl{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qshrun_n_{1.data_type}",
"width": [64],
"llvm": "sqshrun.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qrshrun_n_{1.data_type}",
"width": [64],
"llvm": "sqrshrun.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qshrn_n_{1.data_type}",
"width": [64],
"llvm": "qshrn{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "rshrn_n_{1.data_type}",
"width": [64],
"llvm": "rshrn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qrshrn_n_{1.data_type}",
"width": [64],
"llvm": "qrshrn{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "sri{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "vsri.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "sli{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "vsli.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "vqmovn_{1.data_type}",
"width": [64],
"llvm": "qxtn{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w"]
},
{
"intrinsic": "abs{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "abs.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0"]
},
{
"intrinsic": "abs{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.fabs.{0.llvm_name}",
"ret": "f32",
"args": ["0"]
},
{
"intrinsic": "qabs{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "sqabs.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0"]
},
{
"intrinsic": "qneg{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqneg.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0"]
},
{
"intrinsic": "clz{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.ctlz.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0"]
},
{
"intrinsic": "cls{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "cls.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0"]
},
{
"intrinsic": "cnt{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.ctpop.{0.llvm_name}",
"ret": "i8",
"args": ["0"]
},
{
"intrinsic": "recpe{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "recpe.{0.llvm_name}",
"ret": ["u32","f32"],
"args": ["0"]
},
{
"intrinsic": "recps{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "frecps.{0.llvm_name}",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "sqrt{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.sqrt.{0.llvm_name}",
"ret": "f32",
"args": ["0"]
},
{
"intrinsic": "rsqrte{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "rsqrte.{0.llvm_name}",
"ret": ["u32","f32"],
"args": ["0"]
},
{
"intrinsic": "rsqrts{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "rsqrts.{0.llvm_name}",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "bsl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "bsl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0u", "0"]
},
{
"intrinsic": "padd{0.width}_{0.data_type}",
"width": [64],
"llvm": "padd.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "paddl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "paddl{0.kind}.{0.llvm_name}.{1.llvm_name}",
"ret": "i(16-64)",
"args": ["0dn"]
},
{
"intrinsic": "padal{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "padal{0.kind}.{0.llvm_name}.{1.llvm_name}",
"ret": "i(16-64)",
"args": ["0", "0dn"]
},
{
"intrinsic": "pmax{0.width}_{0.data_type}",
"width": [64],
"llvm": "pmax{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "pmin{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "pmin{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "tbl1_{0.data_type}",
"width": [64],
"llvm": "tbl1",
"ret": "i8",
"args": ["0", "0u"]
},
{
"intrinsic": "tbx1_{0.data_type}",
"width": [64],
"llvm": "tbx1",
"ret": "i8",
"args": ["0", "0", "0u"]
},
{
"intrinsic": "tbl2_{0.data_type}",
"width": [64],
"llvm": "tbl2",
"ret": "i8",
"args": ["(0,0)f", "0u"]
},
{
"intrinsic": "tbx2_{0.data_type}",
"width": [64],
"llvm": "tbx2",
"ret": "i8",
"args": ["(0,0)f", "0u"]
},
{
"intrinsic": "tbl3_{0.data_type}",
"width": [64],
"llvm": "tbl3",
"ret": "i8",
"args": ["(0,0,0)f", "0u"]
},
{
"intrinsic": "tbx3_{0.data_type}",
"width": [64],
"llvm": "tbx3",
"ret": "i8",
"args": ["0", "(0,0,0)f", "0u"]
},
{
"intrinsic": "tbl4_{0.data_type}",
"width": [64],
"llvm": "tbl4",
"ret": "i8",
"args": ["(0,0,0,0)f", "0u"]
},
{
"intrinsic": "tbx4_{0.data_type}",
"width": [64],
"llvm": "tbx4",
"ret": "i8",
"args": ["0", "(0,0,0,0)f", "0u"]
}
]
}

View File

@ -0,0 +1,571 @@
# Copyright 2015 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
from __future__ import division, print_function
import json
import argparse
import sys
import re
import textwrap
SPEC = re.compile(
r'^(?:(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
r'(?P<width>\d+)(:?/(?P<llvm_width>\d+))?)'
r'|(?P<reference>\d+)(?P<modifiers>[vShdnwus]*)(?P<force_width>x\d+)?)$'
)
class PlatformInfo(object):
def __init__(self, json):
self._platform = json['platform']
self._intrinsic_prefix = json['intrinsic_prefix']
def intrinsic_prefix(self):
return self._intrinsic_prefix
class IntrinsicSet(object):
def __init__(self, platform, json):
self._llvm_prefix = json['llvm_prefix']
self._type_info = json['number_info']
self._intrinsics = json['intrinsics']
self._widths = json['width_info']
self._platform = platform
def intrinsics(self):
for raw in self._intrinsics:
yield GenericIntrinsic(self,
raw['intrinsic'], raw['width'], raw['llvm'],
raw['ret'], raw['args'])
def platform(self):
return self._platform
def llvm_prefix(self):
return self._llvm_prefix
def width_info(self, bitwidth):
return self._widths[str(bitwidth)]
def number_type_info(self, value):
data = self._type_info[value.__class__.__name__.lower()]
bitwidth = value.bitwidth()
def lookup(raw):
if not isinstance(raw, dict):
return raw
try:
return raw[str(bitwidth)]
except KeyError:
return raw['pattern'].format(bitwidth = bitwidth)
return PlatformTypeInfo(value.llvm_name(),
{k: lookup(v) for k, v in data.items()})
class PlatformTypeInfo(object):
def __init__(self, llvm_name, properties):
self.properties = properties
self.llvm_name = llvm_name
def __getattr__(self, name):
return self.properties[name]
def vectorize(self, length, width_info):
props = self.properties.copy()
props.update(width_info)
return PlatformTypeInfo('v{}{}'.format(length, self.llvm_name), props)
class Type(object):
def __init__(self, bitwidth):
self._bitwidth = bitwidth
def bitwidth(self):
return self._bitwidth
def modify(self, spec, width):
raise NotImplementedError()
class Number(Type):
def __init__(self, bitwidth):
Type.__init__(self, bitwidth)
def modify(self, spec, width):
if spec == 'u':
return Unsigned(self.bitwidth())
elif spec == 's':
return Signed(self.bitwidth())
elif spec == 'w':
return self.__class__(self.bitwidth() * 2)
elif spec == 'n':
return self.__class__(self.bitwidth() // 2)
elif spec == 'v':
return Vector(self, width // self.bitwidth())
else:
raise ValueError('unknown modification spec {}', spec)
def type_info(self, platform_info):
return platform_info.number_type_info(self)
class Signed(Number):
def __init__(self, bitwidth, llvm_bitwidth = None):
Number.__init__(self, bitwidth)
self._llvm_bitwidth = llvm_bitwidth
def compiler_ctor(self):
if self._llvm_bitwidth is None:
return 'i({})'.format(self.bitwidth())
else:
return 'i_({}, {})'.format(self.bitwidth(),
self._llvm_bitwidth)
def llvm_name(self):
bw = self._llvm_bitwidth or self.bitwidth()
return 'i{}'.format(bw)
def rust_name(self):
return 'i{}'.format(self.bitwidth())
class Unsigned(Number):
def __init__(self, bitwidth, llvm_bitwidth = None):
Number.__init__(self, bitwidth)
self._llvm_bitwidth = llvm_bitwidth
def compiler_ctor(self):
if self._llvm_bitwidth is None:
return 'u({})'.format(self.bitwidth())
else:
return 'u_({}, {})'.format(self.bitwidth(),
self._llvm_bitwidth)
def llvm_name(self):
bw = self._llvm_bitwidth or self.bitwidth()
return 'i{}'.format(bw)
def rust_name(self):
return 'u{}'.format(self.bitwidth())
class Float(Number):
def __init__(self, bitwidth):
assert bitwidth in (32, 64)
Number.__init__(self, bitwidth)
def compiler_ctor(self):
return 'f({})'.format(self.bitwidth())
def llvm_name(self):
return 'f{}'.format(self.bitwidth())
def rust_name(self):
return 'f{}'.format(self.bitwidth())
class Vector(Type):
def __init__(self, elem, length):
assert isinstance(elem, Type) and not isinstance(elem, Vector)
Type.__init__(self,
elem.bitwidth() * length)
self._length = length
self._elem = elem
def modify(self, spec, width):
if spec == 'h':
return Vector(self._elem, self._length // 2)
elif spec == 'd':
return Vector(self._elem, self._length * 2)
elif spec.startswith('x'):
new_bitwidth = int(spec[1:])
return Vector(self._elem, new_bitwidth // self._elem.bitwidth())
else:
return Vector(self._elem.modify(spec, width), self._length)
def compiler_ctor(self):
return 'v({}, {})'.format(self._elem.compiler_ctor(), self._length)
def rust_name(self):
return '{}x{}'.format(self._elem.rust_name(), self._length)
def type_info(self, platform_info):
elem_info = self._elem.type_info(platform_info)
return elem_info.vectorize(self._length,
platform_info.width_info(self.bitwidth()))
class Aggregate(Type):
def __init__(self, flatten, elems):
self._flatten = flatten
self._elems = elems
Type.__init__(self, sum(elem.bitwidth() for elem in elems))
def __repr__(self):
return '<Aggregate {}>'.format(self._elems)
def compiler_ctor(self):
return 'agg({}, vec![{}])'.format('true' if self._flatten else 'false',
', '.join(elem.compiler_ctor() for elem in self._elems))
def rust_name(self):
return '({})'.format(', '.join(elem.rust_name() for elem in self._elems))
def type_info(self, platform_info):
#return PlatformTypeInfo(None, None, self._llvm_name)
return None
TYPE_ID_LOOKUP = {'i': [Signed, Unsigned],
's': [Signed],
'u': [Unsigned],
'f': [Float]}
class TypeSpec(object):
def __init__(self, spec):
if not isinstance(spec, list):
spec = [spec]
self.spec = spec
def enumerate(self, width):
for spec in self.spec:
match = SPEC.match(spec)
if match:
id = match.group('id')
is_vector = id.islower()
type_ctors = TYPE_ID_LOOKUP[id.lower()]
start = match.group('start')
if start is not None:
end = match.group('end')
llvm_width = None
else:
start = end = match.group('width')
llvm_width = match.group('llvm_width')
start = int(start)
end = int(end)
bitwidth = start
while bitwidth <= end:
for ctor in type_ctors:
if llvm_width is not None:
assert not is_vector
llvm_width = int(llvm_width)
assert llvm_width < bitwidth
scalar = ctor(bitwidth, llvm_width)
else:
scalar = ctor(bitwidth)
if is_vector:
yield Vector(scalar, width // bitwidth)
else:
yield scalar
bitwidth *= 2
else:
print('Failed to parse: `{}`'.format(spec), file=sys.stderr)
def resolve(self, width, zero):
assert len(self.spec) == 1
spec = self.spec[0]
match = SPEC.match(spec)
if match:
id = match.group('id')
if id is not None:
options = list(self.enumerate(width))
assert len(options) == 1
return options[0]
reference = match.group('reference')
if reference != '0':
raise NotImplementedError('only argument 0 (return value) references are supported')
ret = zero
for x in match.group('modifiers') or []:
ret = ret.modify(x, width)
force = match.group('force_width')
if force is not None:
ret = ret.modify(force, width)
return ret
elif spec.startswith('('):
if spec.endswith(')'):
raise NotImplementedError()
elif spec.endswith(')f'):
true_spec = spec[1:-2]
flatten = True
elems = [TypeSpec(subspec).resolve(width, zero) for subspec in true_spec.split(',')]
return Aggregate(flatten, elems)
class GenericIntrinsic(object):
def __init__(self, platform, intrinsic, widths, llvm_name, ret, args):
self._platform = platform
self.intrinsic = intrinsic
self.widths = map(int, widths)
self.llvm_name = llvm_name
self.ret = TypeSpec(ret)
self.args = list(map(TypeSpec, args))
def monomorphise(self):
for width in self.widths:
# must be a power of two
assert width & (width - 1) == 0
for ret in self.ret.enumerate(width):
args = [arg.resolve(width, ret) for arg in self.args]
yield MonomorphicIntrinsic(self._platform, self.intrinsic, width, self.llvm_name,
ret, args)
class MonomorphicIntrinsic(object):
def __init__(self, platform, intrinsic, width, llvm_name, ret, args):
self._platform = platform
self._intrinsic = intrinsic
self._width = '' if width == 64 else 'q'
self._llvm_name = llvm_name
self._ret_raw = ret
self._ret = ret.type_info(platform)
self._args_raw = args
self._args = [arg.type_info(platform) for arg in args]
def llvm_name(self):
if self._llvm_name.startswith('!'):
return self._llvm_name[1:].format(self._ret, *self._args)
else:
return self._platform.llvm_prefix() + self._llvm_name.format(self._ret, *self._args)
def intrinsic_suffix(self):
return self._intrinsic.format(self._ret,
*self._args,
width = self._width)
def intrinsic_name(self):
return self._platform.platform().intrinsic_prefix() + self.intrinsic_suffix()
def compiler_args(self):
return ', '.join(arg.compiler_ctor() for arg in self._args_raw)
def compiler_ret(self):
return self._ret_raw.compiler_ctor()
def compiler_signature(self):
return '({}) -> {}'.format(self.compiler_args(), self.compiler_ret())
def intrinsic_signature(self):
names = 'xyzwabcdef'
return '({}) -> {}'.format(', '.join('{}: {}'.format(name, arg.rust_name())
for name, arg in zip(names, self._args_raw)),
self._ret_raw.rust_name())
def parse_args():
parser = argparse.ArgumentParser(
formatter_class = argparse.RawDescriptionHelpFormatter,
description = 'Render an intrinsic definition JSON to various formats.',
epilog = textwrap.dedent('''\
An intrinsic definition consists of a map with fields:
- intrinsic: pattern for the name(s) of the vendor's C intrinsic(s)
- llvm: pattern for the name(s) of the internal llvm intrinsic(s)
- width: a vector of vector bit-widths the pattern works with
- ret: type specifier for the return value
- arguments: vector of type specifiers for arguments
The width and types describe a range of possible intrinsics,
and these are fed back into the intrinsic and llvm patterns to
create the appropriate definitions.
## Type specifier grammar
```
type := vector | scalar | aggregate | reference
vector := vector_elem width |
vector_elem := 'i' | 'u' | 's' | 'f'
scalar := scalar_type number llvm_width?
scalar_type := 'U' | 'S' | 'F'
llvm_width := '/' number
aggregate := '(' (type),* ')' 'f'?
reference := number modifiers*
modifiers := 'v' | 'h' | 'd' | 'n' | 'w' | 'u' | 's' |
'x' number
width = number | '(' number '-' number ')'
number = [0-9]+
```
## Vectors
The vector grammar is a pattern describing many possibilities
for arguments/return value. The `vector_elem` describes the
types of elements to use, and the `width` describes the (range
of) widths for those elements, which are then placed into a
vector with the `width` bitwidth. E.g. if an intrinsic has a
`width` that includes 128, and the return value is `i(8-32)`,
then some instantiation of that intrinsic will be `u8x16`,
`u32x4`, `i32x4`, etc.
### Elements
- i: integer, both signed and unsigned
- u: unsigned integer
- s: signed integer
- f: float
## Scalars
Similar to vectors, but these describe a single concrete type,
not a range. The number is the bitwidth. The optional
`llvm_width` is the bitwidth of the integer that should be
passed to LLVM (by truncating the Rust argument): this only
works with scalar integers and the LLVM width must be smaller
than the Rust width.
### Types
- U: unsigned integer
- S: signed integer
- F: float
## Aggregates
An aggregate is a collection of multiple types; a tuple in
Rust terms, or an unnamed struct in LLVM. The `f` modifiers
forces the tuple to be flattened in the LLVM
intrinsic. E.g. if `llvm.foo` takes `(F32,S32)`:
- no `f` corresponds to `declare ... @llvm.foo({float, i32})`.
- having an `f` corresponds to `declare ... @llvm.foo(float, i32)`.
(Currently aggregates can not contain other aggregates.)
## References
A reference uses the type of another argument, with possible
modifications. The number refers to the type to use, starting
with 0 == return value, 1 == first argument, 2 == second
argument, etc. (Currently only referencing 0, the return
value, is supported.)
### Modifiers
- 'v': put a scalar into a vector of the current width (u32 -> u32x4, when width == 128)
- 'h': half the length of the vector (u32x4 -> u32x2)
- 'd': double the length of the vector (u32x2 -> u32x4)
- 'n': narrow the element of the vector (u32x4 -> u16x4)
- 'w': widen the element of the vector (u16x4 -> u32x4)
- 'u': force an integer (vector or scalar) to be unsigned (i32x4 -> u32x4)
- 's': force an integer (vector or scalar) to be signed (u32x4 -> i32x4)
- 'x' number: force the type to be a vector of bitwidth `number`.
'''))
parser.add_argument('--format', choices=FORMATS, required=True,
help = 'Output format.')
parser.add_argument('-o', '--out', type=argparse.FileType('w'), default=sys.stdout,
help = 'File to output to (default stdout).')
parser.add_argument('-i', '--info', type=argparse.FileType('r'),
help = 'File containing platform specific information to merge into'
'the input files\' header.')
parser.add_argument('in_', metavar="FILE", type=argparse.FileType('r'), nargs='+',
help = 'JSON files to load')
return parser.parse_args()
class ExternBlock(object):
def __init__(self):
pass
def open(self, platform):
return 'extern "platform-intrinsic" {'
def render(self, mono):
return ' fn {}{};'.format(mono.intrinsic_name(),
mono.intrinsic_signature())
def close(self):
return '}'
class CompilerDefs(object):
def __init__(self):
pass
def open(self, platform):
return '''\
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// DO NOT EDIT: autogenerated by etc/platform-intrinsics/generator.py
// ignore-tidy-linelength
#![allow(unused_imports)]
use {{Intrinsic, i, i_, u, u_, f, v, agg}};
use IntrinsicDef::Named;
use rustc::middle::ty;
pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> {{
if !name.starts_with("{0}") {{ return None }}
Some(match &name["{0}".len()..] {{'''.format(platform.intrinsic_prefix())
def render(self, mono):
return '''\
"{}" => Intrinsic {{
inputs: vec![{}],
output: {},
definition: Named("{}")
}},'''.format(mono.intrinsic_suffix(),
mono.compiler_args(),
mono.compiler_ret(),
mono.llvm_name())
def close(self):
return '''\
_ => return None,
})
}'''
FORMATS = {
'extern-block': ExternBlock(),
'compiler-defs': CompilerDefs(),
}
def main():
args = parse_args()
ins = args.in_
out = args.out
out_format = FORMATS[args.format]
info = args.info
one_file_no_info = False
if len(ins) > 1 and info is None:
print('error: cannot have multiple inputs without an info header.', file=sys.stderr)
sys.exit(1)
elif info is None:
info = ins[0]
one_file_no_info = True
info_json = json.load(info)
platform = PlatformInfo(info_json)
print(out_format.open(platform), file=out)
for in_ in ins:
if one_file_no_info:
data = info_json
else:
data = json.load(in_)
data.update(info_json)
intrinsics = IntrinsicSet(platform, data)
for intr in intrinsics.intrinsics():
for mono in intr.monomorphise():
print(out_format.render(mono), file=out)
print(out_format.close(), file=out)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,152 @@
{
"llvm_prefix": "llvm.x86.avx.",
"intrinsics": [
{
"intrinsic": "256_addsub_{0.data_type}",
"width": [256],
"llvm": "addsub.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "256_dp_ps",
"width": [256],
"llvm": "dp.ps.256",
"ret": "f32",
"args": ["0", "0", "S32/8"]
},
{
"intrinsic": "256_hadd_{0.data_type}",
"width": [256],
"llvm": "hadd.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "256_hsub_{0.data_type}",
"width": [256],
"llvm": "hsub.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "256_max_{0.data_type}",
"width": [256],
"llvm": "max.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "256_min_{0.data_type}",
"width": [256],
"llvm": "min.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "256_movemask_ps",
"width": [256],
"llvm": "movmsk.ps.256",
"ret": "S32",
"args": ["f32"]
},
{
"intrinsic": "256_movemask_pd",
"width": [256],
"llvm": "movmsk.pd.256",
"ret": "S32",
"args": ["f64"]
},
{
"intrinsic": "{0.width_mm}_permutevar_{0.data_type}",
"width": [128, 256],
"llvm": "vpermilvar.{0.data_type}{0.width_suffix}",
"ret": "f(32-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "256_rcp_ps",
"width": [256],
"llvm": "rcp.ps.256",
"ret": "f32",
"args": ["f32"]
},
{
"intrinsic": "256_rsqrt_ps",
"width": [256],
"llvm": "rsqrt.ps.256",
"ret": "f32",
"args": ["f32"]
},
{
"intrinsic": "256_sqrt_{0.data_type}",
"width": [256],
"llvm": "!llvm.sqrt.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0"]
},
{
"intrinsic": "{1.width_mm}_testc_ps",
"width": [128, 256],
"llvm": "vtestc.ps{1.width_suffix}",
"ret": "S32",
"args": ["f32", "f32"]
},
{
"intrinsic": "{1.width_mm}_testc_pd",
"width": [128, 256],
"llvm": "vtestc.pd{1.width_suffix}",
"ret": "S32",
"args": ["f64", "f64"]
},
{
"intrinsic": "256_testc_si256",
"width": [256],
"llvm": "ptestc.256",
"ret": "S32",
"args": ["u64", "u64"]
},
{
"intrinsic": "{1.width_mm}_testnzc_ps",
"width": [128, 256],
"llvm": "vtestnzc.ps{1.width_suffix}",
"ret": "S32",
"args": ["f32", "f32"]
},
{
"intrinsic": "{1.width_mm}_testnzc_pd",
"width": [128, 256],
"llvm": "vtestnzc.pd{1.width_suffix}",
"ret": "S32",
"args": ["f64", "f64"]
},
{
"intrinsic": "256_testnzc_si256",
"width": [256],
"llvm": "ptestnzc.256",
"ret": "S32",
"args": ["u64", "u64"]
},
{
"intrinsic": "{1.width_mm}_testz_ps",
"width": [128, 256],
"llvm": "vtestz.ps{1.width_suffix}",
"ret": "S32",
"args": ["f32", "f32"]
},
{
"intrinsic": "{1.width_mm}_testz_pd",
"width": [128, 256],
"llvm": "vtestz.pd{1.width_suffix}",
"ret": "S32",
"args": ["f64", "f64"]
},
{
"intrinsic": "256_testz_si256",
"width": [256],
"llvm": "ptestz.256",
"ret": "S32",
"args": ["u64", "u64"]
}
]
}

View File

@ -0,0 +1,159 @@
{
"llvm_prefix": "llvm.x86.avx2.",
"intrinsics": [
{
"intrinsic": "256_abs_{0.data_type}",
"width": [256],
"llvm": "avx2.pabs.{0.data_type_short}",
"ret": "s(8-32)",
"args": ["0"]
},
{
"intrinsic": "256_adds_{0.data_type}",
"width": [256],
"llvm": "avx2.padd{0.kind_short}s.{0.data_type_short}",
"ret": "i(8-16)",
"args": ["0", "0"]
},
{
"intrinsic": "256_avg_{0.data_type}",
"width": [256],
"llvm": "avx2.pavg.{0.data_type_short}",
"ret": "u(8-16)",
"args": ["0", "0"]
},
{
"intrinsic": "256_hadd_{0.data_type}",
"width": [256],
"llvm": "phadd.{0.data_type_short}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "256_hadds_epi16",
"width": [256],
"llvm": "phadd.sw",
"ret": "s16",
"args": ["0", "0"]
},
{
"intrinsic": "256_hsub_{0.data_type}",
"width": [256],
"llvm": "phsub.{0.data_type_short}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "256_hsubs_epi16",
"width": [256],
"llvm": "phsub.sw",
"ret": "s16",
"args": ["0", "0"]
},
{
"intrinsic": "256_madd_epi16",
"width": [256],
"llvm": "pmadd.wd",
"ret": "s32",
"args": ["s16", "s16"]
},
{
"intrinsic": "256_maddubs_epi16",
"width": [256],
"llvm": "pmadd.ub.sw",
"ret": "s16",
"args": ["s8", "s8"]
},
{
"intrinsic": "256_max_{0.data_type}",
"width": [256],
"llvm": "pmax{0.kind}.{0.data_type_short}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "256_min_{0.data_type}",
"width": [256],
"llvm": "pmin{0.kind}.{0.data_type_short}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "256_movemask_epi8",
"width": [256],
"llvm": "pmovmskb",
"ret": "S32",
"args": ["s8"]
},
{
"intrinsic": "256_mpsadbw_epu8",
"width": [256],
"llvm": "mpsadbw",
"ret": "u16",
"args": ["u8", "u8", "S32/8"]
},
{
"intrinsic": "256_mul_{0.data_type}",
"width": [256],
"llvm": "pmul{0.data_type_short}.dq",
"ret": "i64",
"args": ["0dn", "0dn"]
},
{
"intrinsic": "256_mulhi_{0.data_type}",
"width": [256],
"llvm": "pmulh{0.data_type_short}.w",
"ret": "i16",
"args": ["0", "0"]
},
{
"intrinsic": "256_mulhrs_epi16",
"width": [256],
"llvm": "pmul.hr.sw",
"ret": "s16",
"args": ["0", "0"]
},
{
"intrinsic": "256_pack{0.kind_short}s_{1.data_type}",
"width": [256],
"llvm": "pack{0.kind}s{1.data_type_short}{0.data_type_short}",
"ret": "i(8-16)",
"args": ["0hws", "0hws"]
},
{
"intrinsic": "256_permutevar8x32_{0.data_type}",
"width": [256],
"llvm": "perm{0.data_type_short}",
"ret": ["s32", "f32"],
"args": ["0", "0s"]
},
{
"intrinsic": "256_sad_epu8",
"width": [256],
"llvm": "psad.bw",
"ret": "u8",
"args": ["0", "0"]
},
{
"intrinsic": "256_shuffle_epi8",
"width": [256],
"llvm": "pshuf.b",
"ret": "s8",
"args": ["0", "0"]
},
{
"intrinsic": "256_sign_{0.data_type}",
"width": [256],
"llvm": "psign.{0.data_type_short}",
"ret": "s(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "256_subs_{0.data_type}",
"width": [256],
"llvm": "psub{0.kind_short}s.{0.data_type_short}",
"ret": "i(8-16)",
"args": ["0", "0"]
}
]
}

View File

@ -0,0 +1,28 @@
{
"platform": "x86",
"intrinsic_prefix": "x86_mm",
"number_info": {
"signed": {
"kind": "s",
"kind_short": "",
"data_type": { "pattern": "epi{bitwidth}" },
"data_type_short": { "8": "b", "16": "w", "32": "d", "64": "q" }
},
"unsigned": {
"kind": "u",
"kind_short": "u",
"data_type": { "pattern": "epu{bitwidth}" },
"data_type_short": { "8": "b", "16": "w", "32": "d", "64": "q" }
},
"float": {
"kind": "f",
"data_type": { "32": "ps", "64": "pd" },
"data_type_short": { "32": "ps", "64": "pd" }
}
},
"width_info": {
"128": { "width_mm": "", "width_suffix": "" },
"256": { "width_mm": "256", "width_suffix": ".256" },
"512": { "width_mm": "512", "width_suffix": ".512" }
}
}

View File

@ -0,0 +1,47 @@
{
"llvm_prefix": "llvm.x86.sse.",
"intrinsics": [
{
"intrinsic": "_movemask_ps",
"width": [128],
"llvm": "movmsk.ps",
"ret": "S32",
"args": ["f32"]
},
{
"intrinsic": "_max_ps",
"width": [128],
"llvm": "max.ps",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "_min_ps",
"width": [128],
"llvm": "min.ps",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "_rsqrt_ps",
"width": [128],
"llvm": "rsqrt.ps",
"ret": "f32",
"args": ["0"]
},
{
"intrinsic": "_rcp_ps",
"width": [128],
"llvm": "rcp.ps",
"ret": "f32",
"args": ["0"]
},
{
"intrinsic": "_sqrt_ps",
"width": [128],
"llvm": "!llvm.sqrt.v4f32",
"ret": "f32",
"args": ["0"]
}
]
}

View File

@ -0,0 +1,117 @@
{
"llvm_prefix": "llvm.x86.sse2.",
"intrinsics": [
{
"intrinsic": "_adds_{0.data_type}",
"width": [128],
"llvm": "padd{0.kind_short}s.{0.data_type_short}",
"ret": "i(8-16)",
"args": ["0", "0"]
},
{
"intrinsic": "_avg_{0.data_type}",
"width": [128],
"llvm": "pavg.{0.data_type_short}",
"ret": "u(8-16)",
"args": ["0", "0"]
},
{
"intrinsic": "_madd_epi16",
"width": [128],
"llvm": "pmadd.wd",
"ret": "s16",
"args": ["0", "0"]
},
{
"intrinsic": "_max_{0.data_type}",
"width": [128],
"llvm": "pmax{0.kind}.{0.data_type_short}",
"ret": ["s16", "u8"],
"args": ["0", "0"]
},
{
"intrinsic": "_max_pd",
"width": [128],
"llvm": "max.pd",
"ret": "f64",
"args": ["0", "0"]
},
{
"intrinsic": "_min_{0.data_type}",
"width": [128],
"llvm": "pmin{0.kind}.{0.data_type_short}",
"ret": ["s16", "u8"],
"args": ["0", "0"]
},
{
"intrinsic": "_min_pd",
"width": [128],
"llvm": "min.pd",
"ret": "f64",
"args": ["0", "0"]
},
{
"intrinsic": "_movemask_pd",
"width": [128],
"llvm": "movmsk.pd",
"ret": "S32",
"args": ["f64"]
},
{
"intrinsic": "_movemask_epi8",
"width": [128],
"llvm": "pmovmskb.128",
"ret": "S32",
"args": ["s8"]
},
{
"intrinsic": "_mul_epu32",
"width": [128],
"llvm": "pmulu.dq",
"ret": "s64",
"args": ["0dn", "0dn"]
},
{
"intrinsic": "_mulhi_ep{0.kind}16",
"width": [128],
"llvm": "pmulh{0.kind_short}.w",
"ret": "i16",
"args": ["0", "0"]
},
{
"intrinsic": "_packs_{1.data_type}",
"width": [128],
"llvm": "packss{1.data_type_short}{0.data_type_short}.128",
"ret": "s(8-16)",
"args": ["0hw", "0hw"]
},
{
"intrinsic": "_packus_epi16",
"width": [128],
"llvm": "packuswb.128",
"ret": "u8",
"args": ["s16", "s16"]
},
{
"intrinsic": "_sad_epu8",
"width": [128],
"llvm": "psad.bw",
"ret": "u64",
"args": ["u8", "u8"]
},
{
"intrinsic": "_sqrt_pd",
"width": [128],
"llvm": "!llvm.sqrt.v2f64",
"ret": "f64",
"args": ["0"]
},
{
"intrinsic": "_subs_{0.data_type}",
"width": [128],
"llvm": "psub{0.kind_short}s.{0.data_type_short}",
"ret": "i(8-16)",
"args": ["0", "0"]
}
]
}

View File

@ -0,0 +1,26 @@
{
"llvm_prefix": "llvm.x86.sse3.",
"intrinsics": [
{
"intrinsic": "_addsub_{0.data_type}",
"width": [128],
"llvm": "addsub.{0.data_type}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "_hadd_{0.data_type}",
"width": [128],
"llvm": "hadd.{0.data_type}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "_hsub_{0.data_type}",
"width": [128],
"llvm": "hsub.{0.data_type}",
"ret": "f(32-64)",
"args": ["0", "0"]
}
]
}

View File

@ -0,0 +1,75 @@
{
"llvm_prefix": "llvm.x86.sse41.",
"intrinsics": [
{
"intrinsic": "_dp_{0.data_type}",
"width": [128],
"llvm": "dp{0.data_type}",
"ret": "f(32-64)",
"args": ["0", "0", "S32/8"]
},
{
"intrinsic": "_max_{0.data_type}",
"width": [128],
"llvm": "pmax{0.kind}{0.data_type_short}",
"ret": ["s8", "u16", "i32"],
"args": ["0", "0"]
},
{
"intrinsic": "_min_{0.data_type}",
"width": [128],
"llvm": "pmin{0.kind}{0.data_type_short}",
"ret": ["s8", "u16", "i32"],
"args": ["0", "0"]
},
{
"intrinsic": "_minpos_epu16",
"width": [128],
"llvm": "phminposuw",
"ret": "u16",
"args": ["0"]
},
{
"intrinsic": "_mpsadbw_epu8",
"width": [128],
"llvm": "mpsadbw",
"ret": "u16",
"args": ["u8", "u8", "S32/8"]
},
{
"intrinsic": "_mul_epi32",
"width": [128],
"llvm": "muldq",
"ret": "s64",
"args": ["s32", "s32"]
},
{
"intrinsic": "_packus_epi32",
"width": [128],
"llvm": "packusdw",
"ret": "u16",
"args": ["s32", "s32"]
},
{
"intrinsic": "_testc_si128",
"width": [128],
"llvm": "ptestc",
"ret": "S32",
"args": ["u64", "u64"]
},
{
"intrinsic": "_testncz_si128",
"width": [128],
"llvm": "ptest.nzc",
"ret": "S32",
"args": ["u64", "u64"]
},
{
"intrinsic": "_testz_si128",
"width": [128],
"llvm": "ptestz",
"ret": "S32",
"args": ["u64", "u64"]
}
]
}

View File

@ -0,0 +1,103 @@
{
"llvm_prefix": "llvm.x86.sse42.",
"intrinsics": [
{
"intrinsic": "_cmpestra",
"width": [128],
"llvm": "pcmpestria128",
"ret": "S32",
"args": ["s8", "S32", "s8", "S32", "S32/8"]
},
{
"intrinsic": "_cmpestrc",
"width": [128],
"llvm": "pcmpestric128",
"ret": "S32",
"args": ["s8", "S32", "s8", "S32", "S32/8"]
},
{
"intrinsic": "_cmpestri",
"width": [128],
"llvm": "pcmpestri128",
"ret": "S32",
"args": ["s8", "S32", "s8", "S32", "S32/8"]
},
{
"intrinsic": "_cmpestrm",
"width": [128],
"llvm": "pcmpestrm128",
"ret": "s8",
"args": ["s8", "S32", "s8", "S32", "S32/8"]
},
{
"intrinsic": "_cmpestro",
"width": [128],
"llvm": "pcmpestrio128",
"ret": "S32",
"args": ["s8", "S32", "s8", "S32", "S32/8"]
},
{
"intrinsic": "_cmpestrs",
"width": [128],
"llvm": "pcmpestris128",
"ret": "S32",
"args": ["s8", "S32", "s8", "S32", "S32/8"]
},
{
"intrinsic": "_cmpestrz",
"width": [128],
"llvm": "pcmpestriz128",
"ret": "S32",
"args": ["s8", "S32", "s8", "S32", "S32/8"]
},
{
"intrinsic": "_cmpistra",
"width": [128],
"llvm": "pcmpistria128",
"ret": "S32",
"args": ["s8", "s8", "S32/8"]
},
{
"intrinsic": "_cmpistrc",
"width": [128],
"llvm": "pcmpistric128",
"ret": "S32",
"args": ["s8", "s8", "S32/8"]
},
{
"intrinsic": "_cmpistri",
"width": [128],
"llvm": "pcmpistri128",
"ret": "S32",
"args": ["s8", "s8", "S32/8"]
},
{
"intrinsic": "_cmpistrm",
"width": [128],
"llvm": "pcmpistrm128",
"ret": "s8",
"args": ["s8", "s8", "S32/8"]
},
{
"intrinsic": "_cmpistro",
"width": [128],
"llvm": "pcmpistrio128",
"ret": "S32",
"args": ["s8", "s8", "S32/8"]
},
{
"intrinsic": "_cmpistrs",
"width": [128],
"llvm": "pcmpistris128",
"ret": "S32",
"args": ["s8", "s8", "S32/8"]
},
{
"intrinsic": "_cmpistrz",
"width": [128],
"llvm": "pcmpistriz128",
"ret": "S32",
"args": ["s8", "s8", "S32/8"]
}
]
}

View File

@ -0,0 +1,68 @@
{
"llvm_prefix": "llvm.x86.ssse3.",
"intrinsics": [
{
"intrinsic": "_abs_{0.data_type}",
"width": [128],
"llvm": "pabs.{0.data_type_short}",
"ret": "s(8-32)",
"args": ["0"]
},
{
"intrinsic": "_hadd_{0.data_type}",
"width": [128],
"llvm": "phadd.{0.data_type_short}.128",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "_hadds_epi16",
"width": [128],
"llvm": "phadd.sw.128",
"ret": "s16",
"args": ["0", "0"]
},
{
"intrinsic": "_hsub_{0.data_type}",
"width": [128],
"llvm": "phsub.{0.data_type_short}.128",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "_hsubs_epi16",
"width": [128],
"llvm": "phsub.sw.128",
"ret": "s16",
"args": ["0", "0"]
},
{
"intrinsic": "_maddubs_epi16",
"width": [128],
"llvm": "pmadd.ub.sw.128",
"ret": "s16",
"args": ["s8", "s8"]
},
{
"intrinsic": "_mulhrs_epi16",
"width": [128],
"llvm": "pmul.hr.sw.128",
"ret": "s16",
"args": ["s16", "s16"]
},
{
"intrinsic": "_shuffle_epi8",
"width": [128],
"llvm": "pshuf.b.128",
"ret": "s8",
"args": ["s8", "s8"]
},
{
"intrinsic": "_sign_{0.data_type}",
"width": [128],
"llvm": "psign.{0.data_type_short}.128",
"ret": "s(8-16)",
"args": ["0", "0"]
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,58 +30,26 @@ pub struct Intrinsic {
#[derive(Clone, Hash, Eq, PartialEq)]
pub enum Type {
Integer(u8),
Integer(/* signed */ bool, u8, /* llvm width */ u8),
Float(u8),
Pointer(Box<Type>),
Vector(Box<Type>, u8),
Aggregate(bool, Vec<Type>),
}
pub enum IntrinsicDef {
Named(&'static str),
}
fn i(width: u8) -> Type { Type::Integer(width) }
fn i(width: u8) -> Type { Type::Integer(true, width, width) }
fn i_(width: u8, llvm_width: u8) -> Type { Type::Integer(true, width, llvm_width) }
fn u(width: u8) -> Type { Type::Integer(false, width, width) }
#[allow(dead_code)]
fn u_(width: u8, llvm_width: u8) -> Type { Type::Integer(false, width, llvm_width) }
fn f(width: u8) -> Type { Type::Float(width) }
fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) }
macro_rules! ty {
(f32x8) => (v(f(32), 8));
(f64x4) => (v(f(64), 4));
(i8x32) => (v(i(8), 32));
(i16x16) => (v(i(16), 16));
(i32x8) => (v(i(32), 8));
(i64x4) => (v(i(64), 4));
(f32x4) => (v(f(32), 4));
(f64x2) => (v(f(64), 2));
(i8x16) => (v(i(8), 16));
(i16x8) => (v(i(16), 8));
(i32x4) => (v(i(32), 4));
(i64x2) => (v(i(64), 2));
(f32x2) => (v(f(32), 2));
(i8x8) => (v(i(8), 8));
(i16x4) => (v(i(16), 4));
(i32x2) => (v(i(32), 2));
(i64x1)=> (v(i(64), 1));
(i64) => (i(64));
(i32) => (i(32));
(i16) => (i(16));
(i8) => (i(8));
(f32) => (f(32));
(f64) => (f(64));
}
macro_rules! plain {
($name: expr, ($($inputs: tt),*) -> $output: tt) => {
Intrinsic {
inputs: vec![$(ty!($inputs)),*],
output: ty!($output),
definition: ::IntrinsicDef::Named($name)
}
}
fn agg(flatten: bool, types: Vec<Type>) -> Type {
Type::Aggregate(flatten, types)
}
mod x86;
@ -91,11 +59,11 @@ mod aarch64;
impl Intrinsic {
pub fn find<'tcx>(tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> {
if name.starts_with("x86_") {
x86::find(tcx, &name["x86_".len()..])
x86::find(tcx, name)
} else if name.starts_with("arm_") {
arm::find(tcx, &name["arm_".len()..])
arm::find(tcx, name)
} else if name.starts_with("aarch64_") {
aarch64::find(tcx, &name["aarch64_".len()..])
aarch64::find(tcx, name)
} else {
None
}

File diff suppressed because it is too large Load Diff

View File

@ -171,9 +171,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("trans_intrinsic_call");
let ret_ty = match callee_ty.sty {
let (arg_tys, ret_ty) = match callee_ty.sty {
ty::TyBareFn(_, ref f) => {
bcx.tcx().erase_late_bound_regions(&f.sig.output())
(bcx.tcx().erase_late_bound_regions(&f.sig.inputs()),
bcx.tcx().erase_late_bound_regions(&f.sig.output()))
}
_ => panic!("expected bare_fn in trans_intrinsic_call")
};
@ -926,25 +927,105 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
Some(intr) => intr,
None => ccx.sess().span_bug(foreign_item.span, "unknown intrinsic"),
};
fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type) -> Type {
fn one<T>(x: Vec<T>) -> T {
assert_eq!(x.len(), 1);
x.into_iter().next().unwrap()
}
fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type,
any_changes_needed: &mut bool) -> Vec<Type> {
use intrinsics::Type::*;
match *t {
Integer(x) => Type::ix(ccx, x as u64),
Integer(_signed, width, llvm_width) => {
*any_changes_needed |= width != llvm_width;
vec![Type::ix(ccx, llvm_width as u64)]
}
Float(x) => {
match x {
32 => Type::f32(ccx),
64 => Type::f64(ccx),
32 => vec![Type::f32(ccx)],
64 => vec![Type::f64(ccx)],
_ => unreachable!()
}
}
Pointer(_) => unimplemented!(),
Vector(ref t, length) => Type::vector(&ty_to_type(ccx, t),
length as u64)
Vector(ref t, length) => {
let elem = one(ty_to_type(ccx, t,
any_changes_needed));
vec![Type::vector(&elem,
length as u64)]
}
Aggregate(false, _) => unimplemented!(),
Aggregate(true, ref contents) => {
*any_changes_needed = true;
contents.iter()
.flat_map(|t| ty_to_type(ccx, t, any_changes_needed))
.collect()
}
}
}
let inputs = intr.inputs.iter().map(|t| ty_to_type(ccx, t)).collect::<Vec<_>>();
let outputs = ty_to_type(ccx, &intr.output);
// This allows an argument list like `foo, (bar, baz),
// qux` to be converted into `foo, bar, baz, qux`, and
// integer arguments to be truncated as needed.
fn modify_as_needed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
t: &intrinsics::Type,
arg_type: Ty<'tcx>,
llarg: ValueRef)
-> Vec<ValueRef>
{
match *t {
intrinsics::Type::Aggregate(true, ref contents) => {
// We found a tuple that needs squishing! So
// run over the tuple and load each field.
//
// This assumes the type is "simple", i.e. no
// destructors, and the contents are SIMD
// etc.
assert!(!bcx.fcx.type_needs_drop(arg_type));
let repr = adt::represent_type(bcx.ccx(), arg_type);
let repr_ptr = &*repr;
(0..contents.len())
.map(|i| {
Load(bcx, adt::trans_field_ptr(bcx, repr_ptr, llarg, 0, i))
})
.collect()
}
intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
// the LLVM intrinsic uses a smaller integer
// size than the C intrinsic's signature, so
// we have to trim it down here.
vec![Trunc(bcx, llarg, Type::ix(bcx.ccx(), llvm_width as u64))]
}
_ => vec![llarg],
}
}
let mut any_changes_needed = false;
let inputs = intr.inputs.iter()
.flat_map(|t| ty_to_type(ccx, t, &mut any_changes_needed))
.collect::<Vec<_>>();
let mut out_changes = false;
let outputs = one(ty_to_type(ccx, &intr.output, &mut out_changes));
// outputting a flattened aggregate is nonsense
assert!(!out_changes);
let llargs = if !any_changes_needed {
// no aggregates to flatten, so no change needed
llargs
} else {
// there are some aggregates that need to be flattened
// in the LLVM call, so we need to run over the types
// again to find them and extract the arguments
intr.inputs.iter()
.zip(&llargs)
.zip(&arg_tys)
.flat_map(|((t, llarg), ty)| modify_as_needed(bcx, t, ty, *llarg))
.collect()
};
assert_eq!(inputs.len(), llargs.len());
match intr.definition {
intrinsics::IntrinsicDef::Named(name) => {
let f = declare::declare_cfn(ccx,

View File

@ -463,13 +463,16 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
};
match *expected {
Integer(bits) => match (bits, &t.sty) {
(8, &ty::TyInt(ast::TyI8)) | (8, &ty::TyUint(ast::TyU8)) |
(16, &ty::TyInt(ast::TyI16)) | (16, &ty::TyUint(ast::TyU16)) |
(32, &ty::TyInt(ast::TyI32)) | (32, &ty::TyUint(ast::TyU32)) |
(64, &ty::TyInt(ast::TyI64)) | (64, &ty::TyUint(ast::TyU64)) => {},
// (The width we pass to LLVM doesn't concern the type checker.)
Integer(signed, bits, _llvm_width) => match (signed, bits, &t.sty) {
(true, 8, &ty::TyInt(ast::TyI8)) | (false, 8, &ty::TyUint(ast::TyU8)) |
(true, 16, &ty::TyInt(ast::TyI16)) | (false, 16, &ty::TyUint(ast::TyU16)) |
(true, 32, &ty::TyInt(ast::TyI32)) | (false, 32, &ty::TyUint(ast::TyU32)) |
(true, 64, &ty::TyInt(ast::TyI64)) | (false, 64, &ty::TyUint(ast::TyU64)) => {},
_ => simple_error(&format!("`{}`", t),
&format!("`i{n}` or `u{n}`", n = bits)),
&format!("`{}{n}`",
if signed {"i"} else {"u"},
n = bits)),
},
Float(bits) => match (bits, &t.sty) {
(32, &ty::TyFloat(ast::TyF32)) |
@ -512,5 +515,22 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
inner_expected,
t_ty)
}
Aggregate(_flatten, ref expected_contents) => {
match t.sty {
ty::TyTuple(ref contents) => {
if contents.len() != expected_contents.len() {
simple_error(&format!("tuple with length {}", contents.len()),
&format!("tuple with length {}", expected_contents.len()));
return
}
for (e, c) in expected_contents.iter().zip(contents) {
match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal,
e, c)
}
}
_ => simple_error(&format!("`{}`", t),
&format!("tuple")),
}
}
}
}

View File

@ -25,27 +25,38 @@ struct f32x4(f32, f32, f32, f32);
#[repr(simd)]
struct i64x2(i64, i64);
// signed vs. unsigned doesn't matter
mod i {
use i16x8;
// correct signatures work well
mod right {
use {i16x8, u16x8};
extern "platform-intrinsic" {
fn x86_mm_adds_epi16(x: i16x8, y: i16x8) -> i16x8;
fn x86_mm_adds_epu16(x: u16x8, y: u16x8) -> u16x8;
}
}
mod u {
use u16x8;
// but incorrect ones don't.
mod signedness {
use {i16x8, u16x8};
// signedness matters
extern "platform-intrinsic" {
fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8;
//~^ ERROR intrinsic argument 1 has wrong type
//~^^ ERROR intrinsic argument 2 has wrong type
//~^^^ ERROR intrinsic return value has wrong type
fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8;
//~^ ERROR intrinsic argument 1 has wrong type
//~^^ ERROR intrinsic argument 2 has wrong type
//~^^^ ERROR intrinsic return value has wrong type
}
}
// but lengths do
// as do lengths
extern "platform-intrinsic" {
fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2;
//~^ ERROR intrinsic argument 1 has wrong type
//~^^ ERROR intrinsic argument 2 has wrong type
//~^^^ ERROR intrinsic return value has wrong type
}
// and so does int vs. float
// and so does int vs. float:
extern "platform-intrinsic" {
fn x86_mm_max_ps(x: i32x4, y: i32x4) -> i32x4;
//~^ ERROR intrinsic argument 1 has wrong type