Skip to content

Commit 5f99422

Browse files
committed
Support LLVM 15 and 16, opaque pointers
This patch adds support for LLVM 15 and 16 by adding support for opaque pointers, which are described in https://llvm.org/docs/OpaquePointers.html. I have also added a test case involving LLVM bitcode using opaque pointers to kick the tires and ensure that the basics work as expected. For the most part, this is a straightforward process, as most uses of pointer types in SAW already do not care about pointee types. There are some exceptions, however: * The `typeOfSetupValue` function, as well as several places that use this function, scrutinize pointee types of pointers, which would appear to fly in the face of opaque pointers. I attempt to explain in #1876 which this is actually OK for now (although a bit awkward). * The `llvm_boilerplate`/skeleton machinery does not support opaque pointers at all. See #1877. * The `llvm_fresh_expanded_val` command does not support opaque pointers at all. See #1879. This patch also bumps the following submodules to bring in support for opaque pointers: * `llvm-pretty`: GaloisInc/llvm-pretty#110 * `llvm-pretty-bc-parser`: GaloisInc/llvm-pretty-bc-parser#221 * `crucible`: GaloisInc/crucible#1085 This also bumps the `what4` submodule to bring in the changes from GaloisInc/what4#234. This isn't necessary to support opaque pointers, but it _is_ necessary to support a build plan involving `tasty-sugar-2.2.*`, which `llvm-pretty-bc-parser`'s test suite now requires.
1 parent 4dfd2a4 commit 5f99422

File tree

17 files changed

+77
-24
lines changed

17 files changed

+77
-24
lines changed

CHANGES.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
see the `mir_*` commands documented in the
100100
[SAW manual](https://github.com/GaloisInc/saw-script/blob/master/doc/manual/manual.md).
101101

102-
* Support LLVM versions up to 14.
102+
* Support LLVM versions up to 16.
103103

104104
# Version 0.9
105105

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ SAW can analyze LLVM programs (usually derived from C, but potentially
7272
for other languages). The only tool strictly required for this is a
7373
compiler that can generate LLVM bitcode, such as `clang`. However,
7474
having the full LLVM tool suite available can be useful. We have tested
75-
SAW with LLVM and `clang` versions from 3.5 to 14.0, as well as the
75+
SAW with LLVM and `clang` versions from 3.5 to 16.0, as well as the
7676
version of `clang` bundled with Apple Xcode. We welcome bug reports on
7777
any failure to parse bitcode from LLVM versions in that range.
7878

deps/crucible

Submodule crucible updated 49 files

deps/llvm-pretty

deps/what4

doc/manual/manual.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1580,7 +1580,7 @@ The resulting `LLVMModule` can be passed into the various functions
15801580
described below to perform analysis of specific LLVM functions.
15811581

15821582
The LLVM bitcode parser should generally work with LLVM versions between
1583-
3.5 and 14.0, though it may be incomplete for some versions. Debug
1583+
3.5 and 16.0, though it may be incomplete for some versions. Debug
15841584
metadata has changed somewhat throughout that version range, so is the
15851585
most likely case of incompleteness. We aim to support every version
15861586
after 3.5, however, so report any parsing failures as [on

heapster-saw/src/Verifier/SAW/Heapster/LLVMGlobalConst.hs

+4-3
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,10 @@ translateLLVMConstExpr w (L.ConstGEP _ _ _ (L.Typed tp ptr) ixs) =
182182
translateLLVMValue w tp ptr >>= \ptr_trans ->
183183
translateLLVMGEP w tp ptr_trans ixs
184184
translateLLVMConstExpr w (L.ConstConv L.BitCast
185-
(L.Typed tp@(L.PtrTo _) v) (L.PtrTo _)) =
186-
-- A bitcast from one LLVM pointer type to another is a no-op for us
187-
translateLLVMValue w tp v
185+
(L.Typed fromTp v) toTp)
186+
| L.isPointer fromTp && L.isPointer toTp
187+
= -- A bitcast from one LLVM pointer type to another is a no-op for us
188+
translateLLVMValue w fromTp v
188189
translateLLVMConstExpr _ ce =
189190
traceAndZeroM ("translateLLVMConstExpr does not yet handle:\n"
190191
++ ppLLVMConstExpr ce)

intTests/test1132-opaque/Makefile

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# NB: Ensure that clang-15 or later is used so that the resulting LLVM bitcode
2+
# uses opaque pointers.
3+
CC = clang
4+
CFLAGS = -g -emit-llvm -frecord-command-line -O0
5+
6+
all: test.bc
7+
8+
test.bc: test.c
9+
$(CC) $(CFLAGS) -c $< -o $@
10+
11+
.PHONY: clean
12+
clean:
13+
rm -f test.bc

intTests/test1132-opaque/test.bc

3.36 KB
Binary file not shown.

intTests/test1132-opaque/test.c

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
4+
void f(uint8_t **x) {
5+
*x = malloc(sizeof(uint8_t));
6+
**x = 42;
7+
}

intTests/test1132-opaque/test.saw

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
bc <- llvm_load_module "test.bc";
2+
3+
let f_contract = do {
4+
x <- llvm_alloc (llvm_pointer (llvm_int 8));
5+
llvm_execute_func [x];
6+
p <- llvm_alloc (llvm_int 8);
7+
llvm_points_to x p;
8+
llvm_points_to p (llvm_term {{ 42 : [8] }});
9+
};
10+
11+
llvm_verify bc "f" [] false f_contract abc;

intTests/test1132-opaque/test.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# A variant of test1132 that instead uses opaque pointers to ensure that the
2+
# basics of SAW work in an opaque pointer context.
3+
set -e
4+
5+
$SAW test.saw

src/SAWScript/Crucible/LLVM/Builtins.hs

+11-2
Original file line numberDiff line numberDiff line change
@@ -2124,15 +2124,24 @@ cryptolTypeOfActual dl mt =
21242124
do cty <- cryptolTypeOfActual dl ty
21252125
return $ Cryptol.tSeq (Cryptol.tNum n) cty
21262126
Crucible.PtrType _ ->
2127-
return $ Cryptol.tWord (Cryptol.tNum (Crucible.ptrBitwidth dl))
2127+
return cryptolPtrType
2128+
Crucible.PtrOpaqueType ->
2129+
return cryptolPtrType
21282130
Crucible.StructType si ->
21292131
do let memtypes = V.toList (Crucible.siFieldTypes si)
21302132
ctys <- traverse (cryptolTypeOfActual dl) memtypes
21312133
case ctys of
21322134
[cty] -> return cty
21332135
_ -> return $ Cryptol.tTuple ctys
2134-
_ ->
2136+
Crucible.X86_FP80Type ->
21352137
Nothing
2138+
Crucible.VecType{} ->
2139+
Nothing
2140+
Crucible.MetadataType ->
2141+
Nothing
2142+
where
2143+
cryptolPtrType :: Cryptol.Type
2144+
cryptolPtrType = Cryptol.tWord (Cryptol.tNum (Crucible.ptrBitwidth dl))
21362145

21372146
-- | Generate a fresh variable term. The name will be used when
21382147
-- pretty-printing the variable in debug output.

src/SAWScript/Crucible/LLVM/Override.hs

+11-5
Original file line numberDiff line numberDiff line change
@@ -1241,9 +1241,15 @@ diffMemTypes x0 y0 =
12411241
(Crucible.IntType x, Crucible.IntType y) | x == y -> []
12421242
(Crucible.FloatType, Crucible.FloatType) -> []
12431243
(Crucible.DoubleType, Crucible.DoubleType) -> []
1244-
(Crucible.PtrType{}, Crucible.PtrType{}) -> []
1245-
(Crucible.IntType w, Crucible.PtrType{}) | w == wptr -> []
1246-
(Crucible.PtrType{}, Crucible.IntType w) | w == wptr -> []
1244+
(_, _)
1245+
| Crucible.isPointerMemType x0 && Crucible.isPointerMemType y0 ->
1246+
[]
1247+
(Crucible.IntType w, _)
1248+
| Crucible.isPointerMemType y0 && w == wptr ->
1249+
[]
1250+
(_, Crucible.IntType w)
1251+
| Crucible.isPointerMemType x0 && w == wptr ->
1252+
[]
12471253
(Crucible.ArrayType xn xt, Crucible.ArrayType yn yt)
12481254
| xn == yn ->
12491255
[ (Nothing : path, l , r) | (path, l, r) <- diffMemTypes xt yt ]
@@ -1314,15 +1320,15 @@ matchArg opts sc cc cs prepost md actual expectedTy expected =
13141320
(V.toList (Crucible.fiType <$> Crucible.siFields fields))
13151321
zs ]
13161322

1317-
(Crucible.LLVMValInt blk off, Crucible.PtrType _, SetupElem () v i) ->
1323+
(Crucible.LLVMValInt blk off, _, SetupElem () v i) | Crucible.isPointerMemType expectedTy ->
13181324
do let tyenv = MS.csAllocations cs
13191325
nameEnv = MS.csTypeNames cs
13201326
delta <- exceptToFail $ resolveSetupElemOffset cc tyenv nameEnv v i
13211327
off' <- liftIO $ W4.bvSub sym off
13221328
=<< W4.bvLit sym (W4.bvWidth off) (Crucible.bytesToBV (W4.bvWidth off) delta)
13231329
matchArg opts sc cc cs prepost md (Crucible.LLVMValInt blk off') expectedTy v
13241330

1325-
(Crucible.LLVMValInt blk off, Crucible.PtrType _, SetupField () v n) ->
1331+
(Crucible.LLVMValInt blk off, _, SetupField () v n) | Crucible.isPointerMemType expectedTy ->
13261332
do let tyenv = MS.csAllocations cs
13271333
nameEnv = MS.csTypeNames cs
13281334
fld <- exceptToFail $

src/SAWScript/Crucible/LLVM/ResolveSetupValue.hs

+7-6
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,8 @@ typeOfSetupValue cc env nameEnv val =
473473

474474
SetupCast () v ltp ->
475475
do memTy <- typeOfSetupValue cc env nameEnv v
476-
case memTy of
477-
Crucible.PtrType _symTy ->
476+
if Crucible.isPointerMemType memTy
477+
then
478478
case let ?lc = lc in Crucible.liftMemType (L.PtrTo ltp) of
479479
Left err -> throwError $ unlines
480480
[ "typeOfSetupValue: invalid type " ++ show ltp
@@ -483,10 +483,11 @@ typeOfSetupValue cc env nameEnv val =
483483
]
484484
Right mt -> pure mt
485485

486-
_ -> throwError $ unwords $
487-
[ "typeOfSetupValue: tried to cast the type of a non-pointer value"
488-
, "actual type of value: " ++ show memTy
489-
]
486+
else
487+
throwError $ unwords $
488+
[ "typeOfSetupValue: tried to cast the type of a non-pointer value"
489+
, "actual type of value: " ++ show memTy
490+
]
490491

491492
SetupElem () v i -> do
492493
do memTy <- typeOfSetupValue cc env nameEnv v

src/SAWScript/Crucible/LLVM/X86.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,7 @@ setArgs env tyenv nameEnv args
11581158
let
11591159
setRegSetupValue rs (reg, sval) =
11601160
exceptToFail (typeOfSetupValue cc tyenv nameEnv sval) >>= \case
1161-
C.LLVM.PtrType _ -> do
1161+
ty | C.LLVM.isPointerMemType ty -> do
11621162
val <- C.LLVM.unpackMemValue sym (C.LLVM.LLVMPointerRepr $ knownNat @64)
11631163
=<< resolveSetupVal cc mem env tyenv nameEnv sval
11641164
setReg reg val rs

0 commit comments

Comments
 (0)