Skip to content
This repository was archived by the owner on Jun 1, 2020. It is now read-only.

LLVM Note: Control flow & Type casting

林子篆 edited this page Mar 7, 2020 · 1 revision

Control flow

br i1 %cond, label %iftrue, label %iffalse

br use %cond(type i1, represent boolean value) detecting jumps to %iftrue or %iffalse

ref

Ref to issue for old design: #67

pattern1Matched:
  %0 = icmp eq i32 %matched, %pattern1
  br i1 %0, label %pattern1Matched, label %pattern2Matched
  ; pattern1
  br label %end
pattern2Matched:
  %1 = icmp eq i32 %matched, %pattern2
  br i1 %1, label %pattern2Matched, label %restPattern
  ; pattern 2
  br label %end
restPattern:
  ; rest pattern
  br label %end
end:
  ; leave match rule

for elz code like:

e: int = 10
match e {
  1 => {
    // pattern 1
  },
  2 => {
    // pattern 2
  },
  _ => {
    // rest pattern
  }
}

LLVM IR select is for value, for example a c++ code:

auto v = c ? 1 : 0;

Mapping LLVM code might be:

%v = alloca i32
%0 = select i1 %c, i32 1, i32 0 
store i32 %0, i32* %v

clang switch

c++

int main() {
  int i = 0;

  switch (i) {
  case 0:
    break;
  case 1:
    break;
  case 2:
    break;
  default:
    break;
  }

  int j = i;
}

llvm

define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  %3 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  store i32 0, i32* %2, align 4
  %4 = load i32, i32* %2, align 4
  switch i32 %4, label %8 [
    i32 0, label %5
    i32 1, label %6
    i32 2, label %7
  ]

; <label>:5:                                      ; preds = %0
  br label %9

; <label>:6:                                      ; preds = %0
  br label %9

; <label>:7:                                      ; preds = %0
  br label %9

; <label>:8:                                      ; preds = %0
  br label %9

; <label>:9:                                      ; preds = %8, %7, %6, %5
  %10 = load i32, i32* %2, align 4
  store i32 %10, i32* %3, align 4
  %11 = load i32, i32* %1, align 4
  ret i32 %11
}

Type casting

trunc

Syntax: <result> = trunc <ty> <value> to <ty2> ; yields ty2

The ‘trunc’ instruction takes a value to trunc, and a type to trunc it to. Both types must be of integer types or vectors of the same number of integers. The bit size of the value must be larger than the bit size of the destination type, ty2. Equal sized types are not allowed.

The ‘trunc’ instruction truncates the high order bits in value and converts the remaining bits to ty2. Since the source size must be larger than the destination size, trunc cannot be a no-op cast. It will always truncate bits.

%X = trunc i32 257 to i8                        ; yields i8:1
%Y = trunc i32 123 to i1                        ; yields i1:true
%Z = trunc i32 122 to i1                        ; yields i1:false
%W = trunc <2 x i16> <i16 8, i16 7> to <2 x i8> ; yields <i8 8, i8 7>

zext

Syntax: <result> = zext <ty> <value> to <ty2> ; yields ty2

The ‘zext’ instruction takes a value to cast, and a type to cast it to. Both types must be of integer types or vectors of the same number of integers. The bit size of the value must be smaller than the bit size of the destination type, ty2.

The zext fills the high order bits of the value with zero bits until it reaches the size of the destination type, ty2.

When zero extending from i1, the result will always be either 0 or 1.

%X = zext i32 257 to i64              ; yields i64:257
%Y = zext i1 true to i32              ; yields i32:1
%Z = zext <2 x i16> <i16 8, i16 7> to <2 x i32> ; yields <i32 8, i32 7>

Clone this wiki locally