SlideShare a Scribd company logo
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;


}


…


}

More Related Content

What's hot

Play with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniquePlay with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit Technique
Angel Boy
 
Linux SMEP bypass techniques
Linux SMEP bypass techniquesLinux SMEP bypass techniques
Linux SMEP bypass techniques
Vitaly Nikolenko
 
MacOS memory allocator (libmalloc) Exploitation
MacOS memory allocator (libmalloc) ExploitationMacOS memory allocator (libmalloc) Exploitation
MacOS memory allocator (libmalloc) Exploitation
Angel Boy
 
LLVM Instruction Selection
LLVM Instruction SelectionLLVM Instruction Selection
LLVM Instruction Selection
Shiva Chen
 
Dive into ROP - a quick introduction to Return Oriented Programming
Dive into ROP - a quick introduction to Return Oriented ProgrammingDive into ROP - a quick introduction to Return Oriented Programming
Dive into ROP - a quick introduction to Return Oriented Programming
Saumil Shah
 
Linux Binary Exploitation - Return-oritend Programing
Linux Binary Exploitation - Return-oritend ProgramingLinux Binary Exploitation - Return-oritend Programing
Linux Binary Exploitation - Return-oritend Programing
Angel Boy
 
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
Adrian Huang
 
Memory Mapping Implementation (mmap) in Linux Kernel
Memory Mapping Implementation (mmap) in Linux KernelMemory Mapping Implementation (mmap) in Linux Kernel
Memory Mapping Implementation (mmap) in Linux Kernel
Adrian Huang
 
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
National Cheng Kung University
 
Linux Memory Management
Linux Memory ManagementLinux Memory Management
Linux Memory ManagementNi Zo-Ma
 
Virtual machine and javascript engine
Virtual machine and javascript engineVirtual machine and javascript engine
Virtual machine and javascript engine
Duoyi Wu
 
OWASP AppSecCali 2015 - Marshalling Pickles
OWASP AppSecCali 2015 - Marshalling PicklesOWASP AppSecCali 2015 - Marshalling Pickles
OWASP AppSecCali 2015 - Marshalling Pickles
Christopher Frohoff
 
Linux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflowLinux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflow
Angel Boy
 
Process Address Space: The way to create virtual address (page table) of user...
Process Address Space: The way to create virtual address (page table) of user...Process Address Space: The way to create virtual address (page table) of user...
Process Address Space: The way to create virtual address (page table) of user...
Adrian Huang
 
Return to dlresolve
Return to dlresolveReturn to dlresolve
Return to dlresolve
Angel Boy
 
Linux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledgeLinux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledge
Angel Boy
 
Linux kernel debugging
Linux kernel debuggingLinux kernel debugging
Linux kernel debugging
libfetion
 
[若渴]Study on Side Channel Attacks and Countermeasures
[若渴]Study on Side Channel Attacks and Countermeasures [若渴]Study on Side Channel Attacks and Countermeasures
[若渴]Study on Side Channel Attacks and Countermeasures
Aj MaChInE
 
Instruction Combine in LLVM
Instruction Combine in LLVMInstruction Combine in LLVM
Instruction Combine in LLVM
Wang Hsiangkai
 
Make ARM Shellcode Great Again
Make ARM Shellcode Great AgainMake ARM Shellcode Great Again
Make ARM Shellcode Great Again
Saumil Shah
 

What's hot (20)

Play with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniquePlay with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit Technique
 
Linux SMEP bypass techniques
Linux SMEP bypass techniquesLinux SMEP bypass techniques
Linux SMEP bypass techniques
 
MacOS memory allocator (libmalloc) Exploitation
MacOS memory allocator (libmalloc) ExploitationMacOS memory allocator (libmalloc) Exploitation
MacOS memory allocator (libmalloc) Exploitation
 
LLVM Instruction Selection
LLVM Instruction SelectionLLVM Instruction Selection
LLVM Instruction Selection
 
Dive into ROP - a quick introduction to Return Oriented Programming
Dive into ROP - a quick introduction to Return Oriented ProgrammingDive into ROP - a quick introduction to Return Oriented Programming
Dive into ROP - a quick introduction to Return Oriented Programming
 
Linux Binary Exploitation - Return-oritend Programing
Linux Binary Exploitation - Return-oritend ProgramingLinux Binary Exploitation - Return-oritend Programing
Linux Binary Exploitation - Return-oritend Programing
 
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
 
Memory Mapping Implementation (mmap) in Linux Kernel
Memory Mapping Implementation (mmap) in Linux KernelMemory Mapping Implementation (mmap) in Linux Kernel
Memory Mapping Implementation (mmap) in Linux Kernel
 
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
 
Linux Memory Management
Linux Memory ManagementLinux Memory Management
Linux Memory Management
 
Virtual machine and javascript engine
Virtual machine and javascript engineVirtual machine and javascript engine
Virtual machine and javascript engine
 
OWASP AppSecCali 2015 - Marshalling Pickles
OWASP AppSecCali 2015 - Marshalling PicklesOWASP AppSecCali 2015 - Marshalling Pickles
OWASP AppSecCali 2015 - Marshalling Pickles
 
Linux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflowLinux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflow
 
Process Address Space: The way to create virtual address (page table) of user...
Process Address Space: The way to create virtual address (page table) of user...Process Address Space: The way to create virtual address (page table) of user...
Process Address Space: The way to create virtual address (page table) of user...
 
Return to dlresolve
Return to dlresolveReturn to dlresolve
Return to dlresolve
 
Linux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledgeLinux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledge
 
Linux kernel debugging
Linux kernel debuggingLinux kernel debugging
Linux kernel debugging
 
[若渴]Study on Side Channel Attacks and Countermeasures
[若渴]Study on Side Channel Attacks and Countermeasures [若渴]Study on Side Channel Attacks and Countermeasures
[若渴]Study on Side Channel Attacks and Countermeasures
 
Instruction Combine in LLVM
Instruction Combine in LLVMInstruction Combine in LLVM
Instruction Combine in LLVM
 
Make ARM Shellcode Great Again
Make ARM Shellcode Great AgainMake ARM Shellcode Great Again
Make ARM Shellcode Great Again
 

Similar to Handling inline assembly in Clang and LLVM

"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 ...
PVS-Studio
 
Price of an Error
Price of an ErrorPrice of an Error
Price of an Error
Andrey Karpov
 
PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio Meets Octave
PVS-Studio Meets Octave
PVS-Studio
 
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
Andrey Karpov
 
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
PVS-Studio
 
Shellcoding in linux
Shellcoding in linuxShellcoding in linux
Shellcoding in linuxAjin Abraham
 
Writing Metasploit Plugins
Writing Metasploit PluginsWriting Metasploit Plugins
Writing Metasploit Plugins
amiable_indian
 
SFO15-500: VIXL
SFO15-500: VIXLSFO15-500: VIXL
SFO15-500: VIXL
Linaro
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggy
Andrey Karpov
 
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
Andrey Karpov
 
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
Andrey Karpov
 
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...
PVS-Studio
 
E yantra robot abstractions
E yantra robot abstractionsE yantra robot abstractions
E yantra robot abstractionsAkshar Desai
 
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...
The Linux Foundation
 
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
Alex Pruden
 
Assembly language part I
Assembly language part IAssembly language part I
Assembly language part I
Mohammed A. Imran
 
Assembly language part I
Assembly language part IAssembly language part I
Assembly language part I
n|u - The Open Security Community
 
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
Valeriia Maliarenko
 
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)
Alexandre Moneger
 
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
PVS-Studio
 

Similar to 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
 

More from Min-Yih Hsu

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
Min-Yih Hsu
 
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
Min-Yih Hsu
 
How to write a TableGen backend
How to write a TableGen backendHow to write a TableGen backend
How to write a TableGen backend
Min-Yih Hsu
 
[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
Min-Yih Hsu
 
[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...
Min-Yih Hsu
 
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
Min-Yih Hsu
 
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
Min-Yih Hsu
 
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
Min-Yih Hsu
 
From V8 to Modern Compilers
From V8 to Modern CompilersFrom V8 to Modern Compilers
From V8 to Modern Compilers
Min-Yih Hsu
 
Introduction to Khronos SYCL
Introduction to Khronos SYCLIntroduction to Khronos SYCL
Introduction to Khronos SYCL
Min-Yih Hsu
 
Trace Scheduling
Trace SchedulingTrace Scheduling
Trace Scheduling
Min-Yih Hsu
 
Polymer Start-Up (SITCON 2016)
Polymer Start-Up (SITCON 2016)Polymer Start-Up (SITCON 2016)
Polymer Start-Up (SITCON 2016)
Min-Yih Hsu
 
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)
Min-Yih Hsu
 
From Android NDK To AOSP
From Android NDK To AOSPFrom Android NDK To AOSP
From Android NDK To AOSP
Min-Yih Hsu
 

More from 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
 

Recently uploaded

Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
WSO2
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
e20449
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
Matt Welsh
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 

Recently uploaded (20)

Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 

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; } … }