//===- targets.go - target data -------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains functions for retrieving target-specific data. // //===----------------------------------------------------------------------===// package irgen import ( "fmt" "strings" "llvm.org/llvm/bindings/go/llvm" ) // PNaClTriple is the LLVM target triple that should be used to compile // modules to be compatible with PNaCl (Portable Native Client). const PNaClTriple = "armv7-none-linux-gnueabi" // Below are the target data representation constants generated by clang. // For unknown targets, we enumerate all targets known to LLVM and use // the first one with a matching architecture. const ( x86TargetData = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" ) // llvmDataLayout returns the data layout string // representation for the specified LLVM triple. func llvmDataLayout(triple string) (string, error) { // Triples are several fields separated by '-' characters. // The first field is the architecture. The architecture's // canonical form may include a '-' character, which would // have been translated to '_' for inclusion in a triple. arch := parseArch(triple[:strings.IndexRune(triple, '-')]) switch arch { case "x86-64": return x86TargetData, nil } for target := llvm.FirstTarget(); target.C != nil; target = target.NextTarget() { if arch == target.Name() { machine := target.CreateTargetMachine( triple, "", "", llvm.CodeGenLevelDefault, llvm.RelocDefault, llvm.CodeModelDefault, ) target := machine.TargetData().String() machine.Dispose() return target, nil } } return "", fmt.Errorf("Invalid target triple: %s", triple) } // Based on parseArch from LLVM's lib/Support/Triple.cpp. // This is used to match the target machine type. func parseArch(arch string) string { switch arch { case "i386", "i486", "i586", "i686", "i786", "i886", "i986": return "x86" case "amd64", "x86_64": return "x86-64" case "powerpc": return "ppc" case "powerpc64", "ppu": return "ppc64" case "mblaze": return "mblaze" case "arm", "xscale": return "arm" case "thumb": return "thumb" case "spu", "cellspu": return "cellspu" case "msp430": return "msp430" case "mips", "mipseb", "mipsallegrex": return "mips" case "mipsel", "mipsallegrexel": return "mipsel" case "mips64", "mips64eb": return "mips64" case "mipsel64": return "mipsel64" case "r600", "hexagon", "sparc", "sparcv9", "tce", "xcore", "nvptx", "nvptx64", "le32", "amdil": return arch } if strings.HasPrefix(arch, "armv") { return "arm" } else if strings.HasPrefix(arch, "thumbv") { return "thumb" } return "unknown" }