2
votes

For my PIC Backend, I want 'int' to be 16 bits. How can I / my target tell clang what should be the size of 'int'? Defining 16-bit registers only seems not sufficient.

Currently "clang -O2 -emit-llvm -target pic" converts

int foo(int a, int b) { return a + b; }

to this IR code, using 32-bit integers:

; ModuleID = '../test/sum.c'
source_filename = "../test/sum.c"
target datalayout = "e-m:e-p:16:16-i16:16-a:0:16-n16-S16"
target triple = "pic"

; Function Attrs: norecurse nounwind readnone
define i32 @foo(i32 %a, i32 %b) local_unnamed_addr #0 {
entry:
  %add = add nsw i32 %b, %a
  ret i32 %add
}

attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.ident = !{!0}

!0 = !{!"clang version 4.0.0 (http://llvm.org/git/clang.git 92920e1616528c259756dd8190d4a47058fae127) (http://llvm.org/git/llvm.git 7ca31361200d6bc8a75fa06f112083a8be544287)"}

This may or may not be the cause of the "Return operand #1 has unhandled type i16" message I described in PIC Backend: 16-bit registers / return type. However I should probably get the type used in clang's output correct before turning to other problems.

2

2 Answers

1
votes

SOLVED: clang takes the size of int (and other types) from its own Target, defined in clang/lib/Basics/Targets.cpp. The native size setting "-n16" is not sufficient to override the (default?) i32 setting. Instead:

IntWidth = 32;
IntAlign = 32;

in my target's constructor does the trick.

This also solves the strange 'unhandled return type i16' issue. Don't know why.

-1
votes

I strongly suggest making a habit of using the ISO/IEC 9899 include files <stdint.h> and <stdbool.h>. In your case, you can then declare

int16_t foo(int16_t a, int16_t b) { return a + b; }

and you are guaranteed that the variables and return values are 16-bit signed integers, irrespective of the target processor. Look at the file contents, or the ISO document appendix B.17 (search for ISO/IEC 9899 and you will find the pdf document easily), to see all the type options.

These include files (together with prefixes on variable names like u16foo and i32bar to clarify to me the size and signedness of identifiers) have saved my skin too many times to count.