blob: 59991fbd601468c26d653f1a8098bd3f8d5229b7 [file] [log] [blame]
//==----- Target.h - Target hooks for GCC to LLVM conversion -----*- C++ -*-==//
//
// Copyright (C) 2007 to 2013 Jin Gu Kang, Anton Korobeynikov, Duncan Sands
// et al.
//
// This file is part of DragonEgg.
//
// DragonEgg is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2, or (at your option) any later version.
//
// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// DragonEgg; see the file COPYING. If not, write to the Free Software
// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
//
//===----------------------------------------------------------------------===//
// This file declares some target-specific hooks for GCC to LLVM conversion.
// It was derived from llvm-arm-target.h and arm.h on llvm-gcc.4.2.
//===----------------------------------------------------------------------===//
#ifndef DRAGONEGG_TARGET_H
#define DRAGONEGG_TARGET_H
/* LLVM specific code to select the calling conventions. The AAPCS
specification says that varargs functions must use the base standard
instead of the VFP hard float variant. We check for that with
(isVoid || hasArgList). */
/* from TARGET_AAPCS_BASED */
#define DEFAULT_TARGET_AAPCS_BASED(ARM_DEFAULT_ABI != ARM_ABI_APCS && \
ARM_DEFAULT_ABI != ARM_ABI_ATPCS)
#define TARGET_ADJUST_LLVM_CC(CC, type) \
{ \
if (TARGET_AAPCS_BASED) { \
if (TARGET_VFP && TARGET_HARD_FLOAT_ABI && \
((TYPE_ARG_TYPES(type) == 0) || \
(TREE_VALUE(tree_last(TYPE_ARG_TYPES(type))) == void_type_node))) \
CC = CallingConv::ARM_AAPCS_VFP; \
else if (!DEFAULT_TARGET_AAPCS_BASED) \
CC = CallingConv::ARM_AAPCS; \
} else if (DEFAULT_TARGET_AAPCS_BASED) { \
CC = CallingConv::ARM_APCS; \
} \
}
#ifdef DRAGONEGG_ABI_H
extern bool llvm_arm_should_pass_aggregate_in_mixed_regs(
tree_node *, Type *Ty, CallingConv::ID, std::vector<Type *> &);
#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, CC, E) \
llvm_arm_should_pass_aggregate_in_mixed_regs((T), (TY), (CC), (E))
struct DefaultABIClient;
extern bool llvm_arm_try_pass_aggregate_custom(
tree_node *, std::vector<Type *> &, CallingConv::ID CC,
struct DefaultABIClient *);
#define LLVM_TRY_PASS_AGGREGATE_CUSTOM(T, E, CC, C) \
llvm_arm_try_pass_aggregate_custom((T), (E), (CC), (C))
extern bool llvm_arm_aggregate_partially_passed_in_regs(
std::vector<Type *> &, std::vector<Type *> &, CallingConv::ID CC);
#define LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(E, SE, ISR, CC) \
llvm_arm_aggregate_partially_passed_in_regs((E), (SE), (CC))
extern Type *
llvm_arm_aggr_type_for_struct_return(tree_node *type, CallingConv::ID CC);
/* LLVM_AGGR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be
returned as an aggregate, otherwise return NULL. */
#define LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(X, CC) \
llvm_arm_aggr_type_for_struct_return((X), (CC))
extern void llvm_arm_extract_multiple_return_value(
Value *Src, Value *Dest, bool isVolatile, LLVMBuilder &B);
/* LLVM_EXTRACT_MULTIPLE_RETURN_VALUE - Extract multiple return value from
SRC and assign it to DEST. */
#define LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Src, Dest, V, B) \
llvm_arm_extract_multiple_return_value((Src), (Dest), (V), (B))
extern bool llvm_arm_should_pass_or_return_aggregate_in_regs(
tree_node *TreeType, CallingConv::ID CC);
/* LLVM_SHOULD_NOT_USE_SHADOW_RETURN = Return true is the given type should
not be returned via a shadow parameter with the given calling conventions. */
#define LLVM_SHOULD_NOT_USE_SHADOW_RETURN(X, CC) \
llvm_arm_should_pass_or_return_aggregate_in_regs((X), (CC))
/* Vectors bigger than 128 are returned using sret. */
#define LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(X, isBuiltin) \
(TREE_INT_CST_LOW(TYPE_SIZE(X)) > 128)
#endif /* DRAGONEGG_ABI_H */
#define LLVM_TARGET_INTRINSIC_PREFIX "arm"
/* LLVM_TARGET_NAME - This specifies the name of the target, which correlates to
* the llvm::InitializeXXXTarget() function.
*/
#define LLVM_TARGET_NAME ARM
/* Turn -march=xx into a CPU type.
*/
#define LLVM_SET_SUBTARGET_FEATURES(C, F) \
{ \
switch (arm_tune) { \
case arm8: \
C = ("arm8"); \
break; \
case arm810: \
C = ("arm810"); \
break; \
case strongarm: \
C = ("strongarm"); \
break; \
case strongarm110: \
C = ("strongarm110"); \
break; \
case strongarm1100: \
C = ("strongarm1100"); \
break; \
case strongarm1110: \
C = ("strongarm1110"); \
break; \
case arm7tdmi: \
C = ("arm7tdmi"); \
break; \
case arm7tdmis: \
C = ("arm7tdmi-s"); \
break; \
case arm710t: \
C = ("arm710t"); \
break; \
case arm720t: \
C = ("arm720t"); \
break; \
case arm740t: \
C = ("arm740t"); \
break; \
case arm9: \
C = ("arm9"); \
break; \
case arm9tdmi: \
C = ("arm9tdmi"); \
break; \
case arm920: \
C = ("arm920"); \
break; \
case arm920t: \
C = ("arm920t"); \
break; \
case arm922t: \
C = ("arm922t"); \
break; \
case arm940t: \
C = ("arm940t"); \
break; \
case ep9312: \
C = ("ep9312"); \
break; \
case arm10tdmi: \
C = ("arm10tdmi"); \
break; \
case arm1020t: \
C = ("arm1020t"); \
break; \
case arm9e: \
C = ("arm9e"); \
break; \
case arm946es: \
C = ("arm946e-s"); \
break; \
case arm966es: \
C = ("arm966e-s"); \
break; \
case arm968es: \
C = ("arm968e-s"); \
break; \
case arm10e: \
C = ("arm10e"); \
break; \
case arm1020e: \
C = ("arm1020e"); \
break; \
case arm1022e: \
C = ("arm1022e"); \
break; \
case xscale: \
C = ("xscale"); \
break; \
case iwmmxt: \
C = ("iwmmxt"); \
break; \
case arm926ejs: \
C = ("arm926ej-s"); \
break; \
case arm1026ejs: \
C = ("arm1026ej-s"); \
break; \
case arm1136js: \
C = ("arm1136j-s"); \
break; \
case arm1136jfs: \
C = ("arm1136jf-s"); \
break; \
case arm1176jzs: \
C = ("arm1176jz-s"); \
break; \
case arm1176jzfs: \
C = ("arm1176jzf-s"); \
break; \
case mpcorenovfp: \
C = ("mpcorenovfp"); \
break; \
case mpcore: \
C = ("mpcore"); \
break; \
case arm1156t2s: \
C = ("arm1156t2-s"); \
break; \
case arm1156t2fs: \
C = ("arm1156t2f-s"); \
break; \
case cortexa8: \
C = ("cortex-a8"); \
break; \
case cortexa9: \
C = ("cortex-a9"); \
break; \
case cortexr4: \
C = ("cortex-r4"); \
break; \
case cortexm3: \
C = ("cortex-m3"); \
break; \
case cortexm4: \
C = ("cortex-m4"); \
break; \
case cortexm0: \
C = ("cortex-m0"); \
break; \
default: \
C = ("arm7tdmi"); \
break; \
} \
F.AddFeature("vfp3", TARGET_VFP3); \
if (!TARGET_VFP3) \
F.AddFeature("vfp2", TARGET_VFP && TARGET_HARD_FLOAT); \
F.AddFeature("neon", TARGET_NEON); \
F.AddFeature("fp16", TARGET_FP16); \
}
/* Encode arm / thumb modes and arm subversion number in the triplet. e.g.
* armv6-apple-darwin, thumbv5-apple-darwin. FIXME: Replace thumb triplets
* with function notes.
*/
#define LLVM_OVERRIDE_TARGET_ARCH() \
(TARGET_THUMB \
? (arm_arch7 \
? "thumbv7" \
: (arm_arch_thumb2 \
? "thumbv6t2" \
: (arm_tune == cortexm0 \
? "thumbv6m" \
: (arm_arch6 \
? "thumbv6" \
: (arm_arch5e \
? "thumbv5e" \
: (arm_arch5 \
? "thumbv5" \
: (arm_arch4t ? "thumbv4t" \
: ""))))))) \
: (arm_arch7 \
? "armv7" \
: (arm_arch_thumb2 \
? "armv6t2" \
: (arm_arch6 \
? "armv6" \
: (arm_arch5e \
? "armv5e" \
: (arm_arch5 \
? "armv5" \
: (arm_arch4t \
? "armv4t" \
: (arm_arch4 ? "armv4" \
: ""))))))))
#if 0
// Dragonegg should make flag_mkernel and flag_apple_kext option later on.
// We didn't decide place to make these flags.
#define LLVM_SET_MACHINE_OPTIONS(argvec) \
if (flag_mkernel || flag_apple_kext) { \
argvec.push_back("-arm-long-calls"); \
argvec.push_back("-arm-strict-align"); \
}
#endif
#define LLVM_SET_TARGET_MACHINE_OPTIONS(options) \
do { \
options.UseSoftFloat = TARGET_SOFT_FLOAT; \
if (TARGET_HARD_FLOAT_ABI) \
options.FloatABIType = llvm::FloatABI::Hard; \
} while (0)
/* These are a couple of extensions to the asm formats
%@ prints out ASM_COMMENT_START
TODO: %r prints out REGISTER_PREFIX reg_names[arg] */
#define LLVM_ASM_EXTENSIONS(ESCAPED_CHAR, ASM, RESULT) \
else if ((ESCAPED_CHAR) == '@') { \
(RESULT) += ASM_COMMENT_START; \
}
/* LLVM_TARGET_INTRINSIC_LOWER - To handle builtins, we want to expand the
invocation into normal LLVM code. If the target can handle the builtin, this
macro should call the target TreeToLLVM::TargetIntrinsicLower method and
return true. This macro is invoked from a method in the TreeToLLVM class. */
#if 0
// Because of data dependency, we will implement later on.
#define LLVM_TARGET_INTRINSIC_LOWER(EXP, BUILTIN_CODE, DESTLOC, RESULT, \
DESTTY, OPS) \
TargetIntrinsicLower(EXP, BUILTIN_CODE, DESTLOC, RESULT, DESTTY, OPS);
#endif
/* LLVM_GET_REG_NAME - The registers known to llvm as "r10", "r11", and "r12"
may have different names in GCC. Register "r12" is called "ip", and on
non-Darwin OSs, "r10" is "sl" and "r11" is "fp". Translate those names.
For VFP registers, GCC doesn't distinguish between the q and d registers
so use the incoming register name if it exists. Otherwise, use the default
register names to match the backend. */
#define LLVM_GET_REG_NAME(REG_NAME, REG_NUM) \
((REG_NUM) == 10 ? "r10" : (REG_NUM) == 11 \
? "r11" \
: (REG_NUM) == 12 \
? "r12" \
: (REG_NUM) >= FIRST_VFP_REGNUM && \
REG_NAME != 0 \
? REG_NAME \
: reg_names[REG_NUM])
/* Define a static enumeration of the NEON builtins to be used when
converting to LLVM intrinsics. These names are derived from the
neon_builtin_data table in arm.c and should be kept in sync with that. */
#endif /* DRAGONEGG_TARGET_H */