mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-21 06:30:16 +00:00
move more pseudo instructions out to X86InstrCompiler.td
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115598 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d071b83b5d
commit
8af88ef157
@ -100,23 +100,6 @@ def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (extloadi32 node:$ptr))>;
|
|||||||
// Instruction list...
|
// Instruction list...
|
||||||
//
|
//
|
||||||
|
|
||||||
// ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into
|
|
||||||
// a stack adjustment and the codegen must know that they may modify the stack
|
|
||||||
// pointer before prolog-epilog rewriting occurs.
|
|
||||||
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
|
||||||
// sub / add which can clobber EFLAGS.
|
|
||||||
let Defs = [RSP, EFLAGS], Uses = [RSP] in {
|
|
||||||
def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), (ins i32imm:$amt),
|
|
||||||
"#ADJCALLSTACKDOWN",
|
|
||||||
[(X86callseq_start timm:$amt)]>,
|
|
||||||
Requires<[In64BitMode]>;
|
|
||||||
def ADJCALLSTACKUP64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
|
|
||||||
"#ADJCALLSTACKUP",
|
|
||||||
[(X86callseq_end timm:$amt1, timm:$amt2)]>,
|
|
||||||
Requires<[In64BitMode]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Miscellaneous Instructions...
|
// Miscellaneous Instructions...
|
||||||
@ -1435,40 +1418,6 @@ let AddedComplexity = 1, isReMaterializable = 1, isAsCheapAsAMove = 1 in
|
|||||||
def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src),
|
def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src),
|
||||||
"", [(set GR64:$dst, i64immZExt32:$src)]>;
|
"", [(set GR64:$dst, i64immZExt32:$src)]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Thread Local Storage Instructions
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// ELF TLS Support
|
|
||||||
// All calls clobber the non-callee saved registers. RSP is marked as
|
|
||||||
// a use to prevent stack-pointer assignments that appear immediately
|
|
||||||
// before calls from potentially appearing dead.
|
|
||||||
let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
|
|
||||||
FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1,
|
|
||||||
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
|
||||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
|
||||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
|
||||||
Uses = [RSP] in
|
|
||||||
def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
|
|
||||||
".byte\t0x66; "
|
|
||||||
"leaq\t$sym(%rip), %rdi; "
|
|
||||||
".word\t0x6666; "
|
|
||||||
"rex64; "
|
|
||||||
"call\t__tls_get_addr@PLT",
|
|
||||||
[(X86tlsaddr tls64addr:$sym)]>,
|
|
||||||
Requires<[In64BitMode]>;
|
|
||||||
|
|
||||||
// Darwin TLS Support
|
|
||||||
// For x86_64, the address of the thunk is passed in %rdi, on return
|
|
||||||
// the address of the variable is in %rax. All other registers are preserved.
|
|
||||||
let Defs = [RAX],
|
|
||||||
Uses = [RDI],
|
|
||||||
usesCustomInserter = 1 in
|
|
||||||
def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
|
|
||||||
"# TLSCall_64",
|
|
||||||
[(X86TLSCall addr:$sym)]>,
|
|
||||||
Requires<[In64BitMode]>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Atomic Instructions
|
// Atomic Instructions
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -12,6 +12,75 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// PIC base construction. This expands to code that looks like this:
|
||||||
|
// call $next_inst
|
||||||
|
// popl %destreg"
|
||||||
|
let neverHasSideEffects = 1, isNotDuplicable = 1, Uses = [ESP] in
|
||||||
|
def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label),
|
||||||
|
"", []>;
|
||||||
|
|
||||||
|
|
||||||
|
// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into
|
||||||
|
// a stack adjustment and the codegen must know that they may modify the stack
|
||||||
|
// pointer before prolog-epilog rewriting occurs.
|
||||||
|
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
||||||
|
// sub / add which can clobber EFLAGS.
|
||||||
|
let Defs = [ESP, EFLAGS], Uses = [ESP] in {
|
||||||
|
def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), (ins i32imm:$amt),
|
||||||
|
"#ADJCALLSTACKDOWN",
|
||||||
|
[(X86callseq_start timm:$amt)]>,
|
||||||
|
Requires<[In32BitMode]>;
|
||||||
|
def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
|
||||||
|
"#ADJCALLSTACKUP",
|
||||||
|
[(X86callseq_end timm:$amt1, timm:$amt2)]>,
|
||||||
|
Requires<[In32BitMode]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into
|
||||||
|
// a stack adjustment and the codegen must know that they may modify the stack
|
||||||
|
// pointer before prolog-epilog rewriting occurs.
|
||||||
|
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
||||||
|
// sub / add which can clobber EFLAGS.
|
||||||
|
let Defs = [RSP, EFLAGS], Uses = [RSP] in {
|
||||||
|
def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), (ins i32imm:$amt),
|
||||||
|
"#ADJCALLSTACKDOWN",
|
||||||
|
[(X86callseq_start timm:$amt)]>,
|
||||||
|
Requires<[In64BitMode]>;
|
||||||
|
def ADJCALLSTACKUP64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
|
||||||
|
"#ADJCALLSTACKUP",
|
||||||
|
[(X86callseq_end timm:$amt1, timm:$amt2)]>,
|
||||||
|
Requires<[In64BitMode]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// x86-64 va_start lowering magic.
|
||||||
|
let usesCustomInserter = 1 in {
|
||||||
|
def VASTART_SAVE_XMM_REGS : I<0, Pseudo,
|
||||||
|
(outs),
|
||||||
|
(ins GR8:$al,
|
||||||
|
i64imm:$regsavefi, i64imm:$offset,
|
||||||
|
variable_ops),
|
||||||
|
"#VASTART_SAVE_XMM_REGS $al, $regsavefi, $offset",
|
||||||
|
[(X86vastart_save_xmm_regs GR8:$al,
|
||||||
|
imm:$regsavefi,
|
||||||
|
imm:$offset)]>;
|
||||||
|
|
||||||
|
// Dynamic stack allocation yields _alloca call for Cygwin/Mingw targets. Calls
|
||||||
|
// to _alloca is needed to probe the stack when allocating more than 4k bytes in
|
||||||
|
// one go. Touching the stack at 4K increments is necessary to ensure that the
|
||||||
|
// guard pages used by the OS virtual memory manager are allocated in correct
|
||||||
|
// sequence.
|
||||||
|
// The main point of having separate instruction are extra unmodelled effects
|
||||||
|
// (compared to ordinary calls) like stack pointer change.
|
||||||
|
|
||||||
|
let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
|
||||||
|
def MINGW_ALLOCA : I<0, Pseudo, (outs), (ins),
|
||||||
|
"# dynamic stack allocation",
|
||||||
|
[(X86MingwAlloca)]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// EH Pseudo Instructions
|
// EH Pseudo Instructions
|
||||||
@ -32,6 +101,90 @@ def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Alias Instructions
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Alias instructions that map movr0 to xor.
|
||||||
|
// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
|
||||||
|
// FIXME: Set encoding to pseudo.
|
||||||
|
let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1,
|
||||||
|
isCodeGenOnly = 1 in {
|
||||||
|
def MOV8r0 : I<0x30, MRMInitReg, (outs GR8 :$dst), (ins), "",
|
||||||
|
[(set GR8:$dst, 0)]>;
|
||||||
|
|
||||||
|
// We want to rewrite MOV16r0 in terms of MOV32r0, because it's a smaller
|
||||||
|
// encoding and avoids a partial-register update sometimes, but doing so
|
||||||
|
// at isel time interferes with rematerialization in the current register
|
||||||
|
// allocator. For now, this is rewritten when the instruction is lowered
|
||||||
|
// to an MCInst.
|
||||||
|
def MOV16r0 : I<0x31, MRMInitReg, (outs GR16:$dst), (ins),
|
||||||
|
"",
|
||||||
|
[(set GR16:$dst, 0)]>, OpSize;
|
||||||
|
|
||||||
|
// FIXME: Set encoding to pseudo.
|
||||||
|
def MOV32r0 : I<0x31, MRMInitReg, (outs GR32:$dst), (ins), "",
|
||||||
|
[(set GR32:$dst, 0)]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Thread Local Storage Instructions
|
||||||
|
//
|
||||||
|
|
||||||
|
// ELF TLS Support
|
||||||
|
// All calls clobber the non-callee saved registers. ESP is marked as
|
||||||
|
// a use to prevent stack-pointer assignments that appear immediately
|
||||||
|
// before calls from potentially appearing dead.
|
||||||
|
let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
|
||||||
|
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
||||||
|
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||||
|
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
||||||
|
Uses = [ESP] in
|
||||||
|
def TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
|
||||||
|
"leal\t$sym, %eax; "
|
||||||
|
"call\t___tls_get_addr@PLT",
|
||||||
|
[(X86tlsaddr tls32addr:$sym)]>,
|
||||||
|
Requires<[In32BitMode]>;
|
||||||
|
|
||||||
|
// All calls clobber the non-callee saved registers. RSP is marked as
|
||||||
|
// a use to prevent stack-pointer assignments that appear immediately
|
||||||
|
// before calls from potentially appearing dead.
|
||||||
|
let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
|
||||||
|
FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1,
|
||||||
|
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
||||||
|
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||||
|
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
||||||
|
Uses = [RSP] in
|
||||||
|
def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
|
||||||
|
".byte\t0x66; "
|
||||||
|
"leaq\t$sym(%rip), %rdi; "
|
||||||
|
".word\t0x6666; "
|
||||||
|
"rex64; "
|
||||||
|
"call\t__tls_get_addr@PLT",
|
||||||
|
[(X86tlsaddr tls64addr:$sym)]>,
|
||||||
|
Requires<[In64BitMode]>;
|
||||||
|
|
||||||
|
// Darwin TLS Support
|
||||||
|
// For i386, the address of the thunk is passed on the stack, on return the
|
||||||
|
// address of the variable is in %eax. %ecx is trashed during the function
|
||||||
|
// call. All other registers are preserved.
|
||||||
|
let Defs = [EAX, ECX],
|
||||||
|
Uses = [ESP],
|
||||||
|
usesCustomInserter = 1 in
|
||||||
|
def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
|
||||||
|
"# TLSCall_32",
|
||||||
|
[(X86TLSCall addr:$sym)]>,
|
||||||
|
Requires<[In32BitMode]>;
|
||||||
|
|
||||||
|
// For x86_64, the address of the thunk is passed in %rdi, on return
|
||||||
|
// the address of the variable is in %rax. All other registers are preserved.
|
||||||
|
let Defs = [RAX],
|
||||||
|
Uses = [RDI],
|
||||||
|
usesCustomInserter = 1 in
|
||||||
|
def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
|
||||||
|
"# TLSCall_64",
|
||||||
|
[(X86TLSCall addr:$sym)]>,
|
||||||
|
Requires<[In64BitMode]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Non-Instruction Patterns
|
// Non-Instruction Patterns
|
||||||
|
@ -504,48 +504,6 @@ def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
|
|||||||
// Instruction list.
|
// Instruction list.
|
||||||
//
|
//
|
||||||
|
|
||||||
// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into
|
|
||||||
// a stack adjustment and the codegen must know that they may modify the stack
|
|
||||||
// pointer before prolog-epilog rewriting occurs.
|
|
||||||
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
|
||||||
// sub / add which can clobber EFLAGS.
|
|
||||||
let Defs = [ESP, EFLAGS], Uses = [ESP] in {
|
|
||||||
def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), (ins i32imm:$amt),
|
|
||||||
"#ADJCALLSTACKDOWN",
|
|
||||||
[(X86callseq_start timm:$amt)]>,
|
|
||||||
Requires<[In32BitMode]>;
|
|
||||||
def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
|
|
||||||
"#ADJCALLSTACKUP",
|
|
||||||
[(X86callseq_end timm:$amt1, timm:$amt2)]>,
|
|
||||||
Requires<[In32BitMode]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// x86-64 va_start lowering magic.
|
|
||||||
let usesCustomInserter = 1 in {
|
|
||||||
def VASTART_SAVE_XMM_REGS : I<0, Pseudo,
|
|
||||||
(outs),
|
|
||||||
(ins GR8:$al,
|
|
||||||
i64imm:$regsavefi, i64imm:$offset,
|
|
||||||
variable_ops),
|
|
||||||
"#VASTART_SAVE_XMM_REGS $al, $regsavefi, $offset",
|
|
||||||
[(X86vastart_save_xmm_regs GR8:$al,
|
|
||||||
imm:$regsavefi,
|
|
||||||
imm:$offset)]>;
|
|
||||||
|
|
||||||
// Dynamic stack allocation yields _alloca call for Cygwin/Mingw targets. Calls
|
|
||||||
// to _alloca is needed to probe the stack when allocating more than 4k bytes in
|
|
||||||
// one go. Touching the stack at 4K increments is necessary to ensure that the
|
|
||||||
// guard pages used by the OS virtual memory manager are allocated in correct
|
|
||||||
// sequence.
|
|
||||||
// The main point of having separate instruction are extra unmodelled effects
|
|
||||||
// (compared to ordinary calls) like stack pointer change.
|
|
||||||
|
|
||||||
let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
|
|
||||||
def MINGW_ALLOCA : I<0, Pseudo, (outs), (ins),
|
|
||||||
"# dynamic stack allocation",
|
|
||||||
[(X86MingwAlloca)]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nop
|
// Nop
|
||||||
let neverHasSideEffects = 1 in {
|
let neverHasSideEffects = 1 in {
|
||||||
def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>;
|
def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>;
|
||||||
@ -555,13 +513,6 @@ let neverHasSideEffects = 1 in {
|
|||||||
"nop{l}\t$zero", []>, TB;
|
"nop{l}\t$zero", []>, TB;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PIC base construction. This expands to code that looks like this:
|
|
||||||
// call $next_inst
|
|
||||||
// popl %destreg"
|
|
||||||
let neverHasSideEffects = 1, isNotDuplicable = 1, Uses = [ESP] in
|
|
||||||
def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label),
|
|
||||||
"", []>;
|
|
||||||
|
|
||||||
|
|
||||||
// Constructing a stack frame.
|
// Constructing a stack frame.
|
||||||
def ENTER : Ii16<0xC8, RawFrmImm8, (outs), (ins i16imm:$len, i8imm:$lvl),
|
def ENTER : Ii16<0xC8, RawFrmImm8, (outs), (ins i16imm:$len, i8imm:$lvl),
|
||||||
@ -3538,63 +3489,7 @@ let neverHasSideEffects = 1 in {
|
|||||||
"{cltd|cdq}", []>; // EDX:EAX = signext(EAX)
|
"{cltd|cdq}", []>; // EDX:EAX = signext(EAX)
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Alias Instructions
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// Alias instructions that map movr0 to xor.
|
|
||||||
// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
|
|
||||||
// FIXME: Set encoding to pseudo.
|
|
||||||
let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1,
|
|
||||||
isCodeGenOnly = 1 in {
|
|
||||||
def MOV8r0 : I<0x30, MRMInitReg, (outs GR8 :$dst), (ins), "",
|
|
||||||
[(set GR8:$dst, 0)]>;
|
|
||||||
|
|
||||||
// We want to rewrite MOV16r0 in terms of MOV32r0, because it's a smaller
|
|
||||||
// encoding and avoids a partial-register update sometimes, but doing so
|
|
||||||
// at isel time interferes with rematerialization in the current register
|
|
||||||
// allocator. For now, this is rewritten when the instruction is lowered
|
|
||||||
// to an MCInst.
|
|
||||||
def MOV16r0 : I<0x31, MRMInitReg, (outs GR16:$dst), (ins),
|
|
||||||
"",
|
|
||||||
[(set GR16:$dst, 0)]>, OpSize;
|
|
||||||
|
|
||||||
// FIXME: Set encoding to pseudo.
|
|
||||||
def MOV32r0 : I<0x31, MRMInitReg, (outs GR32:$dst), (ins), "",
|
|
||||||
[(set GR32:$dst, 0)]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Thread Local Storage Instructions
|
|
||||||
//
|
|
||||||
|
|
||||||
// ELF TLS Support
|
|
||||||
// All calls clobber the non-callee saved registers. ESP is marked as
|
|
||||||
// a use to prevent stack-pointer assignments that appear immediately
|
|
||||||
// before calls from potentially appearing dead.
|
|
||||||
let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
|
|
||||||
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
|
||||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
|
||||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
|
||||||
Uses = [ESP] in
|
|
||||||
def TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
|
|
||||||
"leal\t$sym, %eax; "
|
|
||||||
"call\t___tls_get_addr@PLT",
|
|
||||||
[(X86tlsaddr tls32addr:$sym)]>,
|
|
||||||
Requires<[In32BitMode]>;
|
|
||||||
|
|
||||||
// Darwin TLS Support
|
|
||||||
// For i386, the address of the thunk is passed on the stack, on return the
|
|
||||||
// address of the variable is in %eax. %ecx is trashed during the function
|
|
||||||
// call. All other registers are preserved.
|
|
||||||
let Defs = [EAX, ECX],
|
|
||||||
Uses = [ESP],
|
|
||||||
usesCustomInserter = 1 in
|
|
||||||
def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
|
|
||||||
"# TLSCall_32",
|
|
||||||
[(X86TLSCall addr:$sym)]>,
|
|
||||||
Requires<[In32BitMode]>;
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Atomic support
|
// Atomic support
|
||||||
|
Loading…
x
Reference in New Issue
Block a user