SlideShare une entreprise Scribd logo
1  sur  112
Télécharger pour lire hors ligne
Min-Yih “Min” Hsu @ LLVM Dev Meeting 2021
Handling inline assembly 

in Clang and LLVM
about:me
“Min” Hsu
• Computer Science PhD Candidate in
University of California, Irvine

• Code owner of M68k LLVM backend

• Author of book “LLVM Techniques,
Tips and Best Practices” (2021)
2
How Inline Assembly is
Processed in Clang & LLVM
3
Inline Assembly
4
Introduction to inline assembly
5
void foo(...) {


int sum = 0;


bool flag = ...;


if (flag)


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);


else


sum += 87;


}


* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
5
void foo(...) {


int sum = 0;


bool flag = ...;


if (flag)


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);


else


sum += 87;


}


* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
5
void foo(...) {


int sum = 0;


bool flag = ...;


if (flag)


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);


else


sum += 87;


}


foo:


pushq %rbp


movq %rsp, %rbp


...


testb $1, -9(%rbp)


je LBB0_2


## InlineAsm Start


movl %eax, %ebx


addl %ebx, %esi


## InlineAsm End


jmp LBB0_3


LBB0_2:


movl -8(%rbp), %eax


addl $87, %eax


movl %eax, -8(%rbp)


LBB0_3:


popq %rbp


retq
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
5
void foo(...) {


int sum = 0;


bool flag = ...;


if (flag)


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);


else


sum += 87;


}


foo:


pushq %rbp


movq %rsp, %rbp


...


testb $1, -9(%rbp)


je LBB0_2


## InlineAsm Start


movl %eax, %ebx


addl %ebx, %esi


## InlineAsm End


jmp LBB0_3


LBB0_2:


movl -8(%rbp), %eax


addl $87, %eax


movl %eax, -8(%rbp)


LBB0_3:


popq %rbp


retq
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Why use inline assembly?
6
void foo(...) {


int sum = 0;


bool flag = ...;


if (flag)


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);


else


sum += 87;


}


* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Why use inline assembly?
6
void foo(...) {


int sum = 0;


bool flag = ...;


if (flag)


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);


else


sum += 87;


}


Performance critical code
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Why use inline assembly?
6
void foo(...) {


int sum = 0;


bool flag = ...;


if (flag)


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);


else


sum += 87;


}


Performance critical code
Low-level code

e.g. Kernel, firmware
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Why use inline assembly?
6
void foo(...) {


int sum = 0;


bool flag = ...;


if (flag)


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);


else


sum += 87;


}


Performance critical code
Low-level code

e.g. Kernel, firmware
Compiler optimizations “barrier”
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
7
asm (“movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
7
asm (“movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);
Assembly code (template)
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
7
asm (“movl %%eax, %%ebxn"


"addl %%ebx, %%esi" :::);
Assembly code (template)
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Output operands
8
int out_var;


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %0"


: "=r"(out_var) ::);
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Output operands
8
int out_var;


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %0"


: "=r"(out_var) ::);
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Output operands
8
int out_var;


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %0"


: "=r"(out_var) ::);
Operand constraints
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Operands constraints
9
int out_var;


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %0"


: "=r"(out_var) ::);
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Operands constraints
9
int out_var;


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %0"


: "=r"(out_var) ::);
* x86_64 assembly w/ AT&T syntax
## InlineAsm Start


movl %eax, %ebx


addl %ebx, %esi


## InlineAsm End
Introduction to inline assembly
Operands constraints
9
int out_var;


asm ("movl %%eax, %%ebxn"


"addl %%ebx, %0"


: "=r"(out_var) ::);
* x86_64 assembly w/ AT&T syntax
## InlineAsm Start


movl %eax, %ebx


addl %ebx, %esi


## InlineAsm End
## InlineAsm Start


movl %eax, %ebx


addl %ebx, -8(%ebp)


## InlineAsm End
Operand constraints
10
Operand constraints
10
• ‘r’ : General-purpose register operand

• ‘i’ : Immediate integer operand

• ‘m’ : Memory operand w/ arbitrary addressing mode
Target-independent Constraints
Operand constraints
10
• ‘r’ : General-purpose register operand

• ‘i’ : Immediate integer operand

• ‘m’ : Memory operand w/ arbitrary addressing mode
Target-independent Constraints
• ‘a’ : AL / AH / EAX / RAX

• ‘I’ : Integer constant in the range of [0, 31]

• ‘N’ : Unsigned 8-bit integer constant
X86 Constraints
Operand constraints
10
• ‘r’ : General-purpose register operand

• ‘i’ : Immediate integer operand

• ‘m’ : Memory operand w/ arbitrary addressing mode
Target-independent Constraints
• ‘a’ : AL / AH / EAX / RAX

• ‘I’ : Integer constant in the range of [0, 31]

• ‘N’ : Unsigned 8-bit integer constant
X86 Constraints
• ‘J’ : 16-bit signed integer constant

• “Ci” : Constant integers

• “Cj” : Constant signed integers that do NOT
fi
t in 16 bits
M68k Constraints
Operand constraints
10
• ‘r’ : General-purpose register operand

• ‘i’ : Immediate integer operand

• ‘m’ : Memory operand w/ arbitrary addressing mode
Constraint Modifers
Target-independent Constraints
• ‘=‘ : This is an output operand

• ‘+’ : This is an input / output operand
• ‘a’ : AL / AH / EAX / RAX

• ‘I’ : Integer constant in the range of [0, 31]

• ‘N’ : Unsigned 8-bit integer constant
X86 Constraints
• ‘J’ : 16-bit signed integer constant

• “Ci” : Constant integers

• “Cj” : Constant signed integers that do NOT
fi
t in 16 bits
M68k Constraints
Introduction to inline assembly
Input operands
11
int out_var, in_var;


asm ("movl %1, %%ebxn"


"addl %%ebx, %0"


: “=r"(out_var)


: “r”(in_var) :);
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Input operands
11
int out_var, in_var;


asm ("movl %1, %%ebxn"


"addl %%ebx, %0"


: “=r"(out_var)


: “r”(in_var) :);
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Input operands
11
int out_var, in_var;


asm ("movl %1, %%ebxn"


"addl %%ebx, %0"


: “=r"(out_var)


: “r”(in_var) :);
Operand constraints
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Clobber operands
12
int out_var, in_var;


asm ("movl %1, %%ebxn"


"addl %%ebx, %0"


: “=r"(out_var)


: “r”(in_var)


: “ebx”);
* x86_64 assembly w/ AT&T syntax
Introduction to inline assembly
Clobber operands
12
int out_var, in_var;


asm ("movl %1, %%ebxn"


"addl %%ebx, %0"


: “=r"(out_var)


: “r”(in_var)


: “ebx”);
* x86_64 assembly w/ AT&T syntax
For more inline assembly syntax…
13
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
Handling inline assembly in Clang & LLVM
Background
14
Handling inline assembly in Clang & LLVM
Background
• Most parts of an inline assembly string are simply copied into the
fi
nal
assembly
fi
le
14
Handling inline assembly in Clang & LLVM
Background
• Most parts of an inline assembly string are simply copied into the
fi
nal
assembly
fi
le
• LLVM needs to “glue” inline assembly operands with the surrounding code
14
Handling inline assembly in Clang & LLVM
Background
• Most parts of an inline assembly string are simply copied into the
fi
nal
assembly
fi
le
• LLVM needs to “glue” inline assembly operands with the surrounding code
• Lots of target-speci
fi
c logics

• In both Clang and the backend
14
Handling inline assembly in Clang & LLVM
Background
• Most parts of an inline assembly string are simply copied into the
fi
nal
assembly
fi
le
• LLVM needs to “glue” inline assembly operands with the surrounding code
• Lots of target-speci
fi
c logics

• In both Clang and the backend
• Target-speci
fi
c callbacks are scattered in the codebase

• Documentation for this part is a little…shy
14
Goals
15
Goals
Learning inline assembly workflow in Clang / LLVM
15
Goals
Learning inline assembly workflow in Clang / LLVM
A simple guide for backend developers to add inline assembly support
15
Outline of target-specific logics in each stage
16
Clang
Lowering
LLVM IR
Machine IR
AsmPrinter
Outline of target-specific logics in each stage
16
Clang
Lowering
LLVM IR
Machine IR
AsmPrinter
• Simple validation on operand constraints

• Converting constraints
Outline of target-specific logics in each stage
16
Clang
Lowering
LLVM IR
Machine IR
AsmPrinter
• Simple validation on operand constraints

• Converting constraints
• Classifying constraints

• Constraint validations

• Lowering the operands
Outline of target-specific logics in each stage
16
Clang
Lowering
LLVM IR
Machine IR
AsmPrinter
• Simple validation on operand constraints

• Converting constraints
• Classifying constraints

• Constraint validations

• Lowering the operands
Print out di
ff
erent types of operands
Outline of target-specific logics in each stage
17
Clang
Lowering
LLVM IR
Machine IR
AsmPrinter
• Simple validation on operand constraints

• Converting constraints
• Classifying constraints

• Constraint validations

• Lowering the operands
Print out di
ff
erent types of operands
Operand constraint validations in Clang
18
bool TargetInfo::validateAsmConstraint(const char *&, ConstraintInfo &) const;
Operand constraint validations in Clang
18
bool TargetInfo::validateAsmConstraint(const char *&, ConstraintInfo &) const;
bool M68kTargetInfo::validateAsmConstraint(const char *&Name, ConstraintInfo &info) const {


switch (*Name) {


case 'a': // address register


info.setAllowsRegister();


return true;


}


…


}
Operand constraint validations in Clang
19
bool TargetInfo::validateAsmConstraint(const char *&, ConstraintInfo &) const;
bool M68kTargetInfo::validateAsmConstraint(const char *&Name, ConstraintInfo &info) const {


switch (*Name) {


case 'a': // address register


info.setAllowsRegister();


return true;


case 'J': // constant signed 16-bit integer


info.setRequiresImmediate(std::numeric_limits<int16_t>::min(),


std::numeric_limits<int16_t>::max());


return true;


}


…


}
Operand constraint validations in Clang
Limitation on immediate value validations
20
void foo() {


int32_t x;


asm ("move.l %0, %%d1" : : "J" (x));


}
* M68k assembly w/ Motorola syntax
Operand constraint validations in Clang
Limitation on immediate value validations
20
void foo() {


int32_t x;


asm ("move.l %0, %%d1" : : "J" (x));


}
Constant signed 16-bit integer
* M68k assembly w/ Motorola syntax
Operand constraint validations in Clang
Limitation on immediate value validations
20
void foo() {


int32_t x;


asm ("move.l %0, %%d1" : : "J" (x));


}
$ clang -target m68k -fsyntax-only foo.c


# No error


$ clang -target m68k -emit-llvm foo.c


# No error
Constant signed 16-bit integer
* M68k assembly w/ Motorola syntax
Operand constraint validations in Clang
Limitation on immediate value validations
20
void foo() {


int32_t x;


asm ("move.l %0, %%d1" : : "J" (x));


}
$ clang -target m68k -fsyntax-only foo.c


# No error


$ clang -target m68k -emit-llvm foo.c


# No error
Constant signed 16-bit integer
$ clang -target m68k -S foo.c


error: constraint 'J' expects an integer constant expression
* M68k assembly w/ Motorola syntax
Inline assembly in LLVM IR
21
void foo() {


const int x = 87;


asm ("move.l %0, %%d1" : : "Ci" (x) : "d1");


}
C/C++
* M68k assembly w/ Motorola syntax
Inline assembly in LLVM IR
21
void foo() {


const int x = 87;


asm ("move.l %0, %%d1" : : "Ci" (x) : "d1");


}
C/C++
call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
LLVM IR
* M68k assembly w/ Motorola syntax
Inline assembly in LLVM IR
21
void foo() {


const int x = 87;


asm ("move.l %0, %%d1" : : "Ci" (x) : "d1");


}
C/C++
call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
LLVM IR
* M68k assembly w/ Motorola syntax
Inline assembly in LLVM IR
21
void foo() {


const int x = 87;


asm ("move.l %0, %%d1" : : "Ci" (x) : "d1");


}
C/C++
call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
LLVM IR
* M68k assembly w/ Motorola syntax
Inline assembly in LLVM IR
21
void foo() {


const int x = 87;


asm ("move.l %0, %%d1" : : "Ci" (x) : "d1");


}
C/C++
call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
LLVM IR
* M68k assembly w/ Motorola syntax
Inline assembly in LLVM IR
21
void foo() {


const int x = 87;


asm ("move.l %0, %%d1" : : "Ci" (x) : "d1");


}
C/C++
call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
LLVM IR
* M68k assembly w/ Motorola syntax
Outline of target-specific logics in each stage
22
Clang
Lowering
LLVM IR
Machine IR
AsmPrinter
• Simple validation on operand constraints

• Converting constraints
• Classifying constraints

• Constraint validations

• Lowering the operands
Print out di
ff
erent types of operands
23
LLVM IR call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
23
LLVM IR
SelectionDAG
call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
t2: ch,glue = inlineasm ... "move.l $0, %d1", ...,


TargetConstant:i32<87>, Register:i16 $d1
23
LLVM IR
SelectionDAG
Machine IR
call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1
t2: ch,glue = inlineasm ... "move.l $0, %d1", ...,


TargetConstant:i32<87>, Register:i16 $d1
23
LLVM IR
SelectionDAG
Machine IR
call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1
t2: ch,glue = inlineasm ... "move.l $0, %d1", ...,


TargetConstant:i32<87>, Register:i16 $d1
Constraint classification
24
TargetLowering::ConstraintType


M68kTargetLowering::getConstraintType(StringRef Constraint) const;
Constraint classification
24
TargetLowering::ConstraintType


M68kTargetLowering::getConstraintType(StringRef Constraint) const;
Return:
Constraint classification
24
TargetLowering::ConstraintType


M68kTargetLowering::getConstraintType(StringRef Constraint) const;
• C_RegisterClass
Return:
Ex: ’r’
Constraint classification
24
TargetLowering::ConstraintType


M68kTargetLowering::getConstraintType(StringRef Constraint) const;
• C_RegisterClass
• C_Immediate
Return:
Ex: ’r’
Ex: ‘i’
Constraint classification
24
TargetLowering::ConstraintType


M68kTargetLowering::getConstraintType(StringRef Constraint) const;
• C_RegisterClass
• C_Immediate
• C_Memory
Return:
Ex: ’r’
Ex: ‘i’
Ex: ‘m’, ‘Q’ (AArch64)
Constraint classification
24
TargetLowering::ConstraintType


M68kTargetLowering::getConstraintType(StringRef Constraint) const;
• C_RegisterClass
• C_Immediate
• C_Memory
• C_Other
Return:
Ex: ’r’
Ex: ‘i’
Ex: ‘m’, ‘Q’ (AArch64)
Lowering operands
25
getConstraintType
Method in XXXTargetLowering
Method in XXXISelDAGToDAG
Will be invoked
Lowering operands
25
getConstraintType
getRegForInlineAsmConstraint
C_RegisterClass
Method in XXXTargetLowering
Method in XXXISelDAGToDAG
Will be invoked
Lowering operands
25
getConstraintType
getRegForInlineAsmConstraint
LowerAsmOperandForConstraint
C_RegisterClass
C_Immediate / C_Other
Method in XXXTargetLowering
Method in XXXISelDAGToDAG
Will be invoked
Lowering operands
25
getConstraintType
getRegForInlineAsmConstraint
getInlineAsmMemConstraint
LowerAsmOperandForConstraint
C_RegisterClass
C_Immediate / C_Other
C_Memory
Method in XXXTargetLowering
Method in XXXISelDAGToDAG
Will be invoked
Lowering operands
25
getConstraintType
getRegForInlineAsmConstraint
getInlineAsmMemConstraint
LowerAsmOperandForConstraint
SelectInlineAsmMemoryOperand
C_RegisterClass
C_Immediate / C_Other
C_Memory
Method in XXXTargetLowering
Method in XXXISelDAGToDAG
Will be invoked
Lowering register operands
26
std::pair<unsigned, const TargetRegisterClass *>


TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,


StringRef Constraint,


MVT VT) const;
Lowering register operands
26
std::pair<unsigned, const TargetRegisterClass *>


TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,


StringRef Constraint,


MVT VT) const;
A speci
fi
c register or 0 if not applicable
Lowering register operands
26
std::pair<unsigned, const TargetRegisterClass *>


TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,


StringRef Constraint,


MVT VT) const;
A speci
fi
c register or 0 if not applicable Valid register class to select from
Lowering register operands
M68k Example
27
std::pair<unsigned, const TargetRegisterClass *>


M68kTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *,


StringRef Constraint,


MVT VT) const {


switch (Constraint[0]) {


case 'a':


switch (VT.SimpleTy) {


case MVT::i16:


return std::make_pair(0U, &M68k::AR16RegClass);


}


}


}
Lowering register operands
M68k Example
27
std::pair<unsigned, const TargetRegisterClass *>


M68kTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *,


StringRef Constraint,


MVT VT) const {


switch (Constraint[0]) {


case 'a':


switch (VT.SimpleTy) {


case MVT::i16:


return std::make_pair(0U, &M68k::AR16RegClass);


}


}


}
Lowering register operands
X86 Example
28
std::pair<unsigned, const TargetRegisterClass *>


X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *,


StringRef Constraint,


MVT VT) const {


...


if (Constraint == "Yz") {


// First SSE register (%xmm0).


switch (VT.SimpleTy) {


case MVT::f32:


case MVT::i32:


return std::make_pair(X86::XMM0, &X86::FR32RegClass);


}


}


}
Lowering register operands
X86 Example
28
std::pair<unsigned, const TargetRegisterClass *>


X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *,


StringRef Constraint,


MVT VT) const {


...


if (Constraint == "Yz") {


// First SSE register (%xmm0).


switch (VT.SimpleTy) {


case MVT::f32:


case MVT::i32:


return std::make_pair(X86::XMM0, &X86::FR32RegClass);


}


}


}
Lowering immediate / other operands
29
void TargetLowering::


LowerAsmOperandForConstraint(SDValue Op,


std::string &Constraint,


std::vector<SDValue> &Ops,


SelectionDAG &DAG) const;
Lowering immediate / other operands
M68k Example
30
void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op,


std::string &Constraint,


std::vector<SDValue> &Ops,


SelectionDAG &DAG) const {


switch (Constraint[0]) {


case 'J': { // constant signed 16-bit integer


}


}


}
Lowering immediate / other operands
M68k Example
31
void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op,


std::string &Constraint,


std::vector<SDValue> &Ops,


SelectionDAG &DAG) const {


switch (Constraint[0]) {


case 'J': { // constant signed 16-bit integer


if (auto *C = dyn_cast<ConstantSDNode>(Op)) {


int64_t Val = C->getSExtValue();


}


}


}


}
Lowering immediate / other operands
M68k Example
32
void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op,


std::string &Constraint,


std::vector<SDValue> &Ops,


SelectionDAG &DAG) const {


switch (Constraint[0]) {


case 'J': { // constant signed 16-bit integer


if (auto *C = dyn_cast<ConstantSDNode>(Op)) {


int64_t Val = C->getSExtValue();


if (isInt<16>(Val)) {


Ops.push_back(Op);


return;


}


}


}


}


}
Lowering memory operands
Memory constraint classi
fi
cation
33
unsigned TargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const;
Lowering memory operands
Memory constraint classi
fi
cation
33
unsigned TargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const;
Return:
Lowering memory operands
Memory constraint classi
fi
cation
33
unsigned TargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const;
• InlineAsm::Constraint_m


• InlineAsm::Constraint_o


• InlineAsm::Constraint_v
Return:
Generic memory constraints
Lowering memory operands
Memory constraint classi
fi
cation
33
unsigned TargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const;
• InlineAsm::Constraint_m


• InlineAsm::Constraint_o


• InlineAsm::Constraint_v
Return:
• InlineAsm::Constraint_A


• InlineAsm::Constraint_Q
Generic memory constraints
Target-speci
fi
c constraints!
Lowering memory operands
Memory constraint classi
fi
cation — RISCV Example
34
unsigned RISCVTargetLowering::


getInlineAsmMemConstraint(StringRef ConstraintCode) const {


switch (ConstraintCode[0]) {


case 'A':


return InlineAsm::Constraint_A;


...


}


...


}
Lowering memory operands
35
bool


SelectionDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,


unsigned ConstraintID,


std::vector<SDValue> &OutOps);
Lowering memory operands
RISCV Example
36
bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand(


const SDValue &Op, unsigned ConstraintID,


std::vector<SDValue> &OutOps) {


switch (ConstraintID) {


case InlineAsm::Constraint_A:


OutOps.push_back(Op);


return false;


default:


break;


}




return true;


}
Lowering memory operands
Complex addressing mode — X86 Example
37
bool X86DAGToDAGISel::


SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,


std::vector<SDValue> &OutOps) {


SDValue Op0, Op1, Op2, Op3, Op4;




switch (ConstraintID) {


case InlineAsm::Constraint_m: // memory


if (!selectAddr(nullptr, Op, Op0, Op1, Op2, Op3, Op4))


return true;


break;


}


OutOps.insert(OutOps.end(), {Op0, Op1, Op2, Op3, Op4});


return false;


}
Lowering memory operands
Complex addressing mode — X86 Example
37
bool X86DAGToDAGISel::


SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,


std::vector<SDValue> &OutOps) {


SDValue Op0, Op1, Op2, Op3, Op4;




switch (ConstraintID) {


case InlineAsm::Constraint_m: // memory


if (!selectAddr(nullptr, Op, Op0, Op1, Op2, Op3, Op4))


return true;


break;


}


OutOps.insert(OutOps.end(), {Op0, Op1, Op2, Op3, Op4});


return false;


}
Outline of target-specific logics in each stage
38
Clang
Lowering
LLVM IR
Machine IR
AsmPrinter
• Simple validation on operand constraints

• Converting constraints
• Classifying constraints

• Constraint validations

• Lowering the operands
Print out di
ff
erent types of operands
39
Machine IR
INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1
39
Machine IR
INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1
39
Machine IR
INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1
move.l #87, %d1
39
Machine IR
INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1
move.l 87, %d1
move.l #87, %d1
Printing asm operands
40
bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,


const char *, raw_ostream &O);


bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,


const char *, raw_ostream &O);
Printing non-memory asm operands
M68k Example
41
void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,


raw_ostream &OS) {


const MachineOperand &MO = MI->getOperand(OpNum);


switch (MO.getType()) {


case MachineOperand::MO_Register:


OS << "%" << M68kInstPrinter::getRegisterName(MO.getReg());


break;


case MachineOperand::MO_Immediate:


OS << '#' << MO.getImm();


break;


...


}


}
Printing non-memory asm operands
M68k Example
41
void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,


raw_ostream &OS) {


const MachineOperand &MO = MI->getOperand(OpNum);


switch (MO.getType()) {


case MachineOperand::MO_Register:


OS << "%" << M68kInstPrinter::getRegisterName(MO.getReg());


break;


case MachineOperand::MO_Immediate:


OS << '#' << MO.getImm();


break;


...


}


}
Printing non-memory asm operands
M68k Example
41
void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,


raw_ostream &OS) {


const MachineOperand &MO = MI->getOperand(OpNum);


switch (MO.getType()) {


case MachineOperand::MO_Register:


OS << "%" << M68kInstPrinter::getRegisterName(MO.getReg());


break;


case MachineOperand::MO_Immediate:


OS << '#' << MO.getImm();


break;


...


}


}
Epilogue
Advanced topics
Converting constraints in Clang

Asm dialects

Operand modifiers

Multi-alternative constraints

Constraint weights

Turn (simple) inline asm into LLVM code
43
Thank you!
44
GitHub: mshockwave

Email: minyihh@uci.edu 

25% book discount code: 25MINLLVM
Redeem:
Nov 15 ~ Nov 20, 2021
Appendix
Converting constraints in Clang
46
An operand constraint is assumed to have only a single character by default
Converting constraints in Clang
46
An operand constraint is assumed to have only a single character by default
Example: “Ci”
Converting constraints in Clang
46
An operand constraint is assumed to have only a single character by default
Example: “Ci” -> “^Ci”
Converting constraints in Clang
46
std::string


M68kTargetInfo::convertConstraint(const char *&Constraint) const override {


if (*Constraint == 'C')


// Two-character constraint; add "^" hint for later parsing


return std::string("^") + std::string(Constraint++, 2);


return std::string(1, *Constraint);


}
An operand constraint is assumed to have only a single character by default
Example: “Ci” -> “^Ci”
Operand constraint validations in Clang
Limitation on immediate value validations (cont’d)
47
bool M68kTargetInfo::validateAsmConstraint(const char *&Name, ConstraintInfo &info) const {


switch (*Name) {


…


case 'C':


++Name;


switch (*Name) {


case 'i': // constant integer


case 'j': // integer constant that doesn't fit in 16 bits


info.setRequiresImmediate();


return true;


}


break;


}


…


}

Contenu connexe

Tendances

State: You're Doing It Wrong - Alternative Concurrency Paradigms For The JVM
State: You're Doing It Wrong - Alternative Concurrency Paradigms For The JVMState: You're Doing It Wrong - Alternative Concurrency Paradigms For The JVM
State: You're Doing It Wrong - Alternative Concurrency Paradigms For The JVM
Jonas Bonér
 

Tendances (20)

Understanding of linux kernel memory model
Understanding of linux kernel memory modelUnderstanding of linux kernel memory model
Understanding of linux kernel memory model
 
LCU14-410: How to build an Energy Model for your SoC
LCU14-410: How to build an Energy Model for your SoCLCU14-410: How to build an Energy Model for your SoC
LCU14-410: How to build an Energy Model for your SoC
 
Introduction to Return-Oriented Exploitation on ARM64 - Billy Ellis
Introduction to Return-Oriented Exploitation on ARM64 - Billy EllisIntroduction to Return-Oriented Exploitation on ARM64 - Billy Ellis
Introduction to Return-Oriented Exploitation on ARM64 - Billy Ellis
 
Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)
 
Receive side scaling (RSS) with eBPF in QEMU and virtio-net
Receive side scaling (RSS) with eBPF in QEMU and virtio-netReceive side scaling (RSS) with eBPF in QEMU and virtio-net
Receive side scaling (RSS) with eBPF in QEMU and virtio-net
 
Windows 10 Nt Heap Exploitation (English version)
Windows 10 Nt Heap Exploitation (English version)Windows 10 Nt Heap Exploitation (English version)
Windows 10 Nt Heap Exploitation (English version)
 
The Forefront of the Development for NVDIMM on Linux Kernel (Linux Plumbers c...
The Forefront of the Development for NVDIMM on Linux Kernel (Linux Plumbers c...The Forefront of the Development for NVDIMM on Linux Kernel (Linux Plumbers c...
The Forefront of the Development for NVDIMM on Linux Kernel (Linux Plumbers c...
 
Page cache in Linux kernel
Page cache in Linux kernelPage cache in Linux kernel
Page cache in Linux kernel
 
[KubeCon EU 2021] Introduction and Deep Dive Into Containerd
[KubeCon EU 2021] Introduction and Deep Dive Into Containerd[KubeCon EU 2021] Introduction and Deep Dive Into Containerd
[KubeCon EU 2021] Introduction and Deep Dive Into Containerd
 
2 years with python and serverless
2 years with python and serverless2 years with python and serverless
2 years with python and serverless
 
Vmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is bootedVmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is booted
 
[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가
[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가
[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가
 
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxCon
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxConAnatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxCon
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxCon
 
Linux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKBLinux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKB
 
State: You're Doing It Wrong - Alternative Concurrency Paradigms For The JVM
State: You're Doing It Wrong - Alternative Concurrency Paradigms For The JVMState: You're Doing It Wrong - Alternative Concurrency Paradigms For The JVM
State: You're Doing It Wrong - Alternative Concurrency Paradigms For The JVM
 
GMock framework
GMock frameworkGMock framework
GMock framework
 
Let's talk about Garbage Collection
Let's talk about Garbage CollectionLet's talk about Garbage Collection
Let's talk about Garbage Collection
 
Qemu JIT Code Generator and System Emulation
Qemu JIT Code Generator and System EmulationQemu JIT Code Generator and System Emulation
Qemu JIT Code Generator and System Emulation
 
FreeIPA - Attacking the Active Directory of Linux
FreeIPA - Attacking the Active Directory of LinuxFreeIPA - Attacking the Active Directory of Linux
FreeIPA - Attacking the Active Directory of Linux
 
Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)
 

Similaire à Handling inline assembly in Clang and LLVM

Shellcoding in linux
Shellcoding in linuxShellcoding in linux
Shellcoding in linux
Ajin Abraham
 
E yantra robot abstractions
E yantra robot abstractionsE yantra robot abstractions
E yantra robot abstractions
Akshar Desai
 

Similaire à Handling inline assembly in Clang and LLVM (20)

"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ..."Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
 
Price of an Error
Price of an ErrorPrice of an Error
Price of an Error
 
PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio Meets Octave
PVS-Studio Meets Octave
 
Static analysis and writing C/C++ of high quality code for embedded systems
Static analysis and writing C/C++ of high quality code for embedded systemsStatic analysis and writing C/C++ of high quality code for embedded systems
Static analysis and writing C/C++ of high quality code for embedded systems
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
 
Shellcoding in linux
Shellcoding in linuxShellcoding in linux
Shellcoding in linux
 
Writing Metasploit Plugins
Writing Metasploit PluginsWriting Metasploit Plugins
Writing Metasploit Plugins
 
SFO15-500: VIXL
SFO15-500: VIXLSFO15-500: VIXL
SFO15-500: VIXL
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggy
 
Search for Vulnerabilities Using Static Code Analysis
Search for Vulnerabilities Using Static Code AnalysisSearch for Vulnerabilities Using Static Code Analysis
Search for Vulnerabilities Using Static Code Analysis
 
200 Open Source Projects Later: Source Code Static Analysis Experience
200 Open Source Projects Later: Source Code Static Analysis Experience200 Open Source Projects Later: Source Code Static Analysis Experience
200 Open Source Projects Later: Source Code Static Analysis Experience
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 
E yantra robot abstractions
E yantra robot abstractionsE yantra robot abstractions
E yantra robot abstractions
 
XPDS16: Xen Live Patching - Updating Xen Without Rebooting - Konrad Wilk, Ora...
XPDS16: Xen Live Patching - Updating Xen Without Rebooting - Konrad Wilk, Ora...XPDS16: Xen Live Patching - Updating Xen Without Rebooting - Konrad Wilk, Ora...
XPDS16: Xen Live Patching - Updating Xen Without Rebooting - Konrad Wilk, Ora...
 
zkStudyClub: CirC and Compiling Programs to Circuits
zkStudyClub: CirC and Compiling Programs to CircuitszkStudyClub: CirC and Compiling Programs to Circuits
zkStudyClub: CirC and Compiling Programs to Circuits
 
Assembly language part I
Assembly language part IAssembly language part I
Assembly language part I
 
Assembly language part I
Assembly language part IAssembly language part I
Assembly language part I
 
Java Jit. Compilation and optimization by Andrey Kovalenko
Java Jit. Compilation and optimization by Andrey KovalenkoJava Jit. Compilation and optimization by Andrey Kovalenko
Java Jit. Compilation and optimization by Andrey Kovalenko
 
04 - I love my OS, he protects me (sometimes, in specific circumstances)
04 - I love my OS, he protects me (sometimes, in specific circumstances)04 - I love my OS, he protects me (sometimes, in specific circumstances)
04 - I love my OS, he protects me (sometimes, in specific circumstances)
 
Errors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 librariesErrors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 libraries
 

Plus de Min-Yih Hsu

Plus de Min-Yih Hsu (14)

Debug Information And Where They Come From
Debug Information And Where They Come FromDebug Information And Where They Come From
Debug Information And Where They Come From
 
MCA Daemon: Hybrid Throughput Analysis Beyond Basic Blocks
MCA Daemon: Hybrid Throughput Analysis Beyond Basic BlocksMCA Daemon: Hybrid Throughput Analysis Beyond Basic Blocks
MCA Daemon: Hybrid Throughput Analysis Beyond Basic Blocks
 
How to write a TableGen backend
How to write a TableGen backendHow to write a TableGen backend
How to write a TableGen backend
 
[COSCUP 2021] LLVM Project: The Good, The Bad, and The Ugly
[COSCUP 2021] LLVM Project: The Good, The Bad, and The Ugly[COSCUP 2021] LLVM Project: The Good, The Bad, and The Ugly
[COSCUP 2021] LLVM Project: The Good, The Bad, and The Ugly
 
[TGSA Academic Friday] How To Train Your Dragon - Intro to Modern Compiler Te...
[TGSA Academic Friday] How To Train Your Dragon - Intro to Modern Compiler Te...[TGSA Academic Friday] How To Train Your Dragon - Intro to Modern Compiler Te...
[TGSA Academic Friday] How To Train Your Dragon - Intro to Modern Compiler Te...
 
Paper Study - Demand-Driven Computation of Interprocedural Data Flow
Paper Study - Demand-Driven Computation of Interprocedural Data FlowPaper Study - Demand-Driven Computation of Interprocedural Data Flow
Paper Study - Demand-Driven Computation of Interprocedural Data Flow
 
Paper Study - Incremental Data-Flow Analysis Algorithms by Ryder et al
Paper Study - Incremental Data-Flow Analysis Algorithms by Ryder et alPaper Study - Incremental Data-Flow Analysis Algorithms by Ryder et al
Paper Study - Incremental Data-Flow Analysis Algorithms by Ryder et al
 
Souper-Charging Peepholes with Target Machine Info
Souper-Charging Peepholes with Target Machine InfoSouper-Charging Peepholes with Target Machine Info
Souper-Charging Peepholes with Target Machine Info
 
From V8 to Modern Compilers
From V8 to Modern CompilersFrom V8 to Modern Compilers
From V8 to Modern Compilers
 
Introduction to Khronos SYCL
Introduction to Khronos SYCLIntroduction to Khronos SYCL
Introduction to Khronos SYCL
 
Trace Scheduling
Trace SchedulingTrace Scheduling
Trace Scheduling
 
Polymer Start-Up (SITCON 2016)
Polymer Start-Up (SITCON 2016)Polymer Start-Up (SITCON 2016)
Polymer Start-Up (SITCON 2016)
 
War of Native Speed on Web (SITCON2016)
War of Native Speed on Web (SITCON2016)War of Native Speed on Web (SITCON2016)
War of Native Speed on Web (SITCON2016)
 
From Android NDK To AOSP
From Android NDK To AOSPFrom Android NDK To AOSP
From Android NDK To AOSP
 

Dernier

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 

Dernier (20)

Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Generic or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 

Handling inline assembly in Clang and LLVM

  • 1. Min-Yih “Min” Hsu @ LLVM Dev Meeting 2021 Handling inline assembly 
 in Clang and LLVM
  • 2. about:me “Min” Hsu • Computer Science PhD Candidate in University of California, Irvine • Code owner of M68k LLVM backend • Author of book “LLVM Techniques, Tips and Best Practices” (2021) 2
  • 3. How Inline Assembly is Processed in Clang & LLVM 3
  • 5. Introduction to inline assembly 5 void foo(...) { int sum = 0; bool flag = ...; if (flag) asm ("movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); else sum += 87; } * x86_64 assembly w/ AT&T syntax
  • 6. Introduction to inline assembly 5 void foo(...) { int sum = 0; bool flag = ...; if (flag) asm ("movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); else sum += 87; } * x86_64 assembly w/ AT&T syntax
  • 7. Introduction to inline assembly 5 void foo(...) { int sum = 0; bool flag = ...; if (flag) asm ("movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); else sum += 87; } foo: pushq %rbp movq %rsp, %rbp ... testb $1, -9(%rbp) je LBB0_2 ## InlineAsm Start movl %eax, %ebx addl %ebx, %esi ## InlineAsm End jmp LBB0_3 LBB0_2: movl -8(%rbp), %eax addl $87, %eax movl %eax, -8(%rbp) LBB0_3: popq %rbp retq * x86_64 assembly w/ AT&T syntax
  • 8. Introduction to inline assembly 5 void foo(...) { int sum = 0; bool flag = ...; if (flag) asm ("movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); else sum += 87; } foo: pushq %rbp movq %rsp, %rbp ... testb $1, -9(%rbp) je LBB0_2 ## InlineAsm Start movl %eax, %ebx addl %ebx, %esi ## InlineAsm End jmp LBB0_3 LBB0_2: movl -8(%rbp), %eax addl $87, %eax movl %eax, -8(%rbp) LBB0_3: popq %rbp retq * x86_64 assembly w/ AT&T syntax
  • 9. Introduction to inline assembly Why use inline assembly? 6 void foo(...) { int sum = 0; bool flag = ...; if (flag) asm ("movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); else sum += 87; } * x86_64 assembly w/ AT&T syntax
  • 10. Introduction to inline assembly Why use inline assembly? 6 void foo(...) { int sum = 0; bool flag = ...; if (flag) asm ("movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); else sum += 87; } Performance critical code * x86_64 assembly w/ AT&T syntax
  • 11. Introduction to inline assembly Why use inline assembly? 6 void foo(...) { int sum = 0; bool flag = ...; if (flag) asm ("movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); else sum += 87; } Performance critical code Low-level code e.g. Kernel, firmware * x86_64 assembly w/ AT&T syntax
  • 12. Introduction to inline assembly Why use inline assembly? 6 void foo(...) { int sum = 0; bool flag = ...; if (flag) asm ("movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); else sum += 87; } Performance critical code Low-level code e.g. Kernel, firmware Compiler optimizations “barrier” * x86_64 assembly w/ AT&T syntax
  • 13. Introduction to inline assembly 7 asm (“movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); * x86_64 assembly w/ AT&T syntax
  • 14. Introduction to inline assembly 7 asm (“movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); Assembly code (template) * x86_64 assembly w/ AT&T syntax
  • 15. Introduction to inline assembly 7 asm (“movl %%eax, %%ebxn" "addl %%ebx, %%esi" :::); Assembly code (template) * x86_64 assembly w/ AT&T syntax
  • 16. Introduction to inline assembly Output operands 8 int out_var; asm ("movl %%eax, %%ebxn" "addl %%ebx, %0" : "=r"(out_var) ::); * x86_64 assembly w/ AT&T syntax
  • 17. Introduction to inline assembly Output operands 8 int out_var; asm ("movl %%eax, %%ebxn" "addl %%ebx, %0" : "=r"(out_var) ::); * x86_64 assembly w/ AT&T syntax
  • 18. Introduction to inline assembly Output operands 8 int out_var; asm ("movl %%eax, %%ebxn" "addl %%ebx, %0" : "=r"(out_var) ::); Operand constraints * x86_64 assembly w/ AT&T syntax
  • 19. Introduction to inline assembly Operands constraints 9 int out_var; asm ("movl %%eax, %%ebxn" "addl %%ebx, %0" : "=r"(out_var) ::); * x86_64 assembly w/ AT&T syntax
  • 20. Introduction to inline assembly Operands constraints 9 int out_var; asm ("movl %%eax, %%ebxn" "addl %%ebx, %0" : "=r"(out_var) ::); * x86_64 assembly w/ AT&T syntax ## InlineAsm Start movl %eax, %ebx addl %ebx, %esi ## InlineAsm End
  • 21. Introduction to inline assembly Operands constraints 9 int out_var; asm ("movl %%eax, %%ebxn" "addl %%ebx, %0" : "=r"(out_var) ::); * x86_64 assembly w/ AT&T syntax ## InlineAsm Start movl %eax, %ebx addl %ebx, %esi ## InlineAsm End ## InlineAsm Start movl %eax, %ebx addl %ebx, -8(%ebp) ## InlineAsm End
  • 23. Operand constraints 10 • ‘r’ : General-purpose register operand • ‘i’ : Immediate integer operand • ‘m’ : Memory operand w/ arbitrary addressing mode Target-independent Constraints
  • 24. Operand constraints 10 • ‘r’ : General-purpose register operand • ‘i’ : Immediate integer operand • ‘m’ : Memory operand w/ arbitrary addressing mode Target-independent Constraints • ‘a’ : AL / AH / EAX / RAX • ‘I’ : Integer constant in the range of [0, 31] • ‘N’ : Unsigned 8-bit integer constant X86 Constraints
  • 25. Operand constraints 10 • ‘r’ : General-purpose register operand • ‘i’ : Immediate integer operand • ‘m’ : Memory operand w/ arbitrary addressing mode Target-independent Constraints • ‘a’ : AL / AH / EAX / RAX • ‘I’ : Integer constant in the range of [0, 31] • ‘N’ : Unsigned 8-bit integer constant X86 Constraints • ‘J’ : 16-bit signed integer constant • “Ci” : Constant integers • “Cj” : Constant signed integers that do NOT fi t in 16 bits M68k Constraints
  • 26. Operand constraints 10 • ‘r’ : General-purpose register operand • ‘i’ : Immediate integer operand • ‘m’ : Memory operand w/ arbitrary addressing mode Constraint Modifers Target-independent Constraints • ‘=‘ : This is an output operand • ‘+’ : This is an input / output operand • ‘a’ : AL / AH / EAX / RAX • ‘I’ : Integer constant in the range of [0, 31] • ‘N’ : Unsigned 8-bit integer constant X86 Constraints • ‘J’ : 16-bit signed integer constant • “Ci” : Constant integers • “Cj” : Constant signed integers that do NOT fi t in 16 bits M68k Constraints
  • 27. Introduction to inline assembly Input operands 11 int out_var, in_var; asm ("movl %1, %%ebxn" "addl %%ebx, %0" : “=r"(out_var) : “r”(in_var) :); * x86_64 assembly w/ AT&T syntax
  • 28. Introduction to inline assembly Input operands 11 int out_var, in_var; asm ("movl %1, %%ebxn" "addl %%ebx, %0" : “=r"(out_var) : “r”(in_var) :); * x86_64 assembly w/ AT&T syntax
  • 29. Introduction to inline assembly Input operands 11 int out_var, in_var; asm ("movl %1, %%ebxn" "addl %%ebx, %0" : “=r"(out_var) : “r”(in_var) :); Operand constraints * x86_64 assembly w/ AT&T syntax
  • 30. Introduction to inline assembly Clobber operands 12 int out_var, in_var; asm ("movl %1, %%ebxn" "addl %%ebx, %0" : “=r"(out_var) : “r”(in_var) : “ebx”); * x86_64 assembly w/ AT&T syntax
  • 31. Introduction to inline assembly Clobber operands 12 int out_var, in_var; asm ("movl %1, %%ebxn" "addl %%ebx, %0" : “=r"(out_var) : “r”(in_var) : “ebx”); * x86_64 assembly w/ AT&T syntax
  • 32. For more inline assembly syntax… 13 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
  • 33. Handling inline assembly in Clang & LLVM Background 14
  • 34. Handling inline assembly in Clang & LLVM Background • Most parts of an inline assembly string are simply copied into the fi nal assembly fi le 14
  • 35. Handling inline assembly in Clang & LLVM Background • Most parts of an inline assembly string are simply copied into the fi nal assembly fi le • LLVM needs to “glue” inline assembly operands with the surrounding code 14
  • 36. Handling inline assembly in Clang & LLVM Background • Most parts of an inline assembly string are simply copied into the fi nal assembly fi le • LLVM needs to “glue” inline assembly operands with the surrounding code • Lots of target-speci fi c logics • In both Clang and the backend 14
  • 37. Handling inline assembly in Clang & LLVM Background • Most parts of an inline assembly string are simply copied into the fi nal assembly fi le • LLVM needs to “glue” inline assembly operands with the surrounding code • Lots of target-speci fi c logics • In both Clang and the backend • Target-speci fi c callbacks are scattered in the codebase • Documentation for this part is a little…shy 14
  • 39. Goals Learning inline assembly workflow in Clang / LLVM 15
  • 40. Goals Learning inline assembly workflow in Clang / LLVM A simple guide for backend developers to add inline assembly support 15
  • 41. Outline of target-specific logics in each stage 16 Clang Lowering LLVM IR Machine IR AsmPrinter
  • 42. Outline of target-specific logics in each stage 16 Clang Lowering LLVM IR Machine IR AsmPrinter • Simple validation on operand constraints • Converting constraints
  • 43. Outline of target-specific logics in each stage 16 Clang Lowering LLVM IR Machine IR AsmPrinter • Simple validation on operand constraints • Converting constraints • Classifying constraints • Constraint validations • Lowering the operands
  • 44. Outline of target-specific logics in each stage 16 Clang Lowering LLVM IR Machine IR AsmPrinter • Simple validation on operand constraints • Converting constraints • Classifying constraints • Constraint validations • Lowering the operands Print out di ff erent types of operands
  • 45. Outline of target-specific logics in each stage 17 Clang Lowering LLVM IR Machine IR AsmPrinter • Simple validation on operand constraints • Converting constraints • Classifying constraints • Constraint validations • Lowering the operands Print out di ff erent types of operands
  • 46. Operand constraint validations in Clang 18 bool TargetInfo::validateAsmConstraint(const char *&, ConstraintInfo &) const;
  • 47. Operand constraint validations in Clang 18 bool TargetInfo::validateAsmConstraint(const char *&, ConstraintInfo &) const; bool M68kTargetInfo::validateAsmConstraint(const char *&Name, ConstraintInfo &info) const { switch (*Name) { case 'a': // address register info.setAllowsRegister(); return true; } … }
  • 48. Operand constraint validations in Clang 19 bool TargetInfo::validateAsmConstraint(const char *&, ConstraintInfo &) const; bool M68kTargetInfo::validateAsmConstraint(const char *&Name, ConstraintInfo &info) const { switch (*Name) { case 'a': // address register info.setAllowsRegister(); return true; case 'J': // constant signed 16-bit integer info.setRequiresImmediate(std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); return true; } … }
  • 49. Operand constraint validations in Clang Limitation on immediate value validations 20 void foo() { int32_t x; asm ("move.l %0, %%d1" : : "J" (x)); } * M68k assembly w/ Motorola syntax
  • 50. Operand constraint validations in Clang Limitation on immediate value validations 20 void foo() { int32_t x; asm ("move.l %0, %%d1" : : "J" (x)); } Constant signed 16-bit integer * M68k assembly w/ Motorola syntax
  • 51. Operand constraint validations in Clang Limitation on immediate value validations 20 void foo() { int32_t x; asm ("move.l %0, %%d1" : : "J" (x)); } $ clang -target m68k -fsyntax-only foo.c # No error $ clang -target m68k -emit-llvm foo.c # No error Constant signed 16-bit integer * M68k assembly w/ Motorola syntax
  • 52. Operand constraint validations in Clang Limitation on immediate value validations 20 void foo() { int32_t x; asm ("move.l %0, %%d1" : : "J" (x)); } $ clang -target m68k -fsyntax-only foo.c # No error $ clang -target m68k -emit-llvm foo.c # No error Constant signed 16-bit integer $ clang -target m68k -S foo.c error: constraint 'J' expects an integer constant expression * M68k assembly w/ Motorola syntax
  • 53. Inline assembly in LLVM IR 21 void foo() { const int x = 87; asm ("move.l %0, %%d1" : : "Ci" (x) : "d1"); } C/C++ * M68k assembly w/ Motorola syntax
  • 54. Inline assembly in LLVM IR 21 void foo() { const int x = 87; asm ("move.l %0, %%d1" : : "Ci" (x) : "d1"); } C/C++ call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87) LLVM IR * M68k assembly w/ Motorola syntax
  • 55. Inline assembly in LLVM IR 21 void foo() { const int x = 87; asm ("move.l %0, %%d1" : : "Ci" (x) : "d1"); } C/C++ call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87) LLVM IR * M68k assembly w/ Motorola syntax
  • 56. Inline assembly in LLVM IR 21 void foo() { const int x = 87; asm ("move.l %0, %%d1" : : "Ci" (x) : "d1"); } C/C++ call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87) LLVM IR * M68k assembly w/ Motorola syntax
  • 57. Inline assembly in LLVM IR 21 void foo() { const int x = 87; asm ("move.l %0, %%d1" : : "Ci" (x) : "d1"); } C/C++ call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87) LLVM IR * M68k assembly w/ Motorola syntax
  • 58. Inline assembly in LLVM IR 21 void foo() { const int x = 87; asm ("move.l %0, %%d1" : : "Ci" (x) : "d1"); } C/C++ call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87) LLVM IR * M68k assembly w/ Motorola syntax
  • 59. Outline of target-specific logics in each stage 22 Clang Lowering LLVM IR Machine IR AsmPrinter • Simple validation on operand constraints • Converting constraints • Classifying constraints • Constraint validations • Lowering the operands Print out di ff erent types of operands
  • 60. 23 LLVM IR call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87)
  • 61. 23 LLVM IR SelectionDAG call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87) t2: ch,glue = inlineasm ... "move.l $0, %d1", ..., TargetConstant:i32<87>, Register:i16 $d1
  • 62. 23 LLVM IR SelectionDAG Machine IR call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87) INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1 t2: ch,glue = inlineasm ... "move.l $0, %d1", ..., TargetConstant:i32<87>, Register:i16 $d1
  • 63. 23 LLVM IR SelectionDAG Machine IR call void asm sideeffect "move.l $0, %d1", “^Ci,~{d1}“(i32 87) INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1 t2: ch,glue = inlineasm ... "move.l $0, %d1", ..., TargetConstant:i32<87>, Register:i16 $d1
  • 68. Constraint classification 24 TargetLowering::ConstraintType M68kTargetLowering::getConstraintType(StringRef Constraint) const; • C_RegisterClass • C_Immediate • C_Memory Return: Ex: ’r’ Ex: ‘i’ Ex: ‘m’, ‘Q’ (AArch64)
  • 69. Constraint classification 24 TargetLowering::ConstraintType M68kTargetLowering::getConstraintType(StringRef Constraint) const; • C_RegisterClass • C_Immediate • C_Memory • C_Other Return: Ex: ’r’ Ex: ‘i’ Ex: ‘m’, ‘Q’ (AArch64)
  • 70. Lowering operands 25 getConstraintType Method in XXXTargetLowering Method in XXXISelDAGToDAG Will be invoked
  • 71. Lowering operands 25 getConstraintType getRegForInlineAsmConstraint C_RegisterClass Method in XXXTargetLowering Method in XXXISelDAGToDAG Will be invoked
  • 75. Lowering register operands 26 std::pair<unsigned, const TargetRegisterClass *> TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const;
  • 76. Lowering register operands 26 std::pair<unsigned, const TargetRegisterClass *> TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const; A speci fi c register or 0 if not applicable
  • 77. Lowering register operands 26 std::pair<unsigned, const TargetRegisterClass *> TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const; A speci fi c register or 0 if not applicable Valid register class to select from
  • 78. Lowering register operands M68k Example 27 std::pair<unsigned, const TargetRegisterClass *> M68kTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *, StringRef Constraint, MVT VT) const { switch (Constraint[0]) { case 'a': switch (VT.SimpleTy) { case MVT::i16: return std::make_pair(0U, &M68k::AR16RegClass); } } }
  • 79. Lowering register operands M68k Example 27 std::pair<unsigned, const TargetRegisterClass *> M68kTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *, StringRef Constraint, MVT VT) const { switch (Constraint[0]) { case 'a': switch (VT.SimpleTy) { case MVT::i16: return std::make_pair(0U, &M68k::AR16RegClass); } } }
  • 80. Lowering register operands X86 Example 28 std::pair<unsigned, const TargetRegisterClass *> X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *, StringRef Constraint, MVT VT) const { ... if (Constraint == "Yz") { // First SSE register (%xmm0). switch (VT.SimpleTy) { case MVT::f32: case MVT::i32: return std::make_pair(X86::XMM0, &X86::FR32RegClass); } } }
  • 81. Lowering register operands X86 Example 28 std::pair<unsigned, const TargetRegisterClass *> X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *, StringRef Constraint, MVT VT) const { ... if (Constraint == "Yz") { // First SSE register (%xmm0). switch (VT.SimpleTy) { case MVT::f32: case MVT::i32: return std::make_pair(X86::XMM0, &X86::FR32RegClass); } } }
  • 82. Lowering immediate / other operands 29 void TargetLowering:: LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, std::vector<SDValue> &Ops, SelectionDAG &DAG) const;
  • 83. Lowering immediate / other operands M68k Example 30 void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, std::vector<SDValue> &Ops, SelectionDAG &DAG) const { switch (Constraint[0]) { case 'J': { // constant signed 16-bit integer } } }
  • 84. Lowering immediate / other operands M68k Example 31 void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, std::vector<SDValue> &Ops, SelectionDAG &DAG) const { switch (Constraint[0]) { case 'J': { // constant signed 16-bit integer if (auto *C = dyn_cast<ConstantSDNode>(Op)) { int64_t Val = C->getSExtValue(); } } } }
  • 85. Lowering immediate / other operands M68k Example 32 void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, std::vector<SDValue> &Ops, SelectionDAG &DAG) const { switch (Constraint[0]) { case 'J': { // constant signed 16-bit integer if (auto *C = dyn_cast<ConstantSDNode>(Op)) { int64_t Val = C->getSExtValue(); if (isInt<16>(Val)) { Ops.push_back(Op); return; } } } } }
  • 86. Lowering memory operands Memory constraint classi fi cation 33 unsigned TargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const;
  • 87. Lowering memory operands Memory constraint classi fi cation 33 unsigned TargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const; Return:
  • 88. Lowering memory operands Memory constraint classi fi cation 33 unsigned TargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const; • InlineAsm::Constraint_m • InlineAsm::Constraint_o • InlineAsm::Constraint_v Return: Generic memory constraints
  • 89. Lowering memory operands Memory constraint classi fi cation 33 unsigned TargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const; • InlineAsm::Constraint_m • InlineAsm::Constraint_o • InlineAsm::Constraint_v Return: • InlineAsm::Constraint_A • InlineAsm::Constraint_Q Generic memory constraints Target-speci fi c constraints!
  • 90. Lowering memory operands Memory constraint classi fi cation — RISCV Example 34 unsigned RISCVTargetLowering:: getInlineAsmMemConstraint(StringRef ConstraintCode) const { switch (ConstraintCode[0]) { case 'A': return InlineAsm::Constraint_A; ... } ... }
  • 91. Lowering memory operands 35 bool SelectionDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps);
  • 92. Lowering memory operands RISCV Example 36 bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { switch (ConstraintID) { case InlineAsm::Constraint_A: OutOps.push_back(Op); return false; default: break; } return true; }
  • 93. Lowering memory operands Complex addressing mode — X86 Example 37 bool X86DAGToDAGISel:: SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { SDValue Op0, Op1, Op2, Op3, Op4; switch (ConstraintID) { case InlineAsm::Constraint_m: // memory if (!selectAddr(nullptr, Op, Op0, Op1, Op2, Op3, Op4)) return true; break; } OutOps.insert(OutOps.end(), {Op0, Op1, Op2, Op3, Op4}); return false; }
  • 94. Lowering memory operands Complex addressing mode — X86 Example 37 bool X86DAGToDAGISel:: SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { SDValue Op0, Op1, Op2, Op3, Op4; switch (ConstraintID) { case InlineAsm::Constraint_m: // memory if (!selectAddr(nullptr, Op, Op0, Op1, Op2, Op3, Op4)) return true; break; } OutOps.insert(OutOps.end(), {Op0, Op1, Op2, Op3, Op4}); return false; }
  • 95. Outline of target-specific logics in each stage 38 Clang Lowering LLVM IR Machine IR AsmPrinter • Simple validation on operand constraints • Converting constraints • Classifying constraints • Constraint validations • Lowering the operands Print out di ff erent types of operands
  • 96. 39 Machine IR INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1
  • 97. 39 Machine IR INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1
  • 98. 39 Machine IR INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1 move.l #87, %d1
  • 99. 39 Machine IR INLINEASM &"move.l $0, %d1", ..., /* imm */ 87, /* clobber */ $d1 move.l 87, %d1 move.l #87, %d1
  • 100. Printing asm operands 40 bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *, raw_ostream &O); bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *, raw_ostream &O);
  • 101. Printing non-memory asm operands M68k Example 41 void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS) { const MachineOperand &MO = MI->getOperand(OpNum); switch (MO.getType()) { case MachineOperand::MO_Register: OS << "%" << M68kInstPrinter::getRegisterName(MO.getReg()); break; case MachineOperand::MO_Immediate: OS << '#' << MO.getImm(); break; ... } }
  • 102. Printing non-memory asm operands M68k Example 41 void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS) { const MachineOperand &MO = MI->getOperand(OpNum); switch (MO.getType()) { case MachineOperand::MO_Register: OS << "%" << M68kInstPrinter::getRegisterName(MO.getReg()); break; case MachineOperand::MO_Immediate: OS << '#' << MO.getImm(); break; ... } }
  • 103. Printing non-memory asm operands M68k Example 41 void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS) { const MachineOperand &MO = MI->getOperand(OpNum); switch (MO.getType()) { case MachineOperand::MO_Register: OS << "%" << M68kInstPrinter::getRegisterName(MO.getReg()); break; case MachineOperand::MO_Immediate: OS << '#' << MO.getImm(); break; ... } }
  • 105. Advanced topics Converting constraints in Clang Asm dialects Operand modifiers Multi-alternative constraints Constraint weights Turn (simple) inline asm into LLVM code 43
  • 106. Thank you! 44 GitHub: mshockwave Email: minyihh@uci.edu 25% book discount code: 25MINLLVM Redeem: Nov 15 ~ Nov 20, 2021
  • 108. Converting constraints in Clang 46 An operand constraint is assumed to have only a single character by default
  • 109. Converting constraints in Clang 46 An operand constraint is assumed to have only a single character by default Example: “Ci”
  • 110. Converting constraints in Clang 46 An operand constraint is assumed to have only a single character by default Example: “Ci” -> “^Ci”
  • 111. Converting constraints in Clang 46 std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const override { if (*Constraint == 'C') // Two-character constraint; add "^" hint for later parsing return std::string("^") + std::string(Constraint++, 2); return std::string(1, *Constraint); } An operand constraint is assumed to have only a single character by default Example: “Ci” -> “^Ci”
  • 112. Operand constraint validations in Clang Limitation on immediate value validations (cont’d) 47 bool M68kTargetInfo::validateAsmConstraint(const char *&Name, ConstraintInfo &info) const { switch (*Name) { … case 'C': ++Name; switch (*Name) { case 'i': // constant integer case 'j': // integer constant that doesn't fit in 16 bits info.setRequiresImmediate(); return true; } break; } … }