Rename the 'cretonne' crate to 'cretonne-codegen'.

This fixes the next part of #287.
This commit is contained in:
Dan Gohman
2018-04-17 08:48:02 -07:00
parent 7767186dd0
commit 24fa169e1f
254 changed files with 265 additions and 264 deletions

View File

@@ -0,0 +1 @@
"""Definitions for the base Cretonne language."""

View File

@@ -0,0 +1,35 @@
"""
The `cretonne.entities` module predefines all the Cretonne entity reference
operand types. There are corresponding definitions in the `cretonne.entities`
Rust module.
"""
from __future__ import absolute_import
from cdsl.operands import EntityRefKind
#: A reference to an extended basic block in the same function.
#: This is primarliy used in control flow instructions.
ebb = EntityRefKind(
'ebb', 'An extended basic block in the same function.',
default_member='destination')
#: A reference to a stack slot declared in the function preamble.
stack_slot = EntityRefKind('stack_slot', 'A stack slot.')
#: A reference to a global variable.
global_var = EntityRefKind('global_var', 'A global variable.')
#: A reference to a function sugnature declared in the function preamble.
#: Tbis is used to provide the call signature in an indirect call instruction.
sig_ref = EntityRefKind('sig_ref', 'A function signature.')
#: A reference to an external function declared in the function preamble.
#: This is used to provide the callee and signature in a call instruction.
func_ref = EntityRefKind('func_ref', 'An external function.')
#: A reference to a jump table declared in the function preamble.
jump_table = EntityRefKind(
'jump_table', 'A jump table.', default_member='table')
#: A reference to a heap declared in the function preamble.
heap = EntityRefKind('heap', 'A heap.')

View File

@@ -0,0 +1,81 @@
"""
The cretonne.formats defines all instruction formats.
Every instruction format has a corresponding `InstructionData` variant in the
Rust representation of Cretonne IR, so all instruction formats must be defined
in this module.
"""
from __future__ import absolute_import
from cdsl.formats import InstructionFormat
from cdsl.operands import VALUE, VARIABLE_ARGS
from .immediates import imm64, uimm8, uimm32, ieee32, ieee64, offset32
from .immediates import boolean, intcc, floatcc, memflags, regunit, trapcode
from . import entities
from .entities import ebb, sig_ref, func_ref, stack_slot, heap
Unary = InstructionFormat(VALUE)
UnaryImm = InstructionFormat(imm64)
UnaryIeee32 = InstructionFormat(ieee32)
UnaryIeee64 = InstructionFormat(ieee64)
UnaryBool = InstructionFormat(boolean)
UnaryGlobalVar = InstructionFormat(entities.global_var)
Binary = InstructionFormat(VALUE, VALUE)
BinaryImm = InstructionFormat(VALUE, imm64)
# The select instructions are controlled by the second VALUE operand.
# The first VALUE operand is the controlling flag which has a derived type.
# The fma instruction has the same constraint on all inputs.
Ternary = InstructionFormat(VALUE, VALUE, VALUE, typevar_operand=1)
# Catch-all for instructions with many outputs and inputs and no immediate
# operands.
MultiAry = InstructionFormat(VARIABLE_ARGS)
NullAry = InstructionFormat()
InsertLane = InstructionFormat(VALUE, ('lane', uimm8), VALUE)
ExtractLane = InstructionFormat(VALUE, ('lane', uimm8))
IntCompare = InstructionFormat(intcc, VALUE, VALUE)
IntCompareImm = InstructionFormat(intcc, VALUE, imm64)
IntCond = InstructionFormat(intcc, VALUE)
FloatCompare = InstructionFormat(floatcc, VALUE, VALUE)
FloatCond = InstructionFormat(floatcc, VALUE)
IntSelect = InstructionFormat(intcc, VALUE, VALUE, VALUE)
Jump = InstructionFormat(ebb, VARIABLE_ARGS)
Branch = InstructionFormat(VALUE, ebb, VARIABLE_ARGS)
BranchInt = InstructionFormat(intcc, VALUE, ebb, VARIABLE_ARGS)
BranchFloat = InstructionFormat(floatcc, VALUE, ebb, VARIABLE_ARGS)
BranchIcmp = InstructionFormat(intcc, VALUE, VALUE, ebb, VARIABLE_ARGS)
BranchTable = InstructionFormat(VALUE, entities.jump_table)
Call = InstructionFormat(func_ref, VARIABLE_ARGS)
IndirectCall = InstructionFormat(sig_ref, VALUE, VARIABLE_ARGS)
FuncAddr = InstructionFormat(func_ref)
Load = InstructionFormat(memflags, VALUE, offset32)
Store = InstructionFormat(memflags, VALUE, VALUE, offset32)
StackLoad = InstructionFormat(stack_slot, offset32)
StackStore = InstructionFormat(VALUE, stack_slot, offset32)
# Accessing a WebAssembly heap.
HeapAddr = InstructionFormat(heap, VALUE, uimm32)
RegMove = InstructionFormat(VALUE, ('src', regunit), ('dst', regunit))
CopySpecial = InstructionFormat(('src', regunit), ('dst', regunit))
RegSpill = InstructionFormat(
VALUE, ('src', regunit), ('dst', entities.stack_slot))
RegFill = InstructionFormat(
VALUE, ('src', entities.stack_slot), ('dst', regunit))
Trap = InstructionFormat(trapcode)
CondTrap = InstructionFormat(VALUE, trapcode)
IntCondTrap = InstructionFormat(intcc, VALUE, trapcode)
FloatCondTrap = InstructionFormat(floatcc, VALUE, trapcode)
# Finally extract the names of global variables in this module.
InstructionFormat.extract_names(globals())

View File

@@ -0,0 +1,123 @@
"""
The `cretonne.immediates` module predefines all the Cretonne immediate operand
types.
"""
from __future__ import absolute_import
from cdsl.operands import ImmediateKind
#: A 64-bit immediate integer operand.
#:
#: This type of immediate integer can interact with SSA values with any
#: :py:class:`cretonne.IntType` type.
imm64 = ImmediateKind('imm64', 'A 64-bit immediate integer.')
#: An unsigned 8-bit immediate integer operand.
#:
#: This small operand is used to indicate lane indexes in SIMD vectors and
#: immediate bit counts on shift instructions.
uimm8 = ImmediateKind('uimm8', 'An 8-bit immediate unsigned integer.')
#: An unsigned 32-bit immediate integer operand.
uimm32 = ImmediateKind('uimm32', 'A 32-bit immediate unsigned integer.')
#: A 32-bit immediate signed offset.
#:
#: This is used to represent an immediate address offset in load/store
#: instructions.
offset32 = ImmediateKind(
'offset32',
'A 32-bit immediate signed offset.',
default_member='offset')
#: A 32-bit immediate floating point operand.
#:
#: IEEE 754-2008 binary32 interchange format.
ieee32 = ImmediateKind('ieee32', 'A 32-bit immediate floating point number.')
#: A 64-bit immediate floating point operand.
#:
#: IEEE 754-2008 binary64 interchange format.
ieee64 = ImmediateKind('ieee64', 'A 64-bit immediate floating point number.')
#: An immediate boolean operand.
#:
#: This type of immediate boolean can interact with SSA values with any
#: :py:class:`cretonne.BoolType` type.
boolean = ImmediateKind('bool', 'An immediate boolean.',
rust_type='bool')
#: A condition code for comparing integer values.
#:
#: This enumerated operand kind is used for the :cton:inst:`icmp` instruction
#: and corresponds to the `condcodes::IntCC` Rust type.
intcc = ImmediateKind(
'intcc',
'An integer comparison condition code.',
default_member='cond',
rust_type='ir::condcodes::IntCC',
values={
'eq': 'Equal',
'ne': 'NotEqual',
'sge': 'SignedGreaterThanOrEqual',
'sgt': 'SignedGreaterThan',
'sle': 'SignedLessThanOrEqual',
'slt': 'SignedLessThan',
'uge': 'UnsignedGreaterThanOrEqual',
'ugt': 'UnsignedGreaterThan',
'ule': 'UnsignedLessThanOrEqual',
'ult': 'UnsignedLessThan',
})
#: A condition code for comparing floating point values.
#:
#: This enumerated operand kind is used for the :cton:inst:`fcmp` instruction
#: and corresponds to the `condcodes::FloatCC` Rust type.
floatcc = ImmediateKind(
'floatcc',
'A floating point comparison condition code.',
default_member='cond',
rust_type='ir::condcodes::FloatCC',
values={
'ord': 'Ordered',
'uno': 'Unordered',
'eq': 'Equal',
'ne': 'NotEqual',
'one': 'OrderedNotEqual',
'ueq': 'UnorderedOrEqual',
'lt': 'LessThan',
'le': 'LessThanOrEqual',
'gt': 'GreaterThan',
'ge': 'GreaterThanOrEqual',
'ult': 'UnorderedOrLessThan',
'ule': 'UnorderedOrLessThanOrEqual',
'ugt': 'UnorderedOrGreaterThan',
'uge': 'UnorderedOrGreaterThanOrEqual',
})
#: Flags for memory operations like :cton:inst:`load` and :cton:inst:`store`.
memflags = ImmediateKind(
'memflags',
'Memory operation flags',
default_member='flags', rust_type='ir::MemFlags')
#: A register unit in the current target ISA.
regunit = ImmediateKind(
'regunit',
'A register unit in the target ISA',
rust_type='isa::RegUnit')
#: A trap code indicating the reason for trapping.
#:
#: The Rust enum type also has a `User(u16)` variant for user-provided trap
#: codes.
trapcode = ImmediateKind(
'trapcode',
'A trap reason code.',
default_member='code',
rust_type='ir::TrapCode',
values={
"stk_ovf": 'StackOverflow',
"heap_oob": 'HeapOutOfBounds',
"int_ovf": 'IntegerOverflow',
"int_divz": 'IntegerDivisionByZero',
})

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,295 @@
"""
Patterns for legalizing the `base` instruction set.
The base Cretonne instruction set is 'fat', and many instructions don't have
legal representations in a given target ISA. This module defines legalization
patterns that describe how base instructions can be transformed to other base
instructions that are legal.
"""
from __future__ import absolute_import
from .immediates import intcc, imm64, ieee32, ieee64
from . import instructions as insts
from . import types
from .instructions import iadd, iadd_cout, iadd_cin, iadd_carry, iadd_imm
from .instructions import isub, isub_bin, isub_bout, isub_borrow, irsub_imm
from .instructions import imul, imul_imm
from .instructions import sdiv, sdiv_imm, udiv, udiv_imm
from .instructions import srem, srem_imm, urem, urem_imm
from .instructions import band, bor, bxor, isplit, iconcat
from .instructions import bnot, band_not, bor_not, bxor_not
from .instructions import band_imm, bor_imm, bxor_imm
from .instructions import icmp, icmp_imm, ifcmp, ifcmp_imm
from .instructions import iconst, bint, select
from .instructions import ishl, ishl_imm, sshr, sshr_imm, ushr, ushr_imm
from .instructions import rotl, rotl_imm, rotr, rotr_imm
from .instructions import f32const, f64const
from cdsl.ast import Var
from cdsl.xform import Rtl, XFormGroup
narrow = XFormGroup('narrow', """
Legalize instructions by narrowing.
The transformations in the 'narrow' group work by expressing
instructions in terms of smaller types. Operations on vector types are
expressed in terms of vector types with fewer lanes, and integer
operations are expressed in terms of smaller integer types.
""")
widen = XFormGroup('widen', """
Legalize instructions by widening.
The transformations in the 'widen' group work by expressing
instructions in terms of larger types.
This group is not yet implemented.
""")
expand = XFormGroup('expand', """
Legalize instructions by expansion.
Rewrite instructions in terms of other instructions, generally
operating on the same types as the original instructions.
""")
expand_flags = XFormGroup('expand_flags', """
Instruction expansions for architectures with flags.
Expand some instructions using CPU flags, then fall back to the normal
expansions. Not all architectures support CPU flags, so these patterns
are kept separate.
""", chain=expand)
# Custom expansions for memory objects.
expand.custom_legalize(insts.global_addr, 'expand_global_addr')
expand.custom_legalize(insts.heap_addr, 'expand_heap_addr')
# Custom expansions for calls.
expand.custom_legalize(insts.call, 'expand_call')
# Custom expansions that need to change the CFG.
# TODO: Add sufficient XForm syntax that we don't need to hand-code these.
expand.custom_legalize(insts.trapz, 'expand_cond_trap')
expand.custom_legalize(insts.trapnz, 'expand_cond_trap')
expand.custom_legalize(insts.br_table, 'expand_br_table')
expand.custom_legalize(insts.select, 'expand_select')
# Custom expansions for floating point constants.
# These expansions require bit-casting or creating constant pool entries.
expand.custom_legalize(insts.f32const, 'expand_fconst')
expand.custom_legalize(insts.f64const, 'expand_fconst')
x = Var('x')
y = Var('y')
a = Var('a')
a1 = Var('a1')
a2 = Var('a2')
b = Var('b')
b1 = Var('b1')
b2 = Var('b2')
b_in = Var('b_in')
b_int = Var('b_int')
c = Var('c')
c1 = Var('c1')
c2 = Var('c2')
c_in = Var('c_in')
c_int = Var('c_int')
xl = Var('xl')
xh = Var('xh')
yl = Var('yl')
yh = Var('yh')
al = Var('al')
ah = Var('ah')
cc = Var('cc')
narrow.legalize(
a << iadd(x, y),
Rtl(
(xl, xh) << isplit(x),
(yl, yh) << isplit(y),
(al, c) << iadd_cout(xl, yl),
ah << iadd_cin(xh, yh, c),
a << iconcat(al, ah)
))
narrow.legalize(
a << isub(x, y),
Rtl(
(xl, xh) << isplit(x),
(yl, yh) << isplit(y),
(al, b) << isub_bout(xl, yl),
ah << isub_bin(xh, yh, b),
a << iconcat(al, ah)
))
for bitop in [band, bor, bxor]:
narrow.legalize(
a << bitop(x, y),
Rtl(
(xl, xh) << isplit(x),
(yl, yh) << isplit(y),
al << bitop(xl, yl),
ah << bitop(xh, yh),
a << iconcat(al, ah)
))
narrow.legalize(
a << select(c, x, y),
Rtl(
(xl, xh) << isplit(x),
(yl, yh) << isplit(y),
al << select(c, xl, yl),
ah << select(c, xh, yh),
a << iconcat(al, ah)
))
# Expand integer operations with carry for RISC architectures that don't have
# the flags.
expand.legalize(
(a, c) << iadd_cout(x, y),
Rtl(
a << iadd(x, y),
c << icmp(intcc.ult, a, x)
))
expand.legalize(
(a, b) << isub_bout(x, y),
Rtl(
a << isub(x, y),
b << icmp(intcc.ugt, a, x)
))
expand.legalize(
a << iadd_cin(x, y, c),
Rtl(
a1 << iadd(x, y),
c_int << bint(c),
a << iadd(a1, c_int)
))
expand.legalize(
a << isub_bin(x, y, b),
Rtl(
a1 << isub(x, y),
b_int << bint(b),
a << isub(a1, b_int)
))
expand.legalize(
(a, c) << iadd_carry(x, y, c_in),
Rtl(
(a1, c1) << iadd_cout(x, y),
c_int << bint(c_in),
(a, c2) << iadd_cout(a1, c_int),
c << bor(c1, c2)
))
expand.legalize(
(a, b) << isub_borrow(x, y, b_in),
Rtl(
(a1, b1) << isub_bout(x, y),
b_int << bint(b_in),
(a, b2) << isub_bout(a1, b_int),
b << bor(b1, b2)
))
# Expansions for immediate operands that are out of range.
for inst_imm, inst in [
(iadd_imm, iadd),
(imul_imm, imul),
(sdiv_imm, sdiv),
(udiv_imm, udiv),
(srem_imm, srem),
(urem_imm, urem),
(band_imm, band),
(bor_imm, bor),
(bxor_imm, bor),
(ifcmp_imm, ifcmp)]:
expand.legalize(
a << inst_imm(x, y),
Rtl(
a1 << iconst(y),
a << inst(x, a1)
))
expand.legalize(
a << irsub_imm(y, x),
Rtl(
a1 << iconst(x),
a << isub(a1, y)
))
# Rotates and shifts.
for inst_imm, inst in [
(rotl_imm, rotl),
(rotr_imm, rotr),
(ishl_imm, ishl),
(sshr_imm, sshr),
(ushr_imm, ushr)]:
expand.legalize(
a << inst_imm(x, y),
Rtl(
a1 << iconst.i32(y),
a << inst(x, a1)
))
expand.legalize(
a << icmp_imm(cc, x, y),
Rtl(
a1 << iconst(y),
a << icmp(cc, x, a1)
))
# Expansions for *_not variants of bitwise ops.
for inst_not, inst in [
(band_not, band),
(bor_not, bor),
(bxor_not, bxor)]:
expand.legalize(
a << inst_not(x, y),
Rtl(
a1 << bnot(y),
a << inst(x, a1)
))
# Floating-point sign manipulations.
for ty, minus_zero in [
(types.f32, f32const(ieee32.bits(0x80000000))),
(types.f64, f64const(ieee64.bits(0x8000000000000000)))]:
expand.legalize(
a << insts.fabs.bind(ty)(x),
Rtl(
b << minus_zero,
a << band_not(x, b),
))
expand.legalize(
a << insts.fneg.bind(ty)(x),
Rtl(
b << minus_zero,
a << bxor(x, b),
))
expand.legalize(
a << insts.fcopysign.bind(ty)(x, y),
Rtl(
b << minus_zero,
a1 << band_not(x, b),
a2 << band(y, b),
a << bor(a1, a2)
))
# Expansions using CPU flags.
expand_flags.custom_legalize(insts.stack_check, 'expand_stack_check')
expand_flags.legalize(
insts.trapnz(x, c),
Rtl(
a << insts.ifcmp_imm(x, imm64(0)),
insts.trapif(intcc.ne, a, c)
))
expand_flags.legalize(
insts.trapz(x, c),
Rtl(
a << insts.ifcmp_imm(x, imm64(0)),
insts.trapif(intcc.eq, a, c)
))

View File

@@ -0,0 +1,35 @@
"""
Cretonne predicates that consider `Function` fields.
"""
from cdsl.predicates import FieldPredicate
from .formats import UnaryGlobalVar
try:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from cdsl.formats import FormatField # noqa
except ImportError:
pass
class IsColocatedFunc(FieldPredicate):
"""
An instruction predicate that checks the referenced function is colocated.
"""
def __init__(self, field):
# type: (FormatField) -> None
super(IsColocatedFunc, self).__init__(
field, 'is_colocated_func', ('func',))
class IsColocatedData(FieldPredicate):
"""
An instruction predicate that checks the referenced data object is
colocated.
"""
def __init__(self):
# type: () -> None
super(IsColocatedData, self).__init__(
UnaryGlobalVar.global_var, 'is_colocated_data', ('func',))

View File

@@ -0,0 +1,218 @@
from __future__ import absolute_import
from semantics.primitives import prim_to_bv, prim_from_bv, bvsplit, bvconcat,\
bvadd, bvzeroext, bvsignext
from semantics.primitives import bveq, bvne, bvsge, bvsgt, bvsle, bvslt,\
bvuge, bvugt, bvule, bvult
from semantics.macros import bool2bv
from .instructions import vsplit, vconcat, iadd, iadd_cout, icmp, bextend, \
isplit, iconcat, iadd_cin, iadd_carry
from .immediates import intcc
from cdsl.xform import Rtl, XForm
from cdsl.ast import Var
from cdsl.typevar import TypeSet
from cdsl.ti import InTypeset
try:
from typing import TYPE_CHECKING # noqa
if TYPE_CHECKING:
from cdsl.ast import Enumerator # noqa
from cdsl.instructions import Instruction # noqa
except ImportError:
TYPE_CHECKING = False
x = Var('x')
y = Var('y')
a = Var('a')
b = Var('b')
c_out = Var('c_out')
c_in = Var('c_in')
CC = Var('CC')
bc_out = Var('bc_out')
bvc_out = Var('bvc_out')
bvc_in = Var('bvc_in')
xhi = Var('xhi')
yhi = Var('yhi')
ahi = Var('ahi')
bhi = Var('bhi')
xlo = Var('xlo')
ylo = Var('ylo')
alo = Var('alo')
blo = Var('blo')
lo = Var('lo')
hi = Var('hi')
bvx = Var('bvx')
bvy = Var('bvy')
bva = Var('bva')
bvt = Var('bvt')
bvs = Var('bvs')
bva_wide = Var('bva_wide')
bvlo = Var('bvlo')
bvhi = Var('bvhi')
ScalarTS = TypeSet(lanes=(1, 1), ints=True, floats=True, bools=True)
vsplit.set_semantics(
(lo, hi) << vsplit(x),
Rtl(
bvx << prim_to_bv(x),
(bvlo, bvhi) << bvsplit(bvx),
lo << prim_from_bv(bvlo),
hi << prim_from_bv(bvhi)
))
vconcat.set_semantics(
x << vconcat(lo, hi),
Rtl(
bvlo << prim_to_bv(lo),
bvhi << prim_to_bv(hi),
bvx << bvconcat(bvlo, bvhi),
x << prim_from_bv(bvx)
))
iadd.set_semantics(
a << iadd(x, y),
(Rtl(
bvx << prim_to_bv(x),
bvy << prim_to_bv(y),
bva << bvadd(bvx, bvy),
a << prim_from_bv(bva)
), [InTypeset(x.get_typevar(), ScalarTS)]),
Rtl(
(xlo, xhi) << vsplit(x),
(ylo, yhi) << vsplit(y),
alo << iadd(xlo, ylo),
ahi << iadd(xhi, yhi),
a << vconcat(alo, ahi)
))
#
# Integer arithmetic with carry and/or borrow.
#
iadd_cin.set_semantics(
a << iadd_cin(x, y, c_in),
Rtl(
bvx << prim_to_bv(x),
bvy << prim_to_bv(y),
bvc_in << prim_to_bv(c_in),
bvs << bvzeroext(bvc_in),
bvt << bvadd(bvx, bvy),
bva << bvadd(bvt, bvs),
a << prim_from_bv(bva)
))
iadd_cout.set_semantics(
(a, c_out) << iadd_cout(x, y),
Rtl(
bvx << prim_to_bv(x),
bvy << prim_to_bv(y),
bva << bvadd(bvx, bvy),
bc_out << bvult(bva, bvx),
bvc_out << bool2bv(bc_out),
a << prim_from_bv(bva),
c_out << prim_from_bv(bvc_out)
))
iadd_carry.set_semantics(
(a, c_out) << iadd_carry(x, y, c_in),
Rtl(
bvx << prim_to_bv(x),
bvy << prim_to_bv(y),
bvc_in << prim_to_bv(c_in),
bvs << bvzeroext(bvc_in),
bvt << bvadd(bvx, bvy),
bva << bvadd(bvt, bvs),
bc_out << bvult(bva, bvx),
bvc_out << bool2bv(bc_out),
a << prim_from_bv(bva),
c_out << prim_from_bv(bvc_out)
))
bextend.set_semantics(
a << bextend(x),
(Rtl(
bvx << prim_to_bv(x),
bvy << bvsignext(bvx),
a << prim_from_bv(bvy)
), [InTypeset(x.get_typevar(), ScalarTS)]),
Rtl(
(xlo, xhi) << vsplit(x),
alo << bextend(xlo),
ahi << bextend(xhi),
a << vconcat(alo, ahi)
))
def create_comp_xform(cc, bvcmp_func):
# type: (Enumerator, Instruction) -> XForm
ba = Var('ba')
return XForm(
Rtl(
a << icmp(cc, x, y)
),
Rtl(
bvx << prim_to_bv(x),
bvy << prim_to_bv(y),
ba << bvcmp_func(bvx, bvy),
bva << bool2bv(ba),
bva_wide << bvzeroext(bva),
a << prim_from_bv(bva_wide),
),
constraints=InTypeset(x.get_typevar(), ScalarTS))
icmp.set_semantics(
a << icmp(CC, x, y),
Rtl(
(xlo, xhi) << vsplit(x),
(ylo, yhi) << vsplit(y),
alo << icmp(CC, xlo, ylo),
ahi << icmp(CC, xhi, yhi),
b << vconcat(alo, ahi),
a << bextend(b)
),
create_comp_xform(intcc.eq, bveq),
create_comp_xform(intcc.ne, bvne),
create_comp_xform(intcc.sge, bvsge),
create_comp_xform(intcc.sgt, bvsgt),
create_comp_xform(intcc.sle, bvsle),
create_comp_xform(intcc.slt, bvslt),
create_comp_xform(intcc.uge, bvuge),
create_comp_xform(intcc.ugt, bvugt),
create_comp_xform(intcc.ule, bvule),
create_comp_xform(intcc.ult, bvult))
#
# Legalization helper instructions.
#
isplit.set_semantics(
(xlo, xhi) << isplit(x),
(Rtl(
bvx << prim_to_bv(x),
(bvlo, bvhi) << bvsplit(bvx),
xlo << prim_from_bv(bvlo),
xhi << prim_from_bv(bvhi)
), [InTypeset(x.get_typevar(), ScalarTS)]),
Rtl(
(a, b) << vsplit(x),
(alo, ahi) << isplit(a),
(blo, bhi) << isplit(b),
xlo << vconcat(alo, blo),
xhi << vconcat(bhi, bhi)
))
iconcat.set_semantics(
x << iconcat(xlo, xhi),
(Rtl(
bvlo << prim_to_bv(xlo),
bvhi << prim_to_bv(xhi),
bvx << bvconcat(bvlo, bvhi),
x << prim_from_bv(bvx)
), [InTypeset(x.get_typevar(), ScalarTS)]),
Rtl(
(alo, ahi) << vsplit(xlo),
(blo, bhi) << vsplit(xhi),
a << iconcat(alo, blo),
b << iconcat(ahi, bhi),
x << vconcat(a, b),
))

View File

@@ -0,0 +1,100 @@
"""
Cretonne shared settings.
This module defines settings relevant for all code generators.
"""
from __future__ import absolute_import
from cdsl.settings import SettingGroup, BoolSetting, EnumSetting, NumSetting
group = SettingGroup('shared')
opt_level = EnumSetting(
"""
Optimization level:
- default: Very profitable optimizations enabled, none slow.
- best: Enable all optimizations
- fastest: Optimize for compile time by disabling most optimizations.
""",
'default', 'best', 'fastest')
enable_verifier = BoolSetting(
"""
Run the Cretonne IR verifier at strategic times during compilation.
This makes compilation slower but catches many bugs. The verifier is
disabled by default, except when reading Cretonne IR from a text file.
""",
default=True)
is_64bit = BoolSetting("Enable 64-bit code generation")
is_pic = BoolSetting("Enable Position-Independent Code generation")
return_at_end = BoolSetting(
"""
Generate functions with at most a single return instruction at the
end of the function.
This guarantees that functions do not have any internal return
instructions. Either they never return, or they have a single return
instruction at the end.
""")
avoid_div_traps = BoolSetting(
"""
Generate explicit checks around native division instructions to avoid
their trapping.
This is primarily used by SpiderMonkey which doesn't install a signal
handler for SIGFPE, but expects a SIGILL trap for division by zero.
On ISAs like ARM where the native division instructions don't trap,
this setting has no effect - explicit checks are always inserted.
""")
is_compressed = BoolSetting("Enable compressed instructions")
enable_float = BoolSetting(
"""
Enable the use of floating-point instructions
Disabling use of floating-point instructions is not yet implemented.
""",
default=True)
enable_simd = BoolSetting(
"""Enable the use of SIMD instructions.""",
default=True)
enable_atomics = BoolSetting(
"""Enable the use of atomic instructions""",
default=True)
#
# Settings specific to the `spiderwasm` calling convention.
#
spiderwasm_prologue_words = NumSetting(
"""
Number of pointer-sized words pushed by the spiderwasm prologue.
Functions with the `spiderwasm` calling convention don't generate their
own prologue and epilogue. They depend on externally generated code
that pushes a fixed number of words in the prologue and restores them
in the epilogue.
This setting configures the number of pointer-sized words pushed on the
stack when the Cretonne-generated code is entered. This includes the
pushed return address on x86.
""")
#
# BaldrMonkey requires that not-yet-relocated function addresses be encoded
# as all-ones bitpatterns.
#
allones_funcaddrs = BoolSetting(
"""
Emit not-yet-relocated function addresses as all-ones bit patterns.
""")
group.close(globals())

View File

@@ -0,0 +1,46 @@
"""
The base.types module predefines all the Cretonne scalar types.
"""
from __future__ import absolute_import
from cdsl.types import IntType, FloatType, BoolType, FlagsType
#: Boolean.
b1 = BoolType(1) #: 1-bit bool. Type is abstract (can't be stored in mem)
b8 = BoolType(8) #: 8-bit bool.
b16 = BoolType(16) #: 16-bit bool.
b32 = BoolType(32) #: 32-bit bool.
b64 = BoolType(64) #: 64-bit bool.
i8 = IntType(8) #: 8-bit int.
i16 = IntType(16) #: 16-bit int.
i32 = IntType(32) #: 32-bit int.
i64 = IntType(64) #: 64-bit int.
#: IEEE single precision.
f32 = FloatType(
32, """
A 32-bit floating point type represented in the IEEE 754-2008
*binary32* interchange format. This corresponds to the :c:type:`float`
type in most C implementations.
""")
#: IEEE double precision.
f64 = FloatType(
64, """
A 64-bit floating point type represented in the IEEE 754-2008
*binary64* interchange format. This corresponds to the :c:type:`double`
type in most C implementations.
""")
#: CPU flags from an integer comparison.
iflags = FlagsType(
'iflags', """
CPU flags representing the result of an integer comparison. These flags
can be tested with an :type:`intcc` condition code.
""")
#: CPU flags from a floating point comparison.
fflags = FlagsType(
'fflags', """
CPU flags representing the result of a floating point comparison. These
flags can be tested with a :type:`floatcc` condition code.
""")